diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 340b7daa52..ac8888e14d 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" "html" + "math" "os" "strings" @@ -3006,7 +3007,7 @@ func genValue(v *ssa.Value) { x := regnum(v) p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_FCONST - p.From.Val = v.Aux.(float64) + p.From.Val = math.Float64frombits(uint64(v.AuxInt)) p.To.Type = obj.TYPE_REG p.To.Reg = x case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVBQZXload: diff --git a/src/cmd/compile/internal/ssa/TODO b/src/cmd/compile/internal/ssa/TODO index 8feb1053ae..fbe4f56760 100644 --- a/src/cmd/compile/internal/ssa/TODO +++ b/src/cmd/compile/internal/ssa/TODO @@ -44,7 +44,6 @@ Optimizations (better compiler) - Reuseable slices (e.g. []int of size NumValues()) cached in Func - Handle signed division overflow and sign extension earlier - Implement 64 bit const division with high multiply, maybe in the frontend? -- Store bool and float32/float64 in auxInt Regalloc -------- diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index a7249a4c54..710b7609c6 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -126,6 +126,13 @@ func checkFunc(f *Func) { if _, ok := v.Aux.(bool); ok { f.Fatalf("value %v has a bool Aux value, should be AuxInt", v.LongString()) } + if _, ok := v.Aux.(float32); ok { + f.Fatalf("value %v has a float32 Aux value, should be AuxInt", v.LongString()) + } + + if _, ok := v.Aux.(float64); ok { + f.Fatalf("value %v has a float64 Aux value, should be AuxInt", v.LongString()) + } for _, arg := range v.Args { if arg == nil { diff --git a/src/cmd/compile/internal/ssa/cse.go b/src/cmd/compile/internal/ssa/cse.go index 6469ecd72b..836a7803ac 100644 --- a/src/cmd/compile/internal/ssa/cse.go +++ b/src/cmd/compile/internal/ssa/cse.go @@ -4,10 +4,7 @@ package ssa -import ( - "math" - "sort" -) +import "sort" // cse does common-subexpression elimination on the Function. // Values are just relinked, nothing is deleted. A subsequent deadcode @@ -55,18 +52,11 @@ func cse(f *Func) { arg1op = v.Args[1].Op } - aux := v.Aux - auxInt := v.AuxInt - // -0 == 0, but aren't equivalent values so we use - // Float64bits to distinguish - if f, ok := aux.(float64); ok { - aux = nil - if auxInt != 0 { - v.Fatalf("float would clobber v.auxInt") - } - auxInt = int64(math.Float64bits(f)) - } - k := key{v.Op, v.Type.String(), aux, auxInt, len(v.Args), bid, arg0op, arg1op} + // This assumes that floats are stored in AuxInt + // instead of Aux. If not, then we need to use the + // float bits as part of the key, otherwise since 0.0 == -0.0 + // this would incorrectly treat 0.0 and -0.0 as identical values + k := key{v.Op, v.Type.String(), v.Aux, v.AuxInt, len(v.Args), bid, arg0op, arg1op} m[k] = append(m[k], v) } } diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index 09bfff2bfc..747a5c7f03 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -4,7 +4,10 @@ package ssa -import "sync" +import ( + "math" + "sync" +) // A Func represents a Go func declaration (or function literal) and // its body. This package compiles each Func independently. @@ -287,13 +290,11 @@ func (f *Func) ConstIntPtr(line int32, t Type, c int64) *Value { } func (f *Func) ConstFloat32(line int32, t Type, c float64) *Value { // TODO: cache? - // For now stuff FP values into aux interface - return f.Entry.NewValue0A(line, OpConst32F, t, c) + return f.Entry.NewValue0I(line, OpConst32F, t, int64(math.Float64bits(c))) } func (f *Func) ConstFloat64(line int32, t Type, c float64) *Value { // TODO: cache? - // For now stuff FP values into aux interface - return f.Entry.NewValue0A(line, OpConst64F, t, c) + return f.Entry.NewValue0I(line, OpConst64F, t, int64(math.Float64bits(c))) } func (f *Func) Logf(msg string, args ...interface{}) { f.Config.Logf(msg, args...) } diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 8e1a8a09b1..16bd1df84b 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -81,8 +81,8 @@ (Neg32 x) -> (NEGL x) (Neg16 x) -> (NEGW x) (Neg8 x) -> (NEGB x) -(Neg32F x) -> (PXOR x (MOVSSconst {math.Copysign(0, -1)})) -(Neg64F x) -> (PXOR x (MOVSDconst {math.Copysign(0, -1)})) +(Neg32F x) -> (PXOR x (MOVSSconst [f2i(math.Copysign(0, -1))])) +(Neg64F x) -> (PXOR x (MOVSDconst [f2i(math.Copysign(0, -1))])) (Com64 x) -> (NOTQ x) (Com32 x) -> (NOTL x) @@ -299,8 +299,8 @@ (Const16 [val]) -> (MOVWconst [val]) (Const32 [val]) -> (MOVLconst [val]) (Const64 [val]) -> (MOVQconst [val]) -(Const32F {val}) -> (MOVSSconst {val}) -(Const64F {val}) -> (MOVSDconst {val}) +(Const32F [val]) -> (MOVSSconst [val]) +(Const64F [val]) -> (MOVSDconst [val]) (ConstPtr [val]) -> (MOVQconst [val]) (ConstNil) -> (MOVQconst [0]) (ConstBool [b]) -> (MOVBconst [b]) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 2742a5cc3b..5c47ec6660 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -4,7 +4,10 @@ package ssa -import "fmt" +import ( + "fmt" + "math" +) func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool) { // repeat rewrites until we find no more rewrites @@ -170,3 +173,8 @@ func b2i(b bool) int64 { } return 0 } + +// f2i is used in the rules for storing a float in AuxInt. +func f2i(f float64) int64 { + return int64(math.Float64bits(f)) +} diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index f449892a8a..8ad939ead9 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -1560,20 +1560,20 @@ func rewriteValueAMD64(v *Value, config *Config) bool { enddae5807662af67143a3ac3ad9c63bae5: ; case OpConst32F: - // match: (Const32F {val}) + // match: (Const32F [val]) // cond: - // result: (MOVSSconst {val}) + // result: (MOVSSconst [val]) { - val := v.Aux + val := v.AuxInt v.Op = OpAMD64MOVSSconst v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.Aux = val + v.AuxInt = val return true } - goto end30a68b43982e55971cc58f893ae2c04a - end30a68b43982e55971cc58f893ae2c04a: + goto endfabcef2d57a8f36eaa6041de6f112b89 + endfabcef2d57a8f36eaa6041de6f112b89: ; case OpConst64: // match: (Const64 [val]) @@ -1592,20 +1592,20 @@ func rewriteValueAMD64(v *Value, config *Config) bool { endc630434ae7f143ab69d5f482a9b52b5f: ; case OpConst64F: - // match: (Const64F {val}) + // match: (Const64F [val]) // cond: - // result: (MOVSDconst {val}) + // result: (MOVSDconst [val]) { - val := v.Aux + val := v.AuxInt v.Op = OpAMD64MOVSDconst v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.Aux = val + v.AuxInt = val return true } - goto end958041a44a2ee8fc571cbc0832fad285 - end958041a44a2ee8fc571cbc0832fad285: + goto endae6cf7189e464bbde17b98635a20f0ff + endae6cf7189e464bbde17b98635a20f0ff: ; case OpConst8: // match: (Const8 [val]) @@ -6044,7 +6044,7 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpNeg32F: // match: (Neg32F x) // cond: - // result: (PXOR x (MOVSSconst {math.Copysign(0, -1)})) + // result: (PXOR x (MOVSSconst [f2i(math.Copysign(0, -1))])) { x := v.Args[0] v.Op = OpAMD64PXOR @@ -6054,12 +6054,12 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(x) v0 := b.NewValue0(v.Line, OpAMD64MOVSSconst, TypeInvalid) v0.Type = config.Frontend().TypeFloat32() - v0.Aux = math.Copysign(0, -1) + v0.AuxInt = f2i(math.Copysign(0, -1)) v.AddArg(v0) return true } - goto end47074133a76e069317ceca46372cafc3 - end47074133a76e069317ceca46372cafc3: + goto end685a5fc899e195b9091afbe2a7146051 + end685a5fc899e195b9091afbe2a7146051: ; case OpNeg64: // match: (Neg64 x) @@ -6080,7 +6080,7 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpNeg64F: // match: (Neg64F x) // cond: - // result: (PXOR x (MOVSDconst {math.Copysign(0, -1)})) + // result: (PXOR x (MOVSDconst [f2i(math.Copysign(0, -1))])) { x := v.Args[0] v.Op = OpAMD64PXOR @@ -6090,12 +6090,12 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(x) v0 := b.NewValue0(v.Line, OpAMD64MOVSDconst, TypeInvalid) v0.Type = config.Frontend().TypeFloat64() - v0.Aux = math.Copysign(0, -1) + v0.AuxInt = f2i(math.Copysign(0, -1)) v.AddArg(v0) return true } - goto end9240202f5753ebd23f11f982ece3e06e - end9240202f5753ebd23f11f982ece3e06e: + goto ende85ae82b7a51e75000eb9158d584acb2 + ende85ae82b7a51e75000eb9158d584acb2: ; case OpNeg8: // match: (Neg8 x) diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index 04ea17cce9..d213b72df3 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -4,7 +4,10 @@ package ssa -import "fmt" +import ( + "fmt" + "math" +) // A Value represents a value in the SSA representation of the program. // The ID and Type fields must not be modified. The remainder may be modified @@ -60,6 +63,15 @@ func (v *Value) LongString() string { s += " <" + v.Type.String() + ">" if v.AuxInt != 0 { s += fmt.Sprintf(" [%d]", v.AuxInt) + + switch { + case v.Op == OpConst32F || v.Op == OpConst64F: + s += fmt.Sprintf("(%g)", math.Float64frombits(uint64(v.AuxInt))) + case v.Op == OpConstBool && v.AuxInt == 0: + s += " (false)" + case v.Op == OpConstBool && v.AuxInt == 1: + s += " (true)" + } } if v.Aux != nil { if _, ok := v.Aux.(string); ok {