]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/gc: add backend ginscmp function to emit a comparison
authorRuss Cox <rsc@golang.org>
Wed, 6 May 2015 16:28:19 +0000 (12:28 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 12 May 2015 17:54:57 +0000 (17:54 +0000)
This lets us abstract away which arguments can be constants and so on
and lets the back ends reverse the order of arguments if that helps.

Change-Id: I283ec1d694f2dd84eba22e5eb4aad78a2d2d9eb0
Reviewed-on: https://go-review.googlesource.com/9810
Reviewed-by: David Chase <drchase@google.com>
14 files changed:
src/cmd/5g/cgen.go
src/cmd/5g/galign.go
src/cmd/5g/ggen.go
src/cmd/6g/galign.go
src/cmd/6g/gsubr.go
src/cmd/7g/galign.go
src/cmd/7g/gsubr.go
src/cmd/8g/galign.go
src/cmd/8g/gsubr.go
src/cmd/9g/galign.go
src/cmd/9g/gsubr.go
src/cmd/internal/gc/cgen.go
src/cmd/internal/gc/gen.go
src/cmd/internal/gc/go.go

index 2e922391cb8271606b4804663b2a2f0bb07539b3..c0d7651584b43614f7ebd48701d38de072f517d8 100644 (file)
@@ -53,28 +53,6 @@ func igenindex(n *gc.Node, res *gc.Node, bounded bool) *obj.Prog {
        return cgenindex(n, res, bounded)
 }
 
-func gencmp0(n *gc.Node, t *gc.Type, o int, likely int, to *obj.Prog) {
-       var n1 gc.Node
-
-       gc.Regalloc(&n1, t, nil)
-       gc.Cgen(n, &n1)
-       a := optoas(gc.OCMP, t)
-       if a != arm.ACMP {
-               var n2 gc.Node
-               gc.Nodconst(&n2, t, 0)
-               var n3 gc.Node
-               gc.Regalloc(&n3, t, nil)
-               gmove(&n2, &n3)
-               gins(a, &n1, &n3)
-               gc.Regfree(&n3)
-       } else {
-               gins(arm.ATST, &n1, nil)
-       }
-       a = optoas(o, t)
-       gc.Patch(gc.Gbranch(a, t, likely), to)
-       gc.Regfree(&n1)
-}
-
 func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
        // determine alignment.
        // want to avoid unaligned access, so have to use
index 3c8ba519ebc120bf709300970a994c6f3efca31b..55782e1dae83b835876c00e236afcbc12a294eb5 100644 (file)
@@ -65,6 +65,7 @@ func main() {
        gc.Thearch.Expandchecks = expandchecks
        gc.Thearch.Getg = getg
        gc.Thearch.Gins = gins
+       gc.Thearch.Ginscmp = ginscmp
        gc.Thearch.Ginscon = ginscon
        gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Gmove = gmove
index 0cf0d9299c5895a76ec5c66249ffa7e1f3096418..ade4bd60961606b2f683425e50a7b1a0d1614f08 100644 (file)
@@ -479,6 +479,24 @@ func ginscon(as int, c int64, n *gc.Node) {
        gc.Regfree(&n2)
 }
 
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+       var r1, r2, g1, g2 gc.Node
+       gc.Regalloc(&r1, t, n1)
+       gc.Regalloc(&g1, n1.Type, &r1)
+       gc.Cgen(n1, &g1)
+       gmove(&g1, &r1)
+       gc.Regalloc(&r2, t, n2)
+       gc.Regalloc(&g2, n1.Type, &r2)
+       gc.Cgen(n2, &g2)
+       gmove(&g2, &r2)
+       gins(optoas(gc.OCMP, t), &r1, &r2)
+       gc.Regfree(&g1)
+       gc.Regfree(&r1)
+       gc.Regfree(&g2)
+       gc.Regfree(&r2)
+       return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
 // addr += index*width if possible.
 func addindex(index *gc.Node, width int64, addr *gc.Node) bool {
        switch width {
index 0ca87537ff82577f61198563140980c17b712385..17d78f399d36e7c92fb74e69f2b784c6eabc0911 100644 (file)
@@ -101,6 +101,7 @@ func main() {
        gc.Thearch.Getg = getg
        gc.Thearch.Gins = gins
        gc.Thearch.Ginsboolval = ginsboolval
+       gc.Thearch.Ginscmp = ginscmp
        gc.Thearch.Ginscon = ginscon
        gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Gmove = gmove
index 53d0f038d91a649c058a7f8deecec8ee5763afc0..14e1a57cbd12d965dcaea209a2699e350f6d2e25 100644 (file)
@@ -99,6 +99,42 @@ func ginscon(as int, c int64, n2 *gc.Node) {
        gins(as, &n1, n2)
 }
 
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+       if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && gc.Smallintconst(n1) && n2.Op != gc.OLITERAL {
+               // Reverse comparison to place constant last.
+               op = gc.Brrev(op)
+               n1, n2 = n2, n1
+       }
+       // General case.
+       var r1, r2, g1, g2 gc.Node
+       if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+               r1 = *n1
+       } else {
+               gc.Regalloc(&r1, t, n1)
+               gc.Regalloc(&g1, n1.Type, &r1)
+               gc.Cgen(n1, &g1)
+               gmove(&g1, &r1)
+       }
+       if n2.Op == gc.OLITERAL && gc.Isint[t.Etype] && gc.Smallintconst(n2) {
+               r2 = *n2
+       } else {
+               gc.Regalloc(&r2, t, n2)
+               gc.Regalloc(&g2, n1.Type, &r2)
+               gc.Cgen(n2, &g2)
+               gmove(&g2, &r2)
+       }
+       gins(optoas(gc.OCMP, t), &r1, &r2)
+       if r1.Op == gc.OREGISTER {
+               gc.Regfree(&g1)
+               gc.Regfree(&r1)
+       }
+       if r2.Op == gc.OREGISTER {
+               gc.Regfree(&g2)
+               gc.Regfree(&r2)
+       }
+       return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
 func ginsboolval(a int, n *gc.Node) {
        gins(jmptoset(a), nil, n)
 }
index 34b4ab6142c34958a453872a42aade5825f146fb..8a6184efd04a08a214f3b5b57a63c4edd14c5877 100644 (file)
@@ -65,6 +65,7 @@ func main() {
        gc.Thearch.Expandchecks = expandchecks
        gc.Thearch.Getg = getg
        gc.Thearch.Gins = gins
+       gc.Thearch.Ginscmp = ginscmp
        gc.Thearch.Ginscon = ginscon
        gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Gmove = gmove
index a34a4306aec540edc345c44fd555e16195c44f77..60c3a7ad44d95dd8817381c8e08a2804b035ce1b 100644 (file)
@@ -102,6 +102,34 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
        gc.Regfree(&ntmp)
 }
 
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+       if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
+               // Reverse comparison to place constant last.
+               op = gc.Brrev(op)
+               n1, n2 = n2, n1
+       }
+
+       var r1, r2, g1, g2 gc.Node
+       gc.Regalloc(&r1, t, n1)
+       gc.Regalloc(&g1, n1.Type, &r1)
+       gc.Cgen(n1, &g1)
+       gmove(&g1, &r1)
+       if gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) {
+               ginscon2(optoas(gc.OCMP, t), &r1, gc.Mpgetfix(n2.Val.U.Xval))
+       } else {
+               gc.Regalloc(&r2, t, n2)
+               gc.Regalloc(&g2, n1.Type, &r2)
+               gc.Cgen(n2, &g2)
+               gmove(&g2, &r2)
+               gcmp(optoas(gc.OCMP, t), &r1, &r2)
+               gc.Regfree(&g2)
+               gc.Regfree(&r2)
+       }
+       gc.Regfree(&g1)
+       gc.Regfree(&r1)
+       return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
 /*
  * generate move:
  *     t = f
index e96b628dcc2c595bd3d278957c6c3623384b5f3d..3651f509c9ef22df62c016b56bda3dc15da894f1 100644 (file)
@@ -81,6 +81,7 @@ func main() {
        gc.Thearch.Expandchecks = expandchecks
        gc.Thearch.Getg = getg
        gc.Thearch.Gins = gins
+       gc.Thearch.Ginscmp = ginscmp
        gc.Thearch.Ginscon = ginscon
        gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Gmove = gmove
index 34ddfe0619535f55d2a60f696106b58c92c6502b..d1134d2c7471440e060a3a894c387ada1f4f067f 100644 (file)
@@ -582,6 +582,45 @@ func ginscon(as int, c int64, n2 *gc.Node) {
        gins(as, &n1, n2)
 }
 
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+       if gc.Isint[t.Etype] || int(t.Etype) == gc.Tptr {
+               if (n1.Op == gc.OLITERAL || n1.Op == gc.OADDR && n1.Left.Op == gc.ONAME) && n2.Op != gc.OLITERAL {
+                       // Reverse comparison to place constant (including address constant) last.
+                       op = gc.Brrev(op)
+                       n1, n2 = n2, n1
+               }
+       }
+
+       // General case.
+       var r1, r2, g1, g2 gc.Node
+       if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+               r1 = *n1
+       } else {
+               gc.Regalloc(&r1, t, n1)
+               gc.Regalloc(&g1, n1.Type, &r1)
+               gc.Cgen(n1, &g1)
+               gmove(&g1, &r1)
+       }
+       if n2.Op == gc.OLITERAL && gc.Isint[t.Etype] || n2.Op == gc.OADDR && n2.Left.Op == gc.ONAME && n2.Left.Class == gc.PEXTERN {
+               r2 = *n2
+       } else {
+               gc.Regalloc(&r2, t, n2)
+               gc.Regalloc(&g2, n1.Type, &r2)
+               gc.Cgen(n2, &g2)
+               gmove(&g2, &r2)
+       }
+       gins(optoas(gc.OCMP, t), &r1, &r2)
+       if r1.Op == gc.OREGISTER {
+               gc.Regfree(&g1)
+               gc.Regfree(&r1)
+       }
+       if r2.Op == gc.OREGISTER {
+               gc.Regfree(&g2)
+               gc.Regfree(&r2)
+       }
+       return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
 /*
  * swap node contents
  */
index a2f4a0ef89cee1b5b6d5113e758e50fca1549630..6e1612007bb65d589a660eae5ed9a1b71557a712 100644 (file)
@@ -72,6 +72,7 @@ func main() {
        gc.Thearch.Expandchecks = expandchecks
        gc.Thearch.Getg = getg
        gc.Thearch.Gins = gins
+       gc.Thearch.Ginscmp = ginscmp
        gc.Thearch.Ginscon = ginscon
        gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Gmove = gmove
index 8223fe70b1f273a03ef316aff4bed37ec3f51ec6..61ba87ee3e666f72fb2f66edc4500516128858c8 100644 (file)
@@ -116,6 +116,34 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
        gc.Regfree(&ntmp)
 }
 
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+       if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
+               // Reverse comparison to place constant last.
+               op = gc.Brrev(op)
+               n1, n2 = n2, n1
+       }
+
+       var r1, r2, g1, g2 gc.Node
+       gc.Regalloc(&r1, t, n1)
+       gc.Regalloc(&g1, n1.Type, &r1)
+       gc.Cgen(n1, &g1)
+       gmove(&g1, &r1)
+       if gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) {
+               ginscon2(optoas(gc.OCMP, t), &r1, gc.Mpgetfix(n2.Val.U.Xval))
+       } else {
+               gc.Regalloc(&r2, t, n2)
+               gc.Regalloc(&g2, n1.Type, &r2)
+               gc.Cgen(n2, &g2)
+               gmove(&g2, &r2)
+               rawgins(optoas(gc.OCMP, t), &r1, &r2)
+               gc.Regfree(&g2)
+               gc.Regfree(&r2)
+       }
+       gc.Regfree(&g1)
+       gc.Regfree(&r1)
+       return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
 /*
  * set up nodes representing 2^63
  */
index 6f8187d9536556507a66dcd56c1c2b2a89f94a39..92a670d2fcd73486f47a9fb5536b6d82ee4f8437 100644 (file)
@@ -569,8 +569,7 @@ func cgen_wb(n, res *Node, wb bool) {
 
                        var n2 Node
                        Nodconst(&n2, Types[Tptr], 0)
-                       Thearch.Gins(Thearch.Optoas(OCMP, Types[Tptr]), &n1, &n2)
-                       p1 := Gbranch(Thearch.Optoas(OEQ, Types[Tptr]), nil, 0)
+                       p1 := Thearch.Ginscmp(OEQ, Types[Tptr], &n1, &n2, 0)
 
                        n2 = n1
                        n2.Op = OINDREG
@@ -610,8 +609,7 @@ func cgen_wb(n, res *Node, wb bool) {
 
                        var n2 Node
                        Nodconst(&n2, Types[Tptr], 0)
-                       Thearch.Gins(Thearch.Optoas(OCMP, Types[Tptr]), &n1, &n2)
-                       p1 := Gbranch(Thearch.Optoas(OEQ, Types[Tptr]), nil, 0)
+                       p1 := Thearch.Ginscmp(OEQ, Types[Tptr], &n1, &n2, 0)
 
                        n2 = n1
                        n2.Op = OINDREG
@@ -804,19 +802,7 @@ func cgen_wbptr(n, res *Node) {
        }
 
        wbEnabled := syslook("writeBarrierEnabled", 0)
-       switch Ctxt.Arch.Thechar {
-       default:
-               Fatal("cgen_wbptr: unknown architecture")
-       case '5', '7', '9':
-               var tmp Node
-               Regalloc(&tmp, Types[TUINT8], nil)
-               Thearch.Gmove(wbEnabled, &tmp)
-               Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT8]), &tmp, Nodintconst(0))
-               Regfree(&tmp)
-       case '6', '8':
-               Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT8]), wbEnabled, Nodintconst(0))
-       }
-       pbr := Gbranch(Thearch.Optoas(ONE, Types[TUINT8]), nil, -1)
+       pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
        Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
        pjmp := Gbranch(obj.AJMP, nil, 0)
        Patch(pbr, Pc)
@@ -1055,13 +1041,7 @@ func Agenr(n *Node, a *Node, res *Node) {
                                                n1.Op = OINDREG
                                                n1.Type = Types[Tptr]
                                                n1.Xoffset = int64(Array_nel)
-                                               var n4 Node
-                                               Regalloc(&n4, n1.Type, nil)
-                                               Thearch.Gmove(&n1, &n4)
-                                               Nodconst(&n2, Types[TUINT32], int64(v))
-                                               Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT32]), &n4, &n2)
-                                               Regfree(&n4)
-                                               p1 := Gbranch(Thearch.Optoas(OGT, Types[TUINT32]), nil, +1)
+                                               p1 := Thearch.Ginscmp(OGT, Types[TUINT32], &n1, &n2, +1)
                                                Ginscall(Panicindex, -1)
                                                Patch(p1, Pc)
                                        }
@@ -1099,12 +1079,10 @@ func Agenr(n *Node, a *Node, res *Node) {
                                } else {
                                        Nodconst(&n4, Types[TUINT32], nl.Type.Bound)
                                }
-
-                               Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT32]), &n2, &n4)
+                               p1 := Thearch.Ginscmp(OLT, Types[TUINT32], &n2, &n4, +1)
                                if n4.Op == OREGISTER {
                                        Regfree(&n4)
                                }
-                               p1 := Gbranch(Thearch.Optoas(OLT, Types[TUINT32]), nil, +1)
                                if p2 != nil {
                                        Patch(p2, Pc)
                                }
@@ -1213,8 +1191,7 @@ func Agenr(n *Node, a *Node, res *Node) {
                                                nlen.Type = Types[TUINT32]
                                                nlen.Xoffset += int64(Array_nel)
                                                Nodconst(&n2, Types[TUINT32], int64(v))
-                                               Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT32]), &nlen, &n2)
-                                               p1 := Gbranch(Thearch.Optoas(OGT, Types[TUINT32]), nil, +1)
+                                               p1 := Thearch.Ginscmp(OGT, Types[TUINT32], &nlen, &n2, +1)
                                                Ginscall(Panicindex, -1)
                                                Patch(p1, Pc)
                                        }
@@ -1261,8 +1238,7 @@ func Agenr(n *Node, a *Node, res *Node) {
                                        Nodconst(&nlen, t, nl.Type.Bound)
                                }
 
-                               Thearch.Gins(Thearch.Optoas(OCMP, t), &n2, &nlen)
-                               p1 := Gbranch(Thearch.Optoas(OLT, t), nil, +1)
+                               p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
                                if p2 != nil {
                                        Patch(p2, Pc)
                                }
@@ -1401,25 +1377,7 @@ func Agenr(n *Node, a *Node, res *Node) {
                        v := uint64(Mpgetfix(nr.Val.U.Xval))
                        if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
                                if Debug['B'] == 0 && !n.Bounded {
-                                       if nlen.Op != OREGISTER && (Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9') {
-                                               var tmp2 Node
-                                               Regalloc(&tmp2, Types[Simtype[TUINT]], nil)
-                                               Thearch.Gmove(&nlen, &tmp2)
-                                               Regfree(&nlen) // in case it is OINDREG
-                                               nlen = tmp2
-                                       }
-                                       var n2 Node
-                                       Nodconst(&n2, Types[Simtype[TUINT]], int64(v))
-                                       if Smallintconst(nr) {
-                                               Thearch.Gins(Thearch.Optoas(OCMP, Types[Simtype[TUINT]]), &nlen, &n2)
-                                       } else {
-                                               Regalloc(&tmp, Types[Simtype[TUINT]], nil)
-                                               Thearch.Gmove(&n2, &tmp)
-                                               Thearch.Gins(Thearch.Optoas(OCMP, Types[Simtype[TUINT]]), &nlen, &tmp)
-                                               Regfree(&tmp)
-                                       }
-
-                                       p1 := Gbranch(Thearch.Optoas(OGT, Types[Simtype[TUINT]]), nil, +1)
+                                       p1 := Thearch.Ginscmp(OGT, Types[Simtype[TUINT]], &nlen, Nodintconst(int64(v)), +1)
                                        Ginscall(Panicindex, -1)
                                        Patch(p1, Pc)
                                }
@@ -1456,26 +1414,12 @@ func Agenr(n *Node, a *Node, res *Node) {
                        if Isconst(nl, CTSTR) {
                                Nodconst(&nlen, t, int64(len(nl.Val.U.Sval)))
                        } else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
-                               if Is64(nr.Type) || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
-                                       var n5 Node
-                                       Regalloc(&n5, t, nil)
-                                       Thearch.Gmove(&nlen, &n5)
-                                       Regfree(&nlen)
-                                       nlen = n5
-                               }
+                               // nlen already initialized
                        } else {
                                Nodconst(&nlen, t, nl.Type.Bound)
-                               if !Smallintconst(&nlen) {
-                                       var n5 Node
-                                       Regalloc(&n5, t, nil)
-                                       Thearch.Gmove(&nlen, &n5)
-                                       nlen = n5
-                                       freelen = 1
-                               }
                        }
 
-                       Thearch.Gins(Thearch.Optoas(OCMP, t), &n2, &nlen)
-                       p1 := Gbranch(Thearch.Optoas(OLT, t), nil, +1)
+                       p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
                        Ginscall(Panicindex, -1)
                        Patch(p1, Pc)
                }
@@ -2446,8 +2390,7 @@ func Ginscall(f *Node, proc int) {
 
                if proc == 2 {
                        Nodreg(&reg, Types[TINT32], Thearch.REGRETURN)
-                       Thearch.Gins(Thearch.Optoas(OCMP, Types[TINT32]), &reg, Nodintconst(0))
-                       p := Gbranch(Thearch.Optoas(OEQ, Types[TINT32]), nil, +1)
+                       p := Thearch.Ginscmp(OEQ, Types[TINT32], &reg, Nodintconst(0), +1)
                        cgen_ret(nil)
                        Patch(p, Pc)
                }
index e6af897033479ebd969f14ebaf6918be4dd94439..76e9a82392d7be1179308eeae315f825744cef3e 100644 (file)
@@ -428,8 +428,7 @@ func cgen_dottype(n *Node, res, resok *Node, wb bool) {
        Cgen(&iface, &r1)
        if !isnilinter(n.Left.Type) {
                // Holding itab, want concrete type in second word.
-               Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, Nodintconst(0))
-               p := Gbranch(Thearch.Optoas(OEQ, byteptr), nil, -1)
+               p := Thearch.Ginscmp(OEQ, byteptr, &r1, Nodintconst(0), -1)
                r2 = r1
                r2.Op = OINDREG
                r2.Xoffset = int64(Widthptr)
@@ -438,8 +437,7 @@ func cgen_dottype(n *Node, res, resok *Node, wb bool) {
        }
        Regalloc(&r2, byteptr, nil)
        Cgen(typename(n.Type), &r2)
-       Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, &r2)
-       p := Gbranch(Thearch.Optoas(ONE, byteptr), nil, -1)
+       p := Thearch.Ginscmp(ONE, byteptr, &r1, &r2, -1)
        Regfree(&r2) // not needed for success path; reclaimed on one failure path
        iface.Xoffset += int64(Widthptr)
        Cgen(&iface, &r1)
@@ -521,8 +519,7 @@ func Cgen_As2dottype(n, res, resok *Node) {
        Cgen(&iface, &r1)
        if !isnilinter(n.Left.Type) {
                // Holding itab, want concrete type in second word.
-               Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, Nodintconst(0))
-               p := Gbranch(Thearch.Optoas(OEQ, byteptr), nil, -1)
+               p := Thearch.Ginscmp(OEQ, byteptr, &r1, Nodintconst(0), -1)
                r2 = r1
                r2.Op = OINDREG
                r2.Xoffset = int64(Widthptr)
@@ -531,8 +528,7 @@ func Cgen_As2dottype(n, res, resok *Node) {
        }
        Regalloc(&r2, byteptr, nil)
        Cgen(typename(n.Type), &r2)
-       Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, &r2)
-       p := Gbranch(Thearch.Optoas(ONE, byteptr), nil, -1)
+       p := Thearch.Ginscmp(ONE, byteptr, &r1, &r2, -1)
        iface.Type = n.Type
        iface.Xoffset += int64(Widthptr)
        Cgen(&iface, &r1)
index 71bce0bf2cd12423bd0983d4341d1e27dfd35a5e..404dcbb4ffc37502d8b349a4dc9275354a2de3e4 100644 (file)
@@ -778,13 +778,26 @@ type Arch struct {
        Expandchecks func(*obj.Prog)
        Getg         func(*Node)
        Gins         func(int, *Node, *Node) *obj.Prog
+
+       // Ginscmp generates code comparing n1 to n2 and jumping away if op is satisfied.
+       // The returned prog should be Patch'ed with the jump target.
+       // If op is not satisfied, code falls through to the next emitted instruction.
+       // Likely is the branch prediction hint: +1 for likely, -1 for unlikely, 0 for no opinion.
+       //
+       // Ginscmp must be able to handle all kinds of arguments for n1 and n2,
+       // not just simple registers, although it can assume that there are no
+       // function calls needed during the evaluation, so no in-memory temporaries
+       // are necessary.
+       Ginscmp func(op int, t *Type, n1, n2 *Node, likely int) *obj.Prog
+
        // Ginsboolval inserts instructions to convert the result
        // of a just-completed comparison to a boolean value.
        // The first argument is the conditional jump instruction
        // corresponding to the desired value.
        // The second argument is the destination.
        // If not present, Ginsboolval will be emulated with jumps.
-       Ginsboolval  func(int, *Node)
+       Ginsboolval func(int, *Node)
+
        Ginscon      func(int, int64, *Node)
        Ginsnop      func()
        Gmove        func(*Node, *Node)