Commit f4d9c309 authored by Ilya Tocar's avatar Ilya Tocar

cmd/compile/internal/amd64: use appropriate NEG for div

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: default avatarMatthew Dempsky <mdempsky@google.com>
parent 3b7ad168
......@@ -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
......
......@@ -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.
......
// 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)
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment