mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: make wasm match other platforms for FP->int32/64 conversions
this change is for overflows, so that all the platforms agree. Change-Id: I9f459353615bf24ef8a5de641063d9ce34986241 Reviewed-on: https://go-review.googlesource.com/c/go/+/708358 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
b9f3accdcf
commit
8d810286b3
6 changed files with 89 additions and 17 deletions
|
|
@ -76,13 +76,14 @@
|
||||||
(Cvt32Uto(64|32)F x) => (F(64|32)ConvertI64U (ZeroExt32to64 x))
|
(Cvt32Uto(64|32)F x) => (F(64|32)ConvertI64U (ZeroExt32to64 x))
|
||||||
(Cvt64Uto(64|32)F ...) => (F(64|32)ConvertI64U ...)
|
(Cvt64Uto(64|32)F ...) => (F(64|32)ConvertI64U ...)
|
||||||
|
|
||||||
(Cvt32Fto32 ...) => (I64TruncSatF32S ...)
|
(Cvt32Fto32 ...) => (I32TruncSatF32S ...)
|
||||||
(Cvt32Fto64 ...) => (I64TruncSatF32S ...)
|
(Cvt32Fto64 ...) => (I64TruncSatF32S ...)
|
||||||
(Cvt64Fto32 ...) => (I64TruncSatF64S ...)
|
(Cvt64Fto32 ...) => (I32TruncSatF64S ...)
|
||||||
(Cvt64Fto64 ...) => (I64TruncSatF64S ...)
|
(Cvt64Fto64 ...) => (I64TruncSatF64S ...)
|
||||||
(Cvt32Fto32U ...) => (I64TruncSatF32U ...)
|
|
||||||
|
(Cvt32Fto32U ...) => (I32TruncSatF32U ...)
|
||||||
(Cvt32Fto64U ...) => (I64TruncSatF32U ...)
|
(Cvt32Fto64U ...) => (I64TruncSatF32U ...)
|
||||||
(Cvt64Fto32U ...) => (I64TruncSatF64U ...)
|
(Cvt64Fto32U ...) => (I32TruncSatF64U ...)
|
||||||
(Cvt64Fto64U ...) => (I64TruncSatF64U ...)
|
(Cvt64Fto64U ...) => (I64TruncSatF64U ...)
|
||||||
|
|
||||||
(Cvt32Fto64F ...) => (F64PromoteF32 ...)
|
(Cvt32Fto64F ...) => (F64PromoteF32 ...)
|
||||||
|
|
|
||||||
|
|
@ -222,10 +222,19 @@ func init() {
|
||||||
{name: "F64Mul", asm: "F64Mul", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 * arg1
|
{name: "F64Mul", asm: "F64Mul", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 * arg1
|
||||||
{name: "F64Div", asm: "F64Div", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 / arg1
|
{name: "F64Div", asm: "F64Div", argLength: 2, reg: fp64_21, typ: "Float64"}, // arg0 / arg1
|
||||||
|
|
||||||
{name: "I64TruncSatF64S", asm: "I64TruncSatF64S", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
|
{name: "I64TruncSatF64S", asm: "I64TruncSatF64S", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
|
||||||
{name: "I64TruncSatF64U", asm: "I64TruncSatF64U", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to an unsigned integer (saturating)
|
{name: "I64TruncSatF64U", asm: "I64TruncSatF64U", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Uint64"}, // truncates the float arg0 to an unsigned integer (saturating)
|
||||||
{name: "I64TruncSatF32S", asm: "I64TruncSatF32S", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
|
{name: "I64TruncSatF32S", asm: "I64TruncSatF32S", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
|
||||||
{name: "I64TruncSatF32U", asm: "I64TruncSatF32U", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to an unsigned integer (saturating)
|
{name: "I64TruncSatF32U", asm: "I64TruncSatF32U", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Uint64"}, // truncates the float arg0 to an unsigned integer (saturating)
|
||||||
|
|
||||||
|
// It appears to be wasm convention that everything lands in a 64-bit register;
|
||||||
|
// the WASM instructions for these operations produce 32-bit width results, but
|
||||||
|
// wasm/ssa.go widens them appropriately to 64-bit results.
|
||||||
|
{name: "I32TruncSatF64S", asm: "I32TruncSatF64S", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
|
||||||
|
{name: "I32TruncSatF64U", asm: "I32TruncSatF64U", argLength: 1, reg: regInfo{inputs: []regMask{fp64}, outputs: []regMask{gp}}, typ: "Uint64"}, // truncates the float arg0 to an unsigned integer (saturating)
|
||||||
|
{name: "I32TruncSatF32S", asm: "I32TruncSatF32S", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
|
||||||
|
{name: "I32TruncSatF32U", asm: "I32TruncSatF32U", argLength: 1, reg: regInfo{inputs: []regMask{fp32}, outputs: []regMask{gp}}, typ: "Uint64"}, // truncates the float arg0 to an unsigned integer (saturating)
|
||||||
|
|
||||||
{name: "F32ConvertI64S", asm: "F32ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32"}, // converts the signed integer arg0 to a float
|
{name: "F32ConvertI64S", asm: "F32ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32"}, // converts the signed integer arg0 to a float
|
||||||
{name: "F32ConvertI64U", asm: "F32ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32"}, // converts the unsigned integer arg0 to a float
|
{name: "F32ConvertI64U", asm: "F32ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp32}}, typ: "Float32"}, // converts the unsigned integer arg0 to a float
|
||||||
{name: "F64ConvertI64S", asm: "F64ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp64}}, typ: "Float64"}, // converts the signed integer arg0 to a float
|
{name: "F64ConvertI64S", asm: "F64ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp64}}, typ: "Float64"}, // converts the signed integer arg0 to a float
|
||||||
|
|
|
||||||
|
|
@ -2980,6 +2980,10 @@ const (
|
||||||
OpWasmI64TruncSatF64U
|
OpWasmI64TruncSatF64U
|
||||||
OpWasmI64TruncSatF32S
|
OpWasmI64TruncSatF32S
|
||||||
OpWasmI64TruncSatF32U
|
OpWasmI64TruncSatF32U
|
||||||
|
OpWasmI32TruncSatF64S
|
||||||
|
OpWasmI32TruncSatF64U
|
||||||
|
OpWasmI32TruncSatF32S
|
||||||
|
OpWasmI32TruncSatF32U
|
||||||
OpWasmF32ConvertI64S
|
OpWasmF32ConvertI64S
|
||||||
OpWasmF32ConvertI64U
|
OpWasmF32ConvertI64U
|
||||||
OpWasmF64ConvertI64S
|
OpWasmF64ConvertI64S
|
||||||
|
|
@ -40296,6 +40300,58 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "I32TruncSatF64S",
|
||||||
|
argLen: 1,
|
||||||
|
asm: wasm.AI32TruncSatF64S,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "I32TruncSatF64U",
|
||||||
|
argLen: 1,
|
||||||
|
asm: wasm.AI32TruncSatF64U,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 281470681743360}, // F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "I32TruncSatF32S",
|
||||||
|
argLen: 1,
|
||||||
|
asm: wasm.AI32TruncSatF32S,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "I32TruncSatF32U",
|
||||||
|
argLen: 1,
|
||||||
|
asm: wasm.AI32TruncSatF32U,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 65535}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "F32ConvertI64S",
|
name: "F32ConvertI64S",
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
|
|
|
||||||
|
|
@ -120,10 +120,10 @@ func rewriteValueWasm(v *Value) bool {
|
||||||
v.Op = OpWasmI64Ctz
|
v.Op = OpWasmI64Ctz
|
||||||
return true
|
return true
|
||||||
case OpCvt32Fto32:
|
case OpCvt32Fto32:
|
||||||
v.Op = OpWasmI64TruncSatF32S
|
v.Op = OpWasmI32TruncSatF32S
|
||||||
return true
|
return true
|
||||||
case OpCvt32Fto32U:
|
case OpCvt32Fto32U:
|
||||||
v.Op = OpWasmI64TruncSatF32U
|
v.Op = OpWasmI32TruncSatF32U
|
||||||
return true
|
return true
|
||||||
case OpCvt32Fto64:
|
case OpCvt32Fto64:
|
||||||
v.Op = OpWasmI64TruncSatF32S
|
v.Op = OpWasmI64TruncSatF32S
|
||||||
|
|
@ -143,13 +143,13 @@ func rewriteValueWasm(v *Value) bool {
|
||||||
case OpCvt32to64F:
|
case OpCvt32to64F:
|
||||||
return rewriteValueWasm_OpCvt32to64F(v)
|
return rewriteValueWasm_OpCvt32to64F(v)
|
||||||
case OpCvt64Fto32:
|
case OpCvt64Fto32:
|
||||||
v.Op = OpWasmI64TruncSatF64S
|
v.Op = OpWasmI32TruncSatF64S
|
||||||
return true
|
return true
|
||||||
case OpCvt64Fto32F:
|
case OpCvt64Fto32F:
|
||||||
v.Op = OpWasmF32DemoteF64
|
v.Op = OpWasmF32DemoteF64
|
||||||
return true
|
return true
|
||||||
case OpCvt64Fto32U:
|
case OpCvt64Fto32U:
|
||||||
v.Op = OpWasmI64TruncSatF64U
|
v.Op = OpWasmI32TruncSatF64U
|
||||||
return true
|
return true
|
||||||
case OpCvt64Fto64:
|
case OpCvt64Fto64:
|
||||||
v.Op = OpWasmI64TruncSatF64S
|
v.Op = OpWasmI64TruncSatF64S
|
||||||
|
|
|
||||||
|
|
@ -430,6 +430,17 @@ func ssaGenValueOnStack(s *ssagen.State, v *ssa.Value, extend bool) {
|
||||||
getValue64(s, v.Args[0])
|
getValue64(s, v.Args[0])
|
||||||
s.Prog(v.Op.Asm())
|
s.Prog(v.Op.Asm())
|
||||||
|
|
||||||
|
// 32-bit integer conversion results
|
||||||
|
case ssa.OpWasmI32TruncSatF32S, ssa.OpWasmI32TruncSatF64S:
|
||||||
|
getValue64(s, v.Args[0])
|
||||||
|
s.Prog(v.Op.Asm())
|
||||||
|
s.Prog(wasm.AI64ExtendI32S)
|
||||||
|
|
||||||
|
case ssa.OpWasmI32TruncSatF32U, ssa.OpWasmI32TruncSatF64U:
|
||||||
|
getValue64(s, v.Args[0])
|
||||||
|
s.Prog(v.Op.Asm())
|
||||||
|
s.Prog(wasm.AI64ExtendI32U)
|
||||||
|
|
||||||
case ssa.OpWasmF32DemoteF64:
|
case ssa.OpWasmF32DemoteF64:
|
||||||
getValue64(s, v.Args[0])
|
getValue64(s, v.Args[0])
|
||||||
s.Prog(v.Op.Asm())
|
s.Prog(v.Op.Asm())
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,6 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !wasm
|
|
||||||
|
|
||||||
// TODO fix this to work for wasm
|
|
||||||
// Doing more than this, however, expands the change.
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue