diff options
author | Keith Randall <keithr@alum.mit.edu> | 2018-05-10 10:15:52 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2018-08-24 16:18:39 +0000 |
commit | 305b0de625833f4986b6556cba633e6f21c37c18 (patch) | |
tree | 8599258966d1dfbee9cda4952992ed905c1b9943 | |
parent | ba5e308ea9496e4be0bd8c59a5291359e0ea98b4 (diff) | |
download | go-305b0de625833f4986b6556cba633e6f21c37c18.tar.gz go-305b0de625833f4986b6556cba633e6f21c37c18.zip |
[release-branch.go1.10] cmd/compile: fix zero extend after float->int conversion
Don't do direct loads from argument slots if the sizes don't match.
This prevents us from loading from a float32 using a uint64 load
during expressions like uint64(math.float32Bits(f)) where f is a float32 arg.
Fixes #25335
Change-Id: I3887d76f78c844ba546243e7721d811c3d4a9700
Reviewed-on: https://go-review.googlesource.com/112637
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/131276
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
-rw-r--r-- | src/cmd/compile/internal/ssa/gen/AMD64.rules | 8 | ||||
-rw-r--r-- | src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/ssa/rewriteAMD64.go | 32 | ||||
-rw-r--r-- | test/fixedbugs/issue25322.go | 23 | ||||
-rw-r--r-- | test/fixedbugs/issue25322.out | 1 |
5 files changed, 53 insertions, 13 deletions
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index db7c1a447b..a90722df6e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2658,7 +2658,7 @@ // Load args directly into the register class where it will be used. // We do this by just modifying the type of the Arg. -(MOVQf2i <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym}) -(MOVLf2i <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym}) -(MOVQi2f <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym}) -(MOVLi2f <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym}) +(MOVQf2i <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym}) +(MOVLf2i <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym}) +(MOVQi2f <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym}) +(MOVLi2f <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym}) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index b7c0ce9f08..c3075e1020 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -407,7 +407,7 @@ func init() { {name: "MOVQi2f", argLength: 1, reg: gpfp, typ: "Float64"}, // move 64 bits from int to float reg {name: "MOVQf2i", argLength: 1, reg: fpgp, typ: "UInt64"}, // move 64 bits from float to int reg {name: "MOVLi2f", argLength: 1, reg: gpfp, typ: "Float32"}, // move 32 bits from int to float reg - {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg + {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg, zero extend {name: "PXOR", argLength: 2, reg: fp21, asm: "PXOR", commutative: true, resultInArg0: true}, // exclusive or, applied to X regs for float negation. diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 0b2b321d25..e309ce6bf6 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -7428,8 +7428,8 @@ func rewriteValueAMD64_OpAMD64MOVLatomicload_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVLf2i_0(v *Value) bool { b := v.Block _ = b - // match: (MOVLf2i <t> (Arg [off] {sym})) - // cond: + // match: (MOVLf2i <t> (Arg <u> [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg <t> [off] {sym}) for { t := v.Type @@ -7437,8 +7437,12 @@ func rewriteValueAMD64_OpAMD64MOVLf2i_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) @@ -7452,8 +7456,8 @@ func rewriteValueAMD64_OpAMD64MOVLf2i_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVLi2f_0(v *Value) bool { b := v.Block _ = b - // match: (MOVLi2f <t> (Arg [off] {sym})) - // cond: + // match: (MOVLi2f <t> (Arg <u> [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg <t> [off] {sym}) for { t := v.Type @@ -7461,8 +7465,12 @@ func rewriteValueAMD64_OpAMD64MOVLi2f_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) @@ -9631,8 +9639,8 @@ func rewriteValueAMD64_OpAMD64MOVQatomicload_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVQf2i_0(v *Value) bool { b := v.Block _ = b - // match: (MOVQf2i <t> (Arg [off] {sym})) - // cond: + // match: (MOVQf2i <t> (Arg <u> [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg <t> [off] {sym}) for { t := v.Type @@ -9640,8 +9648,12 @@ func rewriteValueAMD64_OpAMD64MOVQf2i_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) @@ -9655,8 +9667,8 @@ func rewriteValueAMD64_OpAMD64MOVQf2i_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVQi2f_0(v *Value) bool { b := v.Block _ = b - // match: (MOVQi2f <t> (Arg [off] {sym})) - // cond: + // match: (MOVQi2f <t> (Arg <u> [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg <t> [off] {sym}) for { t := v.Type @@ -9664,8 +9676,12 @@ func rewriteValueAMD64_OpAMD64MOVQi2f_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) diff --git a/test/fixedbugs/issue25322.go b/test/fixedbugs/issue25322.go new file mode 100644 index 0000000000..7489bbdfc2 --- /dev/null +++ b/test/fixedbugs/issue25322.go @@ -0,0 +1,23 @@ +// cmpout + +// 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. + +// Missing zero extension when converting a float32 +// to a uint64. + +package main + +import ( + "fmt" + "math" +) + +func Foo(v float32) { + fmt.Printf("%x\n", uint64(math.Float32bits(v))) +} + +func main() { + Foo(2.0) +} diff --git a/test/fixedbugs/issue25322.out b/test/fixedbugs/issue25322.out new file mode 100644 index 0000000000..52f3f6a745 --- /dev/null +++ b/test/fixedbugs/issue25322.out @@ -0,0 +1 @@ +40000000 |