diff --git a/src/cmd/compile/internal/ssa/_gen/Wasm.rules b/src/cmd/compile/internal/ssa/_gen/Wasm.rules index 3fef540658..31d37db657 100644 --- a/src/cmd/compile/internal/ssa/_gen/Wasm.rules +++ b/src/cmd/compile/internal/ssa/_gen/Wasm.rules @@ -412,6 +412,13 @@ (I64Extend32S (I64Extend8S x)) => (I64Extend8S x) (I64Extend16S (I64Extend8S x)) => (I64Extend8S x) +// Sign-extend of a value already zero-extended from fewer bits is a no-op. +// E.g. (I64Extend32S (I64And x (I64Const [0xff]))) — top 33 bits are already +// zero, so sign-extending from 32 is identity. +(I64Extend32S x:(I64And _ (I64Const [c]))) && c >= 0 && int64(int32(c)) == c => x +(I64Extend16S x:(I64And _ (I64Const [c]))) && c >= 0 && int64(int16(c)) == c => x +(I64Extend8S x:(I64And _ (I64Const [c]))) && c >= 0 && int64(int8(c)) == c => x + // TODO: declare these operations as commutative and get rid of these rules? (I64Add (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Add y (I64Const [x])) (I64Mul (I64Const [x]) y) && y.Op != OpWasmI64Const => (I64Mul y (I64Const [x])) diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go index 80c7855a45..1c9f5073e3 100644 --- a/src/cmd/compile/internal/ssa/rewriteWasm.go +++ b/src/cmd/compile/internal/ssa/rewriteWasm.go @@ -4135,6 +4135,26 @@ func rewriteValueWasm_OpWasmI64Extend16S(v *Value) bool { v.AddArg(x) return true } + // match: (I64Extend16S x:(I64And _ (I64Const [c]))) + // cond: c >= 0 && int64(int16(c)) == c + // result: x + for { + x := v_0 + if x.Op != OpWasmI64And { + break + } + _ = x.Args[1] + x_1 := x.Args[1] + if x_1.Op != OpWasmI64Const { + break + } + c := auxIntToInt64(x_1.AuxInt) + if !(c >= 0 && int64(int16(c)) == c) { + break + } + v.copyOf(x) + return true + } return false } func rewriteValueWasm_OpWasmI64Extend32S(v *Value) bool { @@ -4172,6 +4192,26 @@ func rewriteValueWasm_OpWasmI64Extend32S(v *Value) bool { v.AddArg(x) return true } + // match: (I64Extend32S x:(I64And _ (I64Const [c]))) + // cond: c >= 0 && int64(int32(c)) == c + // result: x + for { + x := v_0 + if x.Op != OpWasmI64And { + break + } + _ = x.Args[1] + x_1 := x.Args[1] + if x_1.Op != OpWasmI64Const { + break + } + c := auxIntToInt64(x_1.AuxInt) + if !(c >= 0 && int64(int32(c)) == c) { + break + } + v.copyOf(x) + return true + } return false } func rewriteValueWasm_OpWasmI64Extend8S(v *Value) bool { @@ -4187,6 +4227,26 @@ func rewriteValueWasm_OpWasmI64Extend8S(v *Value) bool { v.AddArg(x) return true } + // match: (I64Extend8S x:(I64And _ (I64Const [c]))) + // cond: c >= 0 && int64(int8(c)) == c + // result: x + for { + x := v_0 + if x.Op != OpWasmI64And { + break + } + _ = x.Args[1] + x_1 := x.Args[1] + if x_1.Op != OpWasmI64Const { + break + } + c := auxIntToInt64(x_1.AuxInt) + if !(c >= 0 && int64(int8(c)) == c) { + break + } + v.copyOf(x) + return true + } return false } func rewriteValueWasm_OpWasmI64LeU(v *Value) bool {