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>
This commit is contained in:
George Adams
2026-03-09 08:56:37 +00:00
committed by Gopher Robot
parent 28b1d8886b
commit def4e491be
2 changed files with 80 additions and 0 deletions

View File

@@ -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]))

View File

@@ -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]))