Commit 95b146e8 authored by Michael Munday's avatar Michael Munday

cmd/compile: improve floating point constant propagation

Add generic rules to propagate floating point constants through
comparisons and integer conversions. These new rules seldom trigger
in the standard library so there is no performance change, however
I think it is worth adding them anyway for completeness.

Change-Id: I9db5222746508a2996f1cafb72f4e0cf2541de07
Reviewed-on: https://go-review.googlesource.com/63795
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 40e25895
......@@ -1492,6 +1492,29 @@ var linuxS390XTests = []*asmTest{
`,
neg: []string{"\tFMOVS\t"},
},
// Constant propagation through float comparisons.
{
fn: `
func $() bool {
return 0.5 == float64(uint32(1)) ||
1.5 > float64(uint64(1<<63)) ||
math.NaN() == math.NaN()
}
`,
pos: []string{"\tMOV(B|BZ|D)\t[$]0,"},
neg: []string{"\tFCMPU\t", "\tMOV(B|BZ|D)\t[$]1,"},
},
{
fn: `
func $() bool {
return float32(0.5) <= float32(int64(1)) &&
float32(1.5) >= float32(int32(-1<<31)) &&
float32(math.NaN()) != float32(math.NaN())
}
`,
pos: []string{"\tMOV(B|BZ|D)\t[$]1,"},
neg: []string{"\tCEBR\t", "\tMOV(B|BZ|D)\t[$]0,"},
},
}
var linuxARMTests = []*asmTest{
......
......@@ -4,7 +4,10 @@
package gc
import "testing"
import (
"math"
"testing"
)
// For GO386=387, make sure fucomi* opcodes are not used
// for comparison operations.
......@@ -29,6 +32,105 @@ func TestFloatCompare(t *testing.T) {
if !compare2(3, 5) {
t.Errorf("compare2 returned false")
}
// test folded float64 comparisons
d1, d3, d5, d9 := float64(1), float64(3), float64(5), float64(9)
if d3 == d5 {
t.Errorf("d3 == d5 returned true")
}
if d3 != d3 {
t.Errorf("d3 != d3 returned true")
}
if d3 > d5 {
t.Errorf("d3 > d5 returned true")
}
if d3 >= d9 {
t.Errorf("d3 >= d9 returned true")
}
if d5 < d1 {
t.Errorf("d5 < d1 returned true")
}
if d9 <= d1 {
t.Errorf("d9 <= d1 returned true")
}
if math.NaN() == math.NaN() {
t.Errorf("math.NaN() == math.NaN() returned true")
}
if math.NaN() >= math.NaN() {
t.Errorf("math.NaN() >= math.NaN() returned true")
}
if math.NaN() <= math.NaN() {
t.Errorf("math.NaN() <= math.NaN() returned true")
}
if math.Copysign(math.NaN(), -1) < math.NaN() {
t.Errorf("math.Copysign(math.NaN(), -1) < math.NaN() returned true")
}
if math.Inf(1) != math.Inf(1) {
t.Errorf("math.Inf(1) != math.Inf(1) returned true")
}
if math.Inf(-1) != math.Inf(-1) {
t.Errorf("math.Inf(-1) != math.Inf(-1) returned true")
}
if math.Copysign(0, -1) != 0 {
t.Errorf("math.Copysign(0, -1) != 0 returned true")
}
if math.Copysign(0, -1) < 0 {
t.Errorf("math.Copysign(0, -1) < 0 returned true")
}
if 0 > math.Copysign(0, -1) {
t.Errorf("0 > math.Copysign(0, -1) returned true")
}
// test folded float32 comparisons
s1, s3, s5, s9 := float32(1), float32(3), float32(5), float32(9)
if s3 == s5 {
t.Errorf("s3 == s5 returned true")
}
if s3 != s3 {
t.Errorf("s3 != s3 returned true")
}
if s3 > s5 {
t.Errorf("s3 > s5 returned true")
}
if s3 >= s9 {
t.Errorf("s3 >= s9 returned true")
}
if s5 < s1 {
t.Errorf("s5 < s1 returned true")
}
if s9 <= s1 {
t.Errorf("s9 <= s1 returned true")
}
sPosNaN, sNegNaN := float32(math.NaN()), float32(math.Copysign(math.NaN(), -1))
if sPosNaN == sPosNaN {
t.Errorf("sPosNaN == sPosNaN returned true")
}
if sPosNaN >= sPosNaN {
t.Errorf("sPosNaN >= sPosNaN returned true")
}
if sPosNaN <= sPosNaN {
t.Errorf("sPosNaN <= sPosNaN returned true")
}
if sNegNaN < sPosNaN {
t.Errorf("sNegNaN < sPosNaN returned true")
}
sPosInf, sNegInf := float32(math.Inf(1)), float32(math.Inf(-1))
if sPosInf != sPosInf {
t.Errorf("sPosInf != sPosInf returned true")
}
if sNegInf != sNegInf {
t.Errorf("sNegInf != sNegInf returned true")
}
sNegZero := float32(math.Copysign(0, -1))
if sNegZero != 0 {
t.Errorf("sNegZero != 0 returned true")
}
if sNegZero < 0 {
t.Errorf("sNegZero < 0 returned true")
}
if 0 > sNegZero {
t.Errorf("0 > sNegZero returned true")
}
}
// For GO386=387, make sure fucomi* opcodes are not used
......
......@@ -46,6 +46,14 @@
(Trunc64to32 (Const64 [c])) -> (Const32 [int64(int32(c))])
(Cvt64Fto32F (Const64F [c])) -> (Const32F [f2i(float64(i2f32(c)))])
(Cvt32Fto64F (Const32F [c])) -> (Const64F [c]) // c is already a 64 bit float
(Cvt32to32F (Const32 [c])) -> (Const32F [f2i(float64(float32(int32(c))))])
(Cvt32to64F (Const32 [c])) -> (Const64F [f2i(float64(int32(c)))])
(Cvt64to32F (Const64 [c])) -> (Const32F [f2i(float64(float32(c)))])
(Cvt64to64F (Const64 [c])) -> (Const64F [f2i(float64(c))])
(Cvt32Fto32 (Const32F [c])) -> (Const32 [int64(int32(i2f(c)))])
(Cvt32Fto64 (Const32F [c])) -> (Const64 [int64(i2f(c))])
(Cvt64Fto32 (Const64F [c])) -> (Const32 [int64(int32(i2f(c)))])
(Cvt64Fto64 (Const64F [c])) -> (Const32 [int64(i2f(c))])
(Round32F x:(Const32F)) -> x
(Round64F x:(Const64F)) -> x
......@@ -561,6 +569,25 @@
(Leq16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) <= uint16(d))])
(Leq8U (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(uint8(c) <= uint8(d))])
// constant floating point comparisons
(Eq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(i2f(c) == i2f(d))])
(Eq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(i2f(c) == i2f(d))])
(Neq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(i2f(c) != i2f(d))])
(Neq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(i2f(c) != i2f(d))])
(Greater64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(i2f(c) > i2f(d))])
(Greater32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(i2f(c) > i2f(d))])
(Geq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(i2f(c) >= i2f(d))])
(Geq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(i2f(c) >= i2f(d))])
(Less64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(i2f(c) < i2f(d))])
(Less32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(i2f(c) < i2f(d))])
(Leq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(i2f(c) <= i2f(d))])
(Leq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(i2f(c) <= i2f(d))])
// simplifications
(Or64 x x) -> x
(Or32 x x) -> 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