Commit db523262 authored by Todd Neal's avatar Todd Neal

[dev.ssa] cmd/compile: only fold 32 bit integers for add/multiply

Fix an issue where doasm fails if trying to multiply by a larger
than 32 bit const (doasm: notfound ft=9 tt=14 00008 IMULQ
$34359738369, CX 9 14).  Fix truncation of 64 to 32 bit integer
when generating LEA causing incorrect values to be computed.

Change-Id: I1e65b63cc32ac673a9bb5a297b578b44c2f1ac8f
Reviewed-on: https://go-review.googlesource.com/12678Reviewed-by: 's avatarKeith Randall <khr@golang.org>
parent 52d76f7a
...@@ -42,3 +42,6 @@ func TestShortCircuit(t *testing.T) { runTest(t, "short_ssa.go") } ...@@ -42,3 +42,6 @@ func TestShortCircuit(t *testing.T) { runTest(t, "short_ssa.go") }
// TestBreakContinue tests that continue and break statements do what they say. // TestBreakContinue tests that continue and break statements do what they say.
func TestBreakContinue(t *testing.T) { runTest(t, "break_ssa.go") } func TestBreakContinue(t *testing.T) { runTest(t, "break_ssa.go") }
// TestArithmetic tests that both backends have the same result for arithmetic expressions.
func TestArithmetic(t *testing.T) { runTest(t, "arith_ssa.go") }
// run
// Copyright 2015 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.
// Tests arithmetic expressions
package main
func test64BitConstMult(a, b int64) {
want := 34359738369*a + b*34359738370
if got := test64BitConstMult_ssa(a, b); want != got {
println("test64BitConstMult failed, wanted", want, "got", got)
failed = true
}
}
func test64BitConstMult_ssa(a, b int64) int64 {
switch { // prevent inlining
}
return 34359738369*a + b*34359738370
}
func test64BitConstAdd(a, b int64) {
want := a + 575815584948629622 + b + 2991856197886747025
if got := test64BitConstAdd_ssa(a, b); want != got {
println("test64BitConstAdd failed, wanted", want, "got", got)
failed = true
}
}
func test64BitConstAdd_ssa(a, b int64) int64 {
switch {
}
return a + 575815584948629622 + b + 2991856197886747025
}
var failed = false
func main() {
test64BitConstMult(1, 2)
test64BitConstAdd(1, 2)
if failed {
panic("failed")
}
}
...@@ -136,12 +136,13 @@ ...@@ -136,12 +136,13 @@
// TODO: Should this be a separate pass? // TODO: Should this be a separate pass?
// fold constants into instructions // fold constants into instructions
(ADDQ x (MOVQconst [c])) -> (ADDQconst [c] x) // TODO: restrict c to int32 range? // TODO: restrict c to int32 range for all?
(ADDQ (MOVQconst [c]) x) -> (ADDQconst [c] x) (ADDQ x (MOVQconst [c])) && is32Bit(c) -> (ADDQconst [c] x)
(ADDQ (MOVQconst [c]) x) && is32Bit(c) -> (ADDQconst [c] x)
(SUBQ x (MOVQconst [c])) -> (SUBQconst x [c]) (SUBQ x (MOVQconst [c])) -> (SUBQconst x [c])
(SUBQ <t> (MOVQconst [c]) x) -> (NEGQ (SUBQconst <t> x [c])) (SUBQ <t> (MOVQconst [c]) x) -> (NEGQ (SUBQconst <t> x [c]))
(MULQ x (MOVQconst [c])) && c == int64(int32(c)) -> (MULQconst [c] x) (MULQ x (MOVQconst [c])) && is32Bit(c) -> (MULQconst [c] x)
(MULQ (MOVQconst [c]) x) -> (MULQconst [c] x) (MULQ (MOVQconst [c]) x) && is32Bit(c) -> (MULQconst [c] x)
(ANDQ x (MOVQconst [c])) -> (ANDQconst [c] x) (ANDQ x (MOVQconst [c])) -> (ANDQconst [c] x)
(ANDQ (MOVQconst [c]) x) -> (ANDQconst [c] x) (ANDQ (MOVQconst [c]) x) -> (ANDQconst [c] x)
(SHLQ x (MOVQconst [c])) -> (SHLQconst [c] x) (SHLQ x (MOVQconst [c])) -> (SHLQconst [c] x)
......
...@@ -130,7 +130,12 @@ func log2(n int64) (l int64) { ...@@ -130,7 +130,12 @@ func log2(n int64) (l int64) {
return l return l
} }
// isPowerOfTwo returns true if n is a power of 2. // isPowerOfTwo reports whether n is a power of 2.
func isPowerOfTwo(n int64) bool { func isPowerOfTwo(n int64) bool {
return n > 0 && n&(n-1) == 0 return n > 0 && n&(n-1) == 0
} }
// is32Bit reports whether n can be represented as a signed 32 bit integer.
func is32Bit(n int64) bool {
return n == int64(int32(n))
}
...@@ -6,14 +6,17 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -6,14 +6,17 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
switch v.Op { switch v.Op {
case OpAMD64ADDQ: case OpAMD64ADDQ:
// match: (ADDQ x (MOVQconst [c])) // match: (ADDQ x (MOVQconst [c]))
// cond: // cond: is32Bit(c)
// result: (ADDQconst [c] x) // result: (ADDQconst [c] x)
{ {
x := v.Args[0] x := v.Args[0]
if v.Args[1].Op != OpAMD64MOVQconst { if v.Args[1].Op != OpAMD64MOVQconst {
goto endacffd55e74ee0ff59ad58a18ddfc9973 goto end1de8aeb1d043e0dadcffd169a99ce5c0
} }
c := v.Args[1].AuxInt c := v.Args[1].AuxInt
if !(is32Bit(c)) {
goto end1de8aeb1d043e0dadcffd169a99ce5c0
}
v.Op = OpAMD64ADDQconst v.Op = OpAMD64ADDQconst
v.AuxInt = 0 v.AuxInt = 0
v.Aux = nil v.Aux = nil
...@@ -22,18 +25,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -22,18 +25,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
v.AddArg(x) v.AddArg(x)
return true return true
} }
goto endacffd55e74ee0ff59ad58a18ddfc9973 goto end1de8aeb1d043e0dadcffd169a99ce5c0
endacffd55e74ee0ff59ad58a18ddfc9973: end1de8aeb1d043e0dadcffd169a99ce5c0:
; ;
// match: (ADDQ (MOVQconst [c]) x) // match: (ADDQ (MOVQconst [c]) x)
// cond: // cond: is32Bit(c)
// result: (ADDQconst [c] x) // result: (ADDQconst [c] x)
{ {
if v.Args[0].Op != OpAMD64MOVQconst { if v.Args[0].Op != OpAMD64MOVQconst {
goto end7166f476d744ab7a51125959d3d3c7e2 goto endca635e3bdecd9e3aeb892f841021dfaa
} }
c := v.Args[0].AuxInt c := v.Args[0].AuxInt
x := v.Args[1] x := v.Args[1]
if !(is32Bit(c)) {
goto endca635e3bdecd9e3aeb892f841021dfaa
}
v.Op = OpAMD64ADDQconst v.Op = OpAMD64ADDQconst
v.AuxInt = 0 v.AuxInt = 0
v.Aux = nil v.Aux = nil
...@@ -42,8 +48,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -42,8 +48,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
v.AddArg(x) v.AddArg(x)
return true return true
} }
goto end7166f476d744ab7a51125959d3d3c7e2 goto endca635e3bdecd9e3aeb892f841021dfaa
end7166f476d744ab7a51125959d3d3c7e2: endca635e3bdecd9e3aeb892f841021dfaa:
; ;
// match: (ADDQ x (SHLQconst [3] y)) // match: (ADDQ x (SHLQconst [3] y))
// cond: // cond:
...@@ -1223,16 +1229,16 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -1223,16 +1229,16 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
; ;
case OpAMD64MULQ: case OpAMD64MULQ:
// match: (MULQ x (MOVQconst [c])) // match: (MULQ x (MOVQconst [c]))
// cond: c == int64(int32(c)) // cond: is32Bit(c)
// result: (MULQconst [c] x) // result: (MULQconst [c] x)
{ {
x := v.Args[0] x := v.Args[0]
if v.Args[1].Op != OpAMD64MOVQconst { if v.Args[1].Op != OpAMD64MOVQconst {
goto end680a32a37babfff4bfa7d23be592a131 goto endb38c6e3e0ddfa25ba0ef9684ac1528c0
} }
c := v.Args[1].AuxInt c := v.Args[1].AuxInt
if !(c == int64(int32(c))) { if !(is32Bit(c)) {
goto end680a32a37babfff4bfa7d23be592a131 goto endb38c6e3e0ddfa25ba0ef9684ac1528c0
} }
v.Op = OpAMD64MULQconst v.Op = OpAMD64MULQconst
v.AuxInt = 0 v.AuxInt = 0
...@@ -1242,18 +1248,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -1242,18 +1248,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
v.AddArg(x) v.AddArg(x)
return true return true
} }
goto end680a32a37babfff4bfa7d23be592a131 goto endb38c6e3e0ddfa25ba0ef9684ac1528c0
end680a32a37babfff4bfa7d23be592a131: endb38c6e3e0ddfa25ba0ef9684ac1528c0:
; ;
// match: (MULQ (MOVQconst [c]) x) // match: (MULQ (MOVQconst [c]) x)
// cond: // cond: is32Bit(c)
// result: (MULQconst [c] x) // result: (MULQconst [c] x)
{ {
if v.Args[0].Op != OpAMD64MOVQconst { if v.Args[0].Op != OpAMD64MOVQconst {
goto endc6e18d6968175d6e58eafa6dcf40c1b8 goto end9cb4f29b0bd7141639416735dcbb3b87
} }
c := v.Args[0].AuxInt c := v.Args[0].AuxInt
x := v.Args[1] x := v.Args[1]
if !(is32Bit(c)) {
goto end9cb4f29b0bd7141639416735dcbb3b87
}
v.Op = OpAMD64MULQconst v.Op = OpAMD64MULQconst
v.AuxInt = 0 v.AuxInt = 0
v.Aux = nil v.Aux = nil
...@@ -1262,8 +1271,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -1262,8 +1271,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
v.AddArg(x) v.AddArg(x)
return true return true
} }
goto endc6e18d6968175d6e58eafa6dcf40c1b8 goto end9cb4f29b0bd7141639416735dcbb3b87
endc6e18d6968175d6e58eafa6dcf40c1b8: end9cb4f29b0bd7141639416735dcbb3b87:
; ;
case OpAMD64MULQconst: case OpAMD64MULQconst:
// match: (MULQconst [-1] x) // match: (MULQconst [-1] x)
......
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