aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorGeorge Adams <georgeadams1995@gmail.com>2026-03-18 09:16:54 +0000
committerGopher Robot <gobot@golang.org>2026-03-20 08:51:08 -0700
commit55de3efde3a2e7789b866a66c81a1fcd7c374f09 (patch)
tree76358568b585ec09e23752bf76072096a47d66e4 /src/cmd
parent686b127fe865e25c1d92a78ba0b56224f3fc0acf (diff)
downloadgo-55de3efde3a2e7789b866a66c81a1fcd7c374f09.tar.xz
cmd/compile: elide sign-extend after zero-extend for wasm
Add rules to eliminate sign-extension of values that have already been zero-extended from fewer bits via an I64And mask: (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 When a value has been masked to fit within the non-negative range of the sign-extension width, the upper bits are already zero and sign- extending is a no-op. For example, (I64Extend32S (I64And x 0xff)) can be elided because 0xff fits in a signed int32, so bit 31 is guaranteed to be zero and sign-extending from 32 bits is identity. Cq-Include-Trybots: luci.golang.try:gotip-wasip1-wasm_wasmtime,gotip-wasip1-wasm_wazero Change-Id: Ia54d67358756e47ca7635a6a8ca4beadb003820a Reviewed-on: https://go-review.googlesource.com/c/go/+/756320 Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Carlos Amedee <carlos@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/ssa/_gen/Wasm.rules7
-rw-r--r--src/cmd/compile/internal/ssa/rewriteWasm.go60
2 files changed, 67 insertions, 0 deletions
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 {