mirror of
https://github.com/golang/go
synced 2024-10-05 18:31:28 -06:00
[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/12678 Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
52d76f7a6a
commit
db5232620a
@ -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.
|
||||
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") }
|
||||
|
47
src/cmd/compile/internal/gc/testdata/arith_ssa.go
vendored
Normal file
47
src/cmd/compile/internal/gc/testdata/arith_ssa.go
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
// 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 @@
|
||||
// TODO: Should this be a separate pass?
|
||||
|
||||
// fold constants into instructions
|
||||
(ADDQ x (MOVQconst [c])) -> (ADDQconst [c] x) // TODO: restrict c to int32 range?
|
||||
(ADDQ (MOVQconst [c]) x) -> (ADDQconst [c] x)
|
||||
// TODO: restrict c to int32 range for all?
|
||||
(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 <t> (MOVQconst [c]) x) -> (NEGQ (SUBQconst <t> x [c]))
|
||||
(MULQ x (MOVQconst [c])) && c == int64(int32(c)) -> (MULQconst [c] x)
|
||||
(MULQ (MOVQconst [c]) x) -> (MULQconst [c] x)
|
||||
(MULQ x (MOVQconst [c])) && is32Bit(c) -> (MULQconst [c] x)
|
||||
(MULQ (MOVQconst [c]) x) && is32Bit(c) -> (MULQconst [c] x)
|
||||
(ANDQ x (MOVQconst [c])) -> (ANDQconst [c] x)
|
||||
(ANDQ (MOVQconst [c]) x) -> (ANDQconst [c] x)
|
||||
(SHLQ x (MOVQconst [c])) -> (SHLQconst [c] x)
|
||||
|
@ -130,7 +130,12 @@ func log2(n int64) (l int64) {
|
||||
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 {
|
||||
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 {
|
||||
switch v.Op {
|
||||
case OpAMD64ADDQ:
|
||||
// match: (ADDQ x (MOVQconst [c]))
|
||||
// cond:
|
||||
// cond: is32Bit(c)
|
||||
// result: (ADDQconst [c] x)
|
||||
{
|
||||
x := v.Args[0]
|
||||
if v.Args[1].Op != OpAMD64MOVQconst {
|
||||
goto endacffd55e74ee0ff59ad58a18ddfc9973
|
||||
goto end1de8aeb1d043e0dadcffd169a99ce5c0
|
||||
}
|
||||
c := v.Args[1].AuxInt
|
||||
if !(is32Bit(c)) {
|
||||
goto end1de8aeb1d043e0dadcffd169a99ce5c0
|
||||
}
|
||||
v.Op = OpAMD64ADDQconst
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
@ -22,18 +25,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
goto endacffd55e74ee0ff59ad58a18ddfc9973
|
||||
endacffd55e74ee0ff59ad58a18ddfc9973:
|
||||
goto end1de8aeb1d043e0dadcffd169a99ce5c0
|
||||
end1de8aeb1d043e0dadcffd169a99ce5c0:
|
||||
;
|
||||
// match: (ADDQ (MOVQconst [c]) x)
|
||||
// cond:
|
||||
// cond: is32Bit(c)
|
||||
// result: (ADDQconst [c] x)
|
||||
{
|
||||
if v.Args[0].Op != OpAMD64MOVQconst {
|
||||
goto end7166f476d744ab7a51125959d3d3c7e2
|
||||
goto endca635e3bdecd9e3aeb892f841021dfaa
|
||||
}
|
||||
c := v.Args[0].AuxInt
|
||||
x := v.Args[1]
|
||||
if !(is32Bit(c)) {
|
||||
goto endca635e3bdecd9e3aeb892f841021dfaa
|
||||
}
|
||||
v.Op = OpAMD64ADDQconst
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
@ -42,8 +48,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
goto end7166f476d744ab7a51125959d3d3c7e2
|
||||
end7166f476d744ab7a51125959d3d3c7e2:
|
||||
goto endca635e3bdecd9e3aeb892f841021dfaa
|
||||
endca635e3bdecd9e3aeb892f841021dfaa:
|
||||
;
|
||||
// match: (ADDQ x (SHLQconst [3] y))
|
||||
// cond:
|
||||
@ -1223,16 +1229,16 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
|
||||
;
|
||||
case OpAMD64MULQ:
|
||||
// match: (MULQ x (MOVQconst [c]))
|
||||
// cond: c == int64(int32(c))
|
||||
// cond: is32Bit(c)
|
||||
// result: (MULQconst [c] x)
|
||||
{
|
||||
x := v.Args[0]
|
||||
if v.Args[1].Op != OpAMD64MOVQconst {
|
||||
goto end680a32a37babfff4bfa7d23be592a131
|
||||
goto endb38c6e3e0ddfa25ba0ef9684ac1528c0
|
||||
}
|
||||
c := v.Args[1].AuxInt
|
||||
if !(c == int64(int32(c))) {
|
||||
goto end680a32a37babfff4bfa7d23be592a131
|
||||
if !(is32Bit(c)) {
|
||||
goto endb38c6e3e0ddfa25ba0ef9684ac1528c0
|
||||
}
|
||||
v.Op = OpAMD64MULQconst
|
||||
v.AuxInt = 0
|
||||
@ -1242,18 +1248,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
goto end680a32a37babfff4bfa7d23be592a131
|
||||
end680a32a37babfff4bfa7d23be592a131:
|
||||
goto endb38c6e3e0ddfa25ba0ef9684ac1528c0
|
||||
endb38c6e3e0ddfa25ba0ef9684ac1528c0:
|
||||
;
|
||||
// match: (MULQ (MOVQconst [c]) x)
|
||||
// cond:
|
||||
// cond: is32Bit(c)
|
||||
// result: (MULQconst [c] x)
|
||||
{
|
||||
if v.Args[0].Op != OpAMD64MOVQconst {
|
||||
goto endc6e18d6968175d6e58eafa6dcf40c1b8
|
||||
goto end9cb4f29b0bd7141639416735dcbb3b87
|
||||
}
|
||||
c := v.Args[0].AuxInt
|
||||
x := v.Args[1]
|
||||
if !(is32Bit(c)) {
|
||||
goto end9cb4f29b0bd7141639416735dcbb3b87
|
||||
}
|
||||
v.Op = OpAMD64MULQconst
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
@ -1262,8 +1271,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
goto endc6e18d6968175d6e58eafa6dcf40c1b8
|
||||
endc6e18d6968175d6e58eafa6dcf40c1b8:
|
||||
goto end9cb4f29b0bd7141639416735dcbb3b87
|
||||
end9cb4f29b0bd7141639416735dcbb3b87:
|
||||
;
|
||||
case OpAMD64MULQconst:
|
||||
// match: (MULQconst [-1] x)
|
||||
|
Loading…
Reference in New Issue
Block a user