diff --git a/src/cmd/compile/internal/ssa/_gen/Wasm.rules b/src/cmd/compile/internal/ssa/_gen/Wasm.rules index 8490fb39b8..9b582c8c00 100644 --- a/src/cmd/compile/internal/ssa/_gen/Wasm.rules +++ b/src/cmd/compile/internal/ssa/_gen/Wasm.rules @@ -390,6 +390,16 @@ (I64ShrU (I64Const [x]) (I64Const [y])) => (I64Const [int64(uint64(x) >> uint64(y))]) (I64ShrS (I64Const [x]) (I64Const [y])) => (I64Const [x >> uint64(y)]) +// Identity and absorption rules for AND/OR/XOR/MUL. +// These fire on nodes created during or after lowering. +(I64And x (I64Const [-1])) => x +(I64And x (I64Const [0])) => (I64Const [0]) +(I64Or x (I64Const [0])) => x +(I64Or x (I64Const [-1])) => (I64Const [-1]) +(I64Xor x (I64Const [0])) => x +(I64Mul x (I64Const [0])) => (I64Const [0]) +(I64Mul x (I64Const [1])) => 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 68a40f0c7f..c0ccd9611d 100644 --- a/src/cmd/compile/internal/ssa/rewriteWasm.go +++ b/src/cmd/compile/internal/ssa/rewriteWasm.go @@ -3949,6 +3949,26 @@ func rewriteValueWasm_OpWasmI64And(v *Value) bool { v.AuxInt = int64ToAuxInt(x & y) return true } + // match: (I64And x (I64Const [-1])) + // result: x + for { + x := v_0 + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != -1 { + break + } + v.copyOf(x) + return true + } + // match: (I64And x (I64Const [0])) + // result: (I64Const [0]) + for { + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 { + break + } + v.reset(OpWasmI64Const) + v.AuxInt = int64ToAuxInt(0) + return true + } // match: (I64And (I64Const [x]) y) // cond: y.Op != OpWasmI64Const // result: (I64And y (I64Const [x])) @@ -4448,6 +4468,26 @@ func rewriteValueWasm_OpWasmI64Mul(v *Value) bool { v.AuxInt = int64ToAuxInt(x * y) return true } + // match: (I64Mul x (I64Const [0])) + // result: (I64Const [0]) + for { + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 { + break + } + v.reset(OpWasmI64Const) + v.AuxInt = int64ToAuxInt(0) + return true + } + // match: (I64Mul x (I64Const [1])) + // result: x + for { + x := v_0 + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 1 { + break + } + v.copyOf(x) + return true + } // match: (I64Mul (I64Const [x]) y) // cond: y.Op != OpWasmI64Const // result: (I64Mul y (I64Const [x])) @@ -4564,6 +4604,26 @@ func rewriteValueWasm_OpWasmI64Or(v *Value) bool { v.AuxInt = int64ToAuxInt(x | y) return true } + // match: (I64Or x (I64Const [0])) + // result: x + for { + x := v_0 + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 { + break + } + v.copyOf(x) + return true + } + // match: (I64Or x (I64Const [-1])) + // result: (I64Const [-1]) + for { + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != -1 { + break + } + v.reset(OpWasmI64Const) + v.AuxInt = int64ToAuxInt(-1) + return true + } // match: (I64Or (I64Const [x]) y) // cond: y.Op != OpWasmI64Const // result: (I64Or y (I64Const [x])) @@ -4788,6 +4848,16 @@ func rewriteValueWasm_OpWasmI64Xor(v *Value) bool { v.AuxInt = int64ToAuxInt(x ^ y) return true } + // match: (I64Xor x (I64Const [0])) + // result: x + for { + x := v_0 + if v_1.Op != OpWasmI64Const || auxIntToInt64(v_1.AuxInt) != 0 { + break + } + v.copyOf(x) + return true + } // match: (I64Xor (I64Const [x]) y) // cond: y.Op != OpWasmI64Const // result: (I64Xor y (I64Const [x]))