aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Adams <georgeadams1995@gmail.com>2026-03-09 08:56:37 +0000
committerGopher Robot <gobot@golang.org>2026-03-10 04:52:13 -0700
commitdef4e491be636d5fda1f1d36bd17fbf3f8a37ea7 (patch)
tree68299f889ca5e8557790fe8f1898ca06eebefda5
parent28b1d8886b3bd5645f8bfebb7713358a1551d435 (diff)
downloadgo-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>
-rw-r--r--src/cmd/compile/internal/ssa/_gen/Wasm.rules10
-rw-r--r--src/cmd/compile/internal/ssa/rewriteWasm.go70
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]))