diff options
| author | George Adams <georgeadams1995@gmail.com> | 2026-03-09 08:56:37 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-03-10 04:52:13 -0700 |
| commit | def4e491be636d5fda1f1d36bd17fbf3f8a37ea7 (patch) | |
| tree | 68299f889ca5e8557790fe8f1898ca06eebefda5 /src/cmd | |
| parent | 28b1d8886b3bd5645f8bfebb7713358a1551d435 (diff) | |
| download | go-def4e491be636d5fda1f1d36bd17fbf3f8a37ea7.tar.xz | |
cmd/compile: add identity and absorption rules for wasm
Add post-lowering identity and absorption rules for I64And, I64Or,
I64Xor, and I64Mul with constant operands:
(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
The generic SSA rules handle these patterns before lowering, but
these rules catch cases where wasm-specific lowering or other
post-lowering optimization passes produce new nodes with identity
or absorbing constant operands.
For example, the complement rule lowers Com64(x) to
(I64Xor x (I64Const [-1])), and if x is later determined to be
all-ones, the I64And absorption rule can fold the result to zero.
Cq-Include-Trybots: luci.golang.try:gotip-wasip1-wasm_wasmtime,gotip-wasip1-wasm_wazero
Change-Id: Ie9a40e075662d4828a70e30b258d92ee171d0bc2
Reviewed-on: https://go-review.googlesource.com/c/go/+/752861
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/ssa/_gen/Wasm.rules | 10 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/rewriteWasm.go | 70 |
2 files changed, 80 insertions, 0 deletions
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])) |
