diff --git a/src/cmd/compile/internal/ssa/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules index c10ff2fa43d..ea12c5d617a 100644 --- a/src/cmd/compile/internal/ssa/gen/Wasm.rules +++ b/src/cmd/compile/internal/ssa/gen/Wasm.rules @@ -377,6 +377,10 @@ (I64Ne (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Ne y (I64Const [x])) (I64Eq x (I64Const [0])) => (I64Eqz x) +(I64LtU (I64Const [0]) x) => (I64Eqz (I64Eqz x)) +(I64LeU x (I64Const [0])) => (I64Eqz x) +(I64LtU x (I64Const [1])) => (I64Eqz x) +(I64LeU (I64Const [1]) x) => (I64Eqz (I64Eqz x)) (I64Ne x (I64Const [0])) => (I64Eqz (I64Eqz x)) (I64Add x (I64Const [y])) => (I64AddConst [y] x) diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go index 16e6f96917a..52b6f6bfc79 100644 --- a/src/cmd/compile/internal/ssa/rewriteWasm.go +++ b/src/cmd/compile/internal/ssa/rewriteWasm.go @@ -591,6 +591,8 @@ func rewriteValueWasm(v *Value) bool { return rewriteValueWasm_OpWasmI64Eq(v) case OpWasmI64Eqz: return rewriteValueWasm_OpWasmI64Eqz(v) + case OpWasmI64LeU: + return rewriteValueWasm_OpWasmI64LeU(v) case OpWasmI64Load: return rewriteValueWasm_OpWasmI64Load(v) case OpWasmI64Load16S: @@ -605,6 +607,8 @@ func rewriteValueWasm(v *Value) bool { return rewriteValueWasm_OpWasmI64Load8S(v) case OpWasmI64Load8U: return rewriteValueWasm_OpWasmI64Load8U(v) + case OpWasmI64LtU: + return rewriteValueWasm_OpWasmI64LtU(v) case OpWasmI64Mul: return rewriteValueWasm_OpWasmI64Mul(v) case OpWasmI64Ne: @@ -3824,6 +3828,37 @@ func rewriteValueWasm_OpWasmI64Eqz(v *Value) bool { } return false } +func rewriteValueWasm_OpWasmI64LeU(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (I64LeU x (I64Const [0])) + // result: (I64Eqz x) + for { + x := v_0 + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 { + break + } + v.reset(OpWasmI64Eqz) + v.AddArg(x) + return true + } + // match: (I64LeU (I64Const [1]) x) + // result: (I64Eqz (I64Eqz x)) + for { + if v_0.Op != OpWasmI64Const || auxIntToInt64(v_0.AuxInt) != 1 { + break + } + x := v_1 + v.reset(OpWasmI64Eqz) + v0 := b.NewValue0(v.Pos, OpWasmI64Eqz, typ.Bool) + v0.AddArg(x) + v.AddArg(v0) + return true + } + return false +} func rewriteValueWasm_OpWasmI64Load(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -4070,6 +4105,37 @@ func rewriteValueWasm_OpWasmI64Load8U(v *Value) bool { } return false } +func rewriteValueWasm_OpWasmI64LtU(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (I64LtU (I64Const [0]) x) + // result: (I64Eqz (I64Eqz x)) + for { + if v_0.Op != OpWasmI64Const || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_1 + v.reset(OpWasmI64Eqz) + v0 := b.NewValue0(v.Pos, OpWasmI64Eqz, typ.Bool) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (I64LtU x (I64Const [1])) + // result: (I64Eqz x) + for { + x := v_0 + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 1 { + break + } + v.reset(OpWasmI64Eqz) + v.AddArg(x) + return true + } + return false +} func rewriteValueWasm_OpWasmI64Mul(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index 3c2dcb7eba0..02bed386615 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -456,3 +456,83 @@ func UintGeqOne(a uint8, b uint16, c uint32, d uint64) int { } return 0 } + +func CmpToZeroU_ex1(a uint8, b uint16, c uint32, d uint64) int { + // wasm:"I64Eqz"-"I64LtU" + if 0 < a { + return 1 + } + // wasm:"I64Eqz"-"I64LtU" + if 0 < b { + return 1 + } + // wasm:"I64Eqz"-"I64LtU" + if 0 < c { + return 1 + } + // wasm:"I64Eqz"-"I64LtU" + if 0 < d { + return 1 + } + return 0 +} + +func CmpToZeroU_ex2(a uint8, b uint16, c uint32, d uint64) int { + // wasm:"I64Eqz"-"I64LeU" + if a <= 0 { + return 1 + } + // wasm:"I64Eqz"-"I64LeU" + if b <= 0 { + return 1 + } + // wasm:"I64Eqz"-"I64LeU" + if c <= 0 { + return 1 + } + // wasm:"I64Eqz"-"I64LeU" + if d <= 0 { + return 1 + } + return 0 +} + +func CmpToOneU_ex1(a uint8, b uint16, c uint32, d uint64) int { + // wasm:"I64Eqz"-"I64LtU" + if a < 1 { + return 1 + } + // wasm:"I64Eqz"-"I64LtU" + if b < 1 { + return 1 + } + // wasm:"I64Eqz"-"I64LtU" + if c < 1 { + return 1 + } + // wasm:"I64Eqz"-"I64LtU" + if d < 1 { + return 1 + } + return 0 +} + +func CmpToOneU_ex2(a uint8, b uint16, c uint32, d uint64) int { + // wasm:"I64Eqz"-"I64LeU" + if 1 <= a { + return 1 + } + // wasm:"I64Eqz"-"I64LeU" + if 1 <= b { + return 1 + } + // wasm:"I64Eqz"-"I64LeU" + if 1 <= c { + return 1 + } + // wasm:"I64Eqz"-"I64LeU" + if 1 <= d { + return 1 + } + return 0 +}