Skip to content

Commit 78d75b3

Browse files
committed
cmd/compile: make 386 float-to-int conversions match amd64
Change-Id: Iff13b4471f94a6a91d8b159603a9338cb9c89747 Reviewed-on: https://go-review.googlesource.com/c/go/+/708295 Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Keith Randall <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 0e466a8 commit 78d75b3

File tree

9 files changed

+182
-23
lines changed

9 files changed

+182
-23
lines changed

src/cmd/compile/internal/ssa/_gen/386.rules

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@
8888
(Cvt32to32F ...) => (CVTSL2SS ...)
8989
(Cvt32to64F ...) => (CVTSL2SD ...)
9090

91-
(Cvt32Fto32 ...) => (CVTTSS2SL ...)
92-
(Cvt64Fto32 ...) => (CVTTSD2SL ...)
91+
(Cvt32Fto32 <t> x) && base.ConvertHash.MatchPos(v.Pos, nil) => (XORL <t> y (SARLconst <t> [31] (ANDL <t> y:(CVTTSS2SL <t> x) (NOTL <typ.Int32> (MOVLf2i x)))))
92+
(Cvt64Fto32 <t> x) && base.ConvertHash.MatchPos(v.Pos, nil) => (XORL <t> y (SARLconst <t> [31] (ANDL <t> y:(CVTTSD2SL <t> x) (NOTL <typ.Int32> (MOVLf2i (CVTSD2SS <typ.Float32> x))))))
93+
(Cvt32Fto32 <t> x) && !base.ConvertHash.MatchPos(v.Pos, nil) => (CVTTSS2SL <t> x)
94+
(Cvt64Fto32 <t> x) && !base.ConvertHash.MatchPos(v.Pos, nil) => (CVTTSD2SL <t> x)
9395

9496
(Cvt32Fto64F ...) => (CVTSS2SD ...)
9597
(Cvt64Fto32F ...) => (CVTSD2SS ...)

src/cmd/compile/internal/ssa/_gen/386Ops.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ func init() {
342342
{name: "MOVWLSX", argLength: 1, reg: gp11, asm: "MOVWLSX"}, // sign extend arg0 from int16 to int32
343343
{name: "MOVWLZX", argLength: 1, reg: gp11, asm: "MOVWLZX"}, // zero extend arg0 from int16 to int32
344344

345+
{name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg, zero extend
346+
345347
{name: "MOVLconst", reg: gp01, asm: "MOVL", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint
346348

347349
{name: "CVTTSD2SL", argLength: 1, reg: fpgp, asm: "CVTTSD2SL"}, // convert float64 to int32

src/cmd/compile/internal/ssa/opGen.go

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/compile/internal/ssa/rewrite386.go

Lines changed: 95 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/compile/internal/x86/ssa.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
538538
p.To.Type = obj.TYPE_MEM
539539
p.To.Reg = v.Args[0].Reg()
540540
ssagen.AddAux(&p.To, v)
541+
case ssa.Op386MOVLf2i:
542+
var p *obj.Prog
543+
p = s.Prog(x86.AMOVL)
544+
p.From.Type = obj.TYPE_REG
545+
p.From.Reg = v.Args[0].Reg()
546+
p.To.Type = obj.TYPE_REG
547+
p.To.Reg = v.Reg()
541548
case ssa.Op386ADDLconstmodify:
542549
sc := v.AuxValAndOff()
543550
val := sc.Val()

src/runtime/asm_386.s

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,16 +1407,6 @@ TEXT runtime·uint32tofloat64(SB),NOSPLIT,$8-12
14071407
FMOVDP F0, ret+4(FP)
14081408
RET
14091409

1410-
TEXT runtime·float64touint32(SB),NOSPLIT,$12-12
1411-
FMOVD a+0(FP), F0
1412-
FSTCW 0(SP)
1413-
FLDCW runtime·controlWord64trunc(SB)
1414-
FMOVVP F0, 4(SP)
1415-
FLDCW 0(SP)
1416-
MOVL 4(SP), AX
1417-
MOVL AX, ret+8(FP)
1418-
RET
1419-
14201410
// gcWriteBarrier informs the GC about heap pointer writes.
14211411
//
14221412
// gcWriteBarrier returns space in a write barrier buffer which

src/runtime/stubs_386.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package runtime
66

77
import "unsafe"
88

9-
func float64touint32(a float64) uint32
109
func uint32tofloat64(a uint32) float64
1110

1211
// stackcheck checks that SP is in range [g->stack.lo, g->stack.hi).

src/runtime/vlrt.go

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,17 @@ func float64toint64(d float64) (y uint64) {
4040
}
4141

4242
func float64touint64(d float64) (y uint64) {
43-
_d2v(&y, d)
43+
_d2vu(&y, d)
4444
return
4545
}
4646

47+
func float64touint32(a float64) uint32 {
48+
if a >= 0xffffffff {
49+
return 0xffffffff
50+
}
51+
return uint32(float64touint64(a))
52+
}
53+
4754
func int64tofloat64(y int64) float64 {
4855
if y < 0 {
4956
return -uint64tofloat64(-uint64(y))
@@ -117,12 +124,16 @@ func _d2v(y *uint64, d float64) {
117124
} else {
118125
/* v = (hi||lo) << -sh */
119126
sh := uint32(-sh)
120-
if sh <= 11 {
127+
if sh <= 10 {
121128
ylo = xlo << sh
122129
yhi = xhi<<sh | xlo>>(32-sh)
123130
} else {
124-
/* overflow */
125-
yhi = uint32(d) /* causes something awful */
131+
if x&sign64 != 0 {
132+
*y = 0x8000000000000000
133+
} else {
134+
*y = 0x7fffffffffffffff
135+
}
136+
return
126137
}
127138
}
128139
if x&sign64 != 0 {
@@ -136,6 +147,50 @@ func _d2v(y *uint64, d float64) {
136147

137148
*y = uint64(yhi)<<32 | uint64(ylo)
138149
}
150+
func _d2vu(y *uint64, d float64) {
151+
x := *(*uint64)(unsafe.Pointer(&d))
152+
if x&sign64 != 0 {
153+
*y = 0
154+
return
155+
}
156+
157+
xhi := uint32(x>>32)&0xfffff | 0x100000
158+
xlo := uint32(x)
159+
sh := 1075 - int32(uint32(x>>52)&0x7ff)
160+
161+
var ylo, yhi uint32
162+
if sh >= 0 {
163+
sh := uint32(sh)
164+
/* v = (hi||lo) >> sh */
165+
if sh < 32 {
166+
if sh == 0 {
167+
ylo = xlo
168+
yhi = xhi
169+
} else {
170+
ylo = xlo>>sh | xhi<<(32-sh)
171+
yhi = xhi >> sh
172+
}
173+
} else {
174+
if sh == 32 {
175+
ylo = xhi
176+
} else if sh < 64 {
177+
ylo = xhi >> (sh - 32)
178+
}
179+
}
180+
} else {
181+
/* v = (hi||lo) << -sh */
182+
sh := uint32(-sh)
183+
if sh <= 11 {
184+
ylo = xlo << sh
185+
yhi = xhi<<sh | xlo>>(32-sh)
186+
} else {
187+
/* overflow */
188+
*y = 0xffffffffffffffff
189+
return
190+
}
191+
}
192+
*y = uint64(yhi)<<32 | uint64(ylo)
193+
}
139194
func uint64div(n, d uint64) uint64 {
140195
// Check for 32 bit operands
141196
if uint32(n>>32) == 0 && uint32(d>>32) == 0 {

test/convert5.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
// Use of this source code is governed by a BSD-style
55
// license that can be found in the LICENSE file.
66

7-
//go:build !wasm && !386 && !arm && !mips
7+
//go:build !wasm
88

9-
// TODO fix this to work for wasm and 32-bit architectures.
9+
// TODO fix this to work for wasm
1010
// Doing more than this, however, expands the change.
1111

1212
package main

0 commit comments

Comments
 (0)