Skip to content

Commit

Permalink
cmd/compile: add saturating conversions on wasm
Browse files Browse the repository at this point in the history
This change adds the GOWASM option "satconv" to enable the generation
of experimental saturating (non-trapping) float-to-int conversions.
It improves the performance of the conversion by 42%.

Previously the conversions had already been augmented with helper
functions to have saturating behavior. Now Wasm.rules is always using
the new operation names and wasm/ssa.go is falling back to the helpers
if the feature is not enabled.

The feature is in phase 4 of the WebAssembly proposal process:
https://github.com/WebAssembly/meetings/blob/master/process/phases.md

More information on the feature can be found at:
https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md

Change-Id: Ic6c3688017054ede804b02b6b0ffd4a02ef33ad7
Reviewed-on: https://go-review.googlesource.com/c/go/+/170119
Reviewed-by: Cherry Zhang <[email protected]>
Run-TryBot: Cherry Zhang <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
neelance authored and Richard Musiol committed Apr 4, 2019
1 parent 1abf3aa commit cf8cc7f
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 42 deletions.
1 change: 1 addition & 0 deletions doc/install-source.html
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,7 @@ <h2 id="environment">Optional environment variables</h2>
The default is to use no experimental features.
</p>
<ul>
<li><code>GOWASM=satconv</code>: generate <a href="https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md">saturating (non-trapping) float-to-int conversions</a></li>
<li><code>GOWASM=signext</code>: generate <a href="https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md">sign-extension operators</a></li>
</ul>
</li>
Expand Down
16 changes: 8 additions & 8 deletions src/cmd/compile/internal/ssa/gen/Wasm.rules
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@
(Cvt64Uto32F x) -> (LoweredRound32F (F64ConvertI64U x))
(Cvt64Uto64F x) -> (F64ConvertI64U x)

(Cvt32Fto32 x) -> (I64TruncF64S x)
(Cvt32Fto64 x) -> (I64TruncF64S x)
(Cvt64Fto32 x) -> (I64TruncF64S x)
(Cvt64Fto64 x) -> (I64TruncF64S x)
(Cvt32Fto32U x) -> (I64TruncF64U x)
(Cvt32Fto64U x) -> (I64TruncF64U x)
(Cvt64Fto32U x) -> (I64TruncF64U x)
(Cvt64Fto64U x) -> (I64TruncF64U x)
(Cvt32Fto32 x) -> (I64TruncSatF64S x)
(Cvt32Fto64 x) -> (I64TruncSatF64S x)
(Cvt64Fto32 x) -> (I64TruncSatF64S x)
(Cvt64Fto64 x) -> (I64TruncSatF64S x)
(Cvt32Fto32U x) -> (I64TruncSatF64U x)
(Cvt32Fto64U x) -> (I64TruncSatF64U x)
(Cvt64Fto32U x) -> (I64TruncSatF64U x)
(Cvt64Fto64U x) -> (I64TruncSatF64U x)

(Cvt32Fto64F x) -> x
(Cvt64Fto32F x) -> (LoweredRound32F x)
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/ssa/gen/WasmOps.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ func init() {
{name: "F64Mul", asm: "F64Mul", argLength: 2, reg: fp21, typ: "Float64"}, // arg0 * arg1
{name: "F64Div", asm: "F64Div", argLength: 2, reg: fp21, typ: "Float64"}, // arg0 / arg1

{name: "I64TruncF64S", asm: "I64TruncF64S", argLength: 1, reg: regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer
{name: "I64TruncF64U", asm: "I64TruncF64U", argLength: 1, reg: regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to an unsigned integer
{name: "I64TruncSatF64S", asm: "I64TruncSatF64S", argLength: 1, reg: regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to a signed integer (saturating)
{name: "I64TruncSatF64U", asm: "I64TruncSatF64U", argLength: 1, reg: regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}, typ: "Int64"}, // truncates the float arg0 to an unsigned integer (saturating)
{name: "F64ConvertI64S", asm: "F64ConvertI64S", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}, typ: "Float64"}, // converts the signed integer arg0 to a float
{name: "F64ConvertI64U", asm: "F64ConvertI64U", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}, typ: "Float64"}, // converts the unsigned integer arg0 to a float

Expand Down
12 changes: 6 additions & 6 deletions src/cmd/compile/internal/ssa/opGen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 16 additions & 16 deletions src/cmd/compile/internal/ssa/rewriteWasm.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 15 additions & 6 deletions src/cmd/compile/internal/wasm/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/obj/wasm"
"cmd/internal/objabi"
)

func Init(arch *gc.Arch) {
Expand Down Expand Up @@ -307,15 +308,23 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value) {
}
s.Prog(wasm.AI64DivS)

case ssa.OpWasmI64TruncF64S:
case ssa.OpWasmI64TruncSatF64S:
getValue64(s, v.Args[0])
p := s.Prog(wasm.ACall)
p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: gc.WasmTruncS}
if objabi.GOWASM.SatConv {
s.Prog(v.Op.Asm())
} else {
p := s.Prog(wasm.ACall)
p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: gc.WasmTruncS}
}

case ssa.OpWasmI64TruncF64U:
case ssa.OpWasmI64TruncSatF64U:
getValue64(s, v.Args[0])
p := s.Prog(wasm.ACall)
p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: gc.WasmTruncU}
if objabi.GOWASM.SatConv {
s.Prog(v.Op.Asm())
} else {
p := s.Prog(wasm.ACall)
p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: gc.WasmTruncU}
}

case
ssa.OpWasmF64Neg, ssa.OpWasmF64ConvertI64S, ssa.OpWasmF64ConvertI64U,
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/alldocs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/cmd/go/internal/help/helpdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ Architecture-specific environment variables:
Valid values are hardfloat (default), softfloat.
GOWASM
For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
Valid values are: signext.
Valid values are satconv, signext.
Special-purpose environment variables:
Expand Down
9 changes: 9 additions & 0 deletions src/cmd/internal/obj/wasm/a.out.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,15 @@ const (
AI64Extend16S
AI64Extend32S

AI32TruncSatF32S // opcode 0xFC 0x00
AI32TruncSatF32U
AI32TruncSatF64S
AI32TruncSatF64U
AI64TruncSatF32S
AI64TruncSatF32U
AI64TruncSatF64S
AI64TruncSatF64U

ALast // Sentinel: End of low-level WebAssembly instructions.

ARESUMEPOINT
Expand Down
8 changes: 8 additions & 0 deletions src/cmd/internal/obj/wasm/anames.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions src/cmd/internal/obj/wasm/wasmobj.go
Original file line number Diff line number Diff line change
Expand Up @@ -886,16 +886,21 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
}

switch {
case p.As < AUnreachable || p.As >= ALast:
case p.As < AUnreachable:
panic(fmt.Sprintf("unexpected assembler op: %s", p.As))
case p.As < AEnd:
w.WriteByte(byte(p.As - AUnreachable + 0x00))
case p.As < ADrop:
w.WriteByte(byte(p.As - AEnd + 0x0B))
case p.As < AI32Load:
w.WriteByte(byte(p.As - ADrop + 0x1A))
default:
case p.As < AI32TruncSatF32S:
w.WriteByte(byte(p.As - AI32Load + 0x28))
case p.As < ALast:
w.WriteByte(0xFC)
w.WriteByte(byte(p.As - AI32TruncSatF32S + 0x00))
default:
panic(fmt.Sprintf("unexpected assembler op: %s", p.As))
}

switch p.As {
Expand Down
6 changes: 6 additions & 0 deletions src/cmd/internal/objabi/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@ func goppc64() int {

type gowasmFeatures struct {
SignExt bool
SatConv bool
}

func (f *gowasmFeatures) String() string {
var flags []string
if f.SatConv {
flags = append(flags, "satconv")
}
if f.SignExt {
flags = append(flags, "signext")
}
Expand All @@ -92,6 +96,8 @@ func (f *gowasmFeatures) String() string {
func gowasm() (f gowasmFeatures) {
for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
switch opt {
case "satconv":
f.SatConv = true
case "signext":
f.SignExt = true
case "":
Expand Down

0 comments on commit cf8cc7f

Please sign in to comment.