]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.10] cmd/compile: fix zero extend after float->int conversion
authorKeith Randall <keithr@alum.mit.edu>
Thu, 10 May 2018 17:15:52 +0000 (10:15 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 24 Aug 2018 16:18:39 +0000 (16:18 +0000)
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>
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/gen/AMD64Ops.go
src/cmd/compile/internal/ssa/rewriteAMD64.go
test/fixedbugs/issue25322.go [new file with mode: 0644]
test/fixedbugs/issue25322.out [new file with mode: 0644]

index db7c1a447b247e05b6498adca71a5c060f0c9ba8..a90722df6e240d966d8678defa747afa22e1dc24 100644 (file)
 
 // 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})
index b7c0ce9f086fe6d805d88bfcb444f93108e6cab9..c3075e1020a2bf17ae702fe72f31b0622ebb998f 100644 (file)
@@ -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.
 
index 0b2b321d2566603215b22e78ca676f0820844737..e309ce6bf629f4032fcc2fe7eebb7d50315d707c 100644 (file)
@@ -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 (file)
index 0000000..7489bbd
--- /dev/null
@@ -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 (file)
index 0000000..52f3f6a
--- /dev/null
@@ -0,0 +1 @@
+40000000