]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: defer lowering OANDNOT until SSA
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Sat, 24 Oct 2020 03:40:09 +0000 (10:40 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Tue, 27 Oct 2020 03:11:45 +0000 (03:11 +0000)
Currently, "x &^ y" gets rewriten into "x & ^y" during walk. It adds
unnecessary complexity to other parts, which must aware about this.

Instead, we can just implement "&^" in the conversion to SSA, so "&^"
can be handled like other binary operators.

However, this CL does not pass toolstash-check. It seems that implements
"&^" in the conversion to SSA causes registers allocation change.

With the parent:

obj: 00212 (.../src/runtime/complex.go:47)    MOVQ    X0, AX
obj: 00213 (.../src/runtime/complex.go:47)    BTRQ    $63, AX
obj: 00214 (.../src/runtime/complex.go:47)    MOVQ    "".n(SP), CX
obj: 00215 (.../src/runtime/complex.go:47)    MOVQ    $-9223372036854775808, DX
obj: 00216 (.../src/runtime/complex.go:47)    ANDQ    DX, CX
obj: 00217 (.../src/runtime/complex.go:47)    ORQ AX, CX

With this CL:

obj: 00212 (.../src/runtime/complex.go:47)    MOVQ    X0, AX
obj: 00213 (.../src/runtime/complex.go:47)    BTRQ    $63, AX
obj: 00214 (.../src/runtime/complex.go:47)    MOVQ    $-9223372036854775808, CX
obj: 00215 (.../src/runtime/complex.go:47)    MOVQ    "".n(SP), DX
obj: 00216 (.../src/runtime/complex.go:47)    ANDQ    CX, DX
obj: 00217 (.../src/runtime/complex.go:47)    ORQ AX, DX

Change-Id: I80acf8496a91be4804fb7ef3df04c19baae2754c
Reviewed-on: https://go-review.googlesource.com/c/go/+/264660
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/walk.go
test/bounds.go

index a1b5a03687eff3beeebac988e643f2c3d22467c9..4769c2c7d93ba0d307f30d612ac4590a9df388e2 100644 (file)
@@ -2472,6 +2472,11 @@ func (s *state) expr(n *Node) *ssa.Value {
                a := s.expr(n.Left)
                b := s.expr(n.Right)
                return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
+       case OANDNOT:
+               a := s.expr(n.Left)
+               b := s.expr(n.Right)
+               b = s.newValue1(s.ssaOp(OBITNOT, b.Type), b.Type, b)
+               return s.newValue2(s.ssaOp(OAND, n.Type), a.Type, a, b)
        case OLSH, ORSH:
                a := s.expr(n.Left)
                b := s.expr(n.Right)
index 83b5db834fc65a8d68ec26d20a59c287d097478a..58de9b5e3ff96e074cff1288f02cc009043d3fdd 100644 (file)
@@ -142,7 +142,7 @@ const (
        _, _                               // second nodeInitorder bit
        _, nodeHasBreak
        _, nodeNoInline  // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
-       _, nodeImplicit  // implicit OADDR or ODEREF; ++/-- statement represented as OASOP; or ANDNOT lowered to OAND
+       _, nodeImplicit  // implicit OADDR or ODEREF; ++/-- statement represented as OASOP
        _, nodeIsDDD     // is the argument variadic
        _, nodeDiag      // already printed error about this
        _, nodeColas     // OAS resulting from :=
index 6ce3eda44b9092b33e34d024c462e1f65b3b6735..927f6c4b1eb8ff75c33bcd63f2ce54a6459b1668 100644 (file)
@@ -474,7 +474,7 @@ opswitch:
                ODEREF, OSPTR, OITAB, OIDATA, OADDR:
                n.Left = walkexpr(n.Left, init)
 
-       case OEFACE, OAND, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH:
+       case OEFACE, OAND, OANDNOT, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH:
                n.Left = walkexpr(n.Left, init)
                n.Right = walkexpr(n.Right, init)
 
@@ -965,14 +965,6 @@ opswitch:
                fn := basicnames[param] + "to" + basicnames[result]
                n = conv(mkcall(fn, types.Types[result], init, conv(n.Left, types.Types[param])), n.Type)
 
-       case OANDNOT:
-               n.Left = walkexpr(n.Left, init)
-               n.Op = OAND
-               n.SetImplicit(true) // for walkCheckPtrArithmetic
-               n.Right = nod(OBITNOT, n.Right, nil)
-               n.Right = typecheck(n.Right, ctxExpr)
-               n.Right = walkexpr(n.Right, init)
-
        case ODIV, OMOD:
                n.Left = walkexpr(n.Left, init)
                n.Right = walkexpr(n.Right, init)
@@ -3609,14 +3601,20 @@ func bounded(n *Node, max int64) bool {
        }
 
        switch n.Op {
-       case OAND:
+       case OAND, OANDNOT:
                v := int64(-1)
-               if smallintconst(n.Left) {
+               switch {
+               case smallintconst(n.Left):
                        v = n.Left.Int64Val()
-               } else if smallintconst(n.Right) {
+               case smallintconst(n.Right):
                        v = n.Right.Int64Val()
+                       if n.Op == OANDNOT {
+                               v = ^v
+                               if !sign {
+                                       v &= 1<<uint(bits) - 1
+                               }
+                       }
                }
-
                if 0 <= v && v < max {
                        return true
                }
@@ -4045,12 +4043,8 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node {
                case OADD:
                        walk(n.Left)
                        walk(n.Right)
-               case OSUB:
+               case OSUB, OANDNOT:
                        walk(n.Left)
-               case OAND:
-                       if n.Implicit() { // was OANDNOT
-                               walk(n.Left)
-                       }
                case OCONVNOP:
                        if n.Left.Type.IsUnsafePtr() {
                                n.Left = cheapexpr(n.Left, init)
index 4a9c3b2d39a2261e53ef3a8763f54aee1e0397c8..aa1d51b6f9cc6e5290bd677ebddac497fee69b71 100644 (file)
@@ -209,6 +209,11 @@ func main() {
        use(a1k[i&^0])
        use(a1k[i&^-2]) // ERROR "index bounds check elided"
        use(a1k[i&^1])
+       use(a1k[i8&^0])
+       use(a1k[i8&^-128]) // ERROR "index bounds check elided"
+       use(a1k[ui8&^1])   // ERROR "index bounds check elided"
+       use(a1k[ui16&^0xf000])
+       use(a1k[ui16&^0xff00]) // ERROR "index bounds check elided"
 
        // Right shift cuts the effective number of bits in the index,
        // but only for unsigned (signed stays negative).