]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/amd64: use appropriate NEG for div
authorIlya Tocar <ilya.tocar@intel.com>
Fri, 23 Feb 2018 19:46:44 +0000 (13:46 -0600)
committerIlya Tocar <ilya.tocar@intel.com>
Mon, 26 Feb 2018 20:09:21 +0000 (20:09 +0000)
Currently we generate NEGQ for DIV{Q,L,W}. By generating NEGL and NEGW,
we will reduce code size, because NEGL doesn't require rex prefix.
This also guarantees that upper 32 bits are zeroed, so we can revert CL 85736,
and remove zero-extensions of DIVL results.
Also adds test for redundant zero extend elimination.

Fixes #23310

Change-Id: Ic58c3104c255a71371a06e09d10a975bbe5df587
Reviewed-on: https://go-review.googlesource.com/96815
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/amd64/ssa.go
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/zeroextension_test.go [new file with mode: 0644]

index 49ef415e66c46b8e118586fa70ac60779964a844..d5e9fd32f034cdb8b1cb43a318dacf7ca974d70a 100644 (file)
@@ -266,7 +266,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
 
                // Issue -1 fixup code.
                // n / -1 = -n
-               n1 := s.Prog(x86.ANEGQ)
+               var n1 *obj.Prog
+               switch v.Op {
+               case ssa.OpAMD64DIVQ:
+                       n1 = s.Prog(x86.ANEGQ)
+               case ssa.OpAMD64DIVL:
+                       n1 = s.Prog(x86.ANEGL)
+               case ssa.OpAMD64DIVW:
+                       n1 = s.Prog(x86.ANEGW)
+               }
                n1.To.Type = obj.TYPE_REG
                n1.To.Reg = x86.REG_AX
 
index df5f6c9fa4a58f2441054d5740b361767664c100..587a2a6d1a068bce7ca59ddef79b78eb963f9369 100644 (file)
@@ -782,12 +782,8 @@ func zeroUpper32Bits(x *Value, depth int) bool {
                OpAMD64ANDL, OpAMD64ANDLconst, OpAMD64ORL, OpAMD64ORLconst,
                OpAMD64XORL, OpAMD64XORLconst, OpAMD64NEGL, OpAMD64NOTL:
                return true
-       case OpArg:
+       case OpArg, OpSelect0, OpSelect1:
                return x.Type.Width == 4
-       case OpSelect0, OpSelect1:
-               // Disabled for now. See issue 23305.
-               // TODO: we could look into the arg of the Select to decide.
-               return false
        case OpPhi:
                // Phis can use each-other as an arguments, instead of tracking visited values,
                // just limit recursion depth.
diff --git a/src/cmd/compile/internal/ssa/zeroextension_test.go b/src/cmd/compile/internal/ssa/zeroextension_test.go
new file mode 100644 (file)
index 0000000..692685e
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+import "testing"
+
+type extTest struct {
+       f    func(uint64, uint64) uint64
+       arg1 uint64
+       arg2 uint64
+       res  uint64
+       name string
+}
+
+var extTests = [...]extTest{
+       {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 / op2)) }, arg1: 0x1, arg2: 0xfffffffeffffffff, res: 0xffffffff, name: "div"},
+       {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 * op2)) }, arg1: 0x1, arg2: 0x100000001, res: 0x1, name: "mul"},
+       {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 + op2)) }, arg1: 0x1, arg2: 0xfffffffffffffff, res: 0x0, name: "add"},
+       {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 - op2)) }, arg1: 0x1, arg2: 0xfffffffffffffff, res: 0x2, name: "sub"},
+       {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 | op2)) }, arg1: 0x1, arg2: 0xfffffffffffffff, res: 0xffffffff, name: "or"},
+       {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 ^ op2)) }, arg1: 0x1, arg2: 0xfffffffffffffff, res: 0xfffffffe, name: "xor"},
+       {f: func(a, b uint64) uint64 { op1 := int32(a); op2 := int32(b); return uint64(uint32(op1 & op2)) }, arg1: 0x1, arg2: 0x100000000000001, res: 0x1, name: "and"},
+}
+
+func TestZeroExtension(t *testing.T) {
+       for _, x := range extTests {
+               r := x.f(x.arg1, x.arg2)
+               if x.res != r {
+                       t.Errorf("%s: got %d want %d", x.name, r, x.res)
+               }
+       }
+}