diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 28541870a2..f3f1ca3d39 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -729,7 +729,7 @@ func (lv *Liveness) markUnsafePoints() { v = v.Args[0] continue } - case ssa.Op386MOVLload, ssa.OpARM64MOVWUload, ssa.OpPPC64MOVWZload: + case ssa.Op386MOVLload, ssa.OpARM64MOVWUload, ssa.OpPPC64MOVWZload, ssa.OpWasmI64Load32U: // Args[0] is the address of the write // barrier control. Ignore Args[1], // which is the mem operand. diff --git a/src/cmd/compile/internal/ssa/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules index 7994fb7f5b..01f3f5a670 100644 --- a/src/cmd/compile/internal/ssa/gen/Wasm.rules +++ b/src/cmd/compile/internal/ssa/gen/Wasm.rules @@ -50,10 +50,16 @@ (OffPtr [off] ptr) && off > 0 -> (I64AddConst [off] ptr) // Lowering extension +// It is unnecessary to extend loads +(SignExt32to64 x:(I64Load32S _ _)) -> x +(SignExt16to(64|32) x:(I64Load16S _ _)) -> x +(SignExt8to(64|32|16) x:(I64Load8S _ _)) -> x +(ZeroExt32to64 x:(I64Load32U _ _)) -> x +(ZeroExt16to(64|32) x:(I64Load16U _ _)) -> x +(ZeroExt8to(64|32|16) x:(I64Load8U _ _)) -> x (SignExt32to64 x) -> (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32])) (SignExt16to(64|32) x) -> (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48])) (SignExt8to(64|32|16) x) -> (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56])) - (ZeroExt32to64 x) -> (I64ShrU (I64Shl x (I64Const [32])) (I64Const [32])) (ZeroExt16to(64|32) x) -> (I64ShrU (I64Shl x (I64Const [48])) (I64Const [48])) (ZeroExt8to(64|32|16) x) -> (I64ShrU (I64Shl x (I64Const [56])) (I64Const [56])) @@ -364,6 +370,10 @@ (I64Ne (I64Const [x]) (I64Const [y])) && x == y -> (I64Const [0]) (I64Ne (I64Const [x]) (I64Const [y])) && x != y -> (I64Const [1]) +(I64Shl (I64Const [x]) (I64Const [y])) -> (I64Const [x << uint64(y)]) +(I64ShrU (I64Const [x]) (I64Const [y])) -> (I64Const [int64(uint64(x) >> uint64(y))]) +(I64ShrS (I64Const [x]) (I64Const [y])) -> (I64Const [x >> uint64(y)]) + (I64Add (I64Const [x]) y) -> (I64Add y (I64Const [x])) (I64Mul (I64Const [x]) y) -> (I64Mul y (I64Const [x])) (I64And (I64Const [x]) y) -> (I64And y (I64Const [x])) @@ -374,6 +384,9 @@ (I64Eq (I64Const [x]) y) -> (I64Eq y (I64Const [x])) (I64Ne (I64Const [x]) y) -> (I64Ne y (I64Const [x])) +(I64Eq x (I64Const [0])) -> (I64Eqz x) +(I64Ne x (I64Const [0])) -> (I64Eqz (I64Eqz x)) + (I64Add x (I64Const [y])) -> (I64AddConst [y] x) (I64Eqz (I64Eqz (I64Eqz x))) -> (I64Eqz x) diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go index 2255561051..38822a7466 100644 --- a/src/cmd/compile/internal/ssa/rewriteWasm.go +++ b/src/cmd/compile/internal/ssa/rewriteWasm.go @@ -489,6 +489,12 @@ func rewriteValueWasm(v *Value) bool { return rewriteValueWasm_OpWasmI64Ne_0(v) case OpWasmI64Or: return rewriteValueWasm_OpWasmI64Or_0(v) + case OpWasmI64Shl: + return rewriteValueWasm_OpWasmI64Shl_0(v) + case OpWasmI64ShrS: + return rewriteValueWasm_OpWasmI64ShrS_0(v) + case OpWasmI64ShrU: + return rewriteValueWasm_OpWasmI64ShrU_0(v) case OpWasmI64Store: return rewriteValueWasm_OpWasmI64Store_0(v) case OpWasmI64Store16: @@ -4503,6 +4509,20 @@ func rewriteValueWasm_OpSignExt16to32_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (SignExt16to32 x:(I64Load16S _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load16S { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (SignExt16to32 x) // cond: // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48])) @@ -4526,6 +4546,20 @@ func rewriteValueWasm_OpSignExt16to64_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (SignExt16to64 x:(I64Load16S _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load16S { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (SignExt16to64 x) // cond: // result: (I64ShrS (I64Shl x (I64Const [48])) (I64Const [48])) @@ -4549,6 +4583,20 @@ func rewriteValueWasm_OpSignExt32to64_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (SignExt32to64 x:(I64Load32S _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load32S { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (SignExt32to64 x) // cond: // result: (I64ShrS (I64Shl x (I64Const [32])) (I64Const [32])) @@ -4572,6 +4620,20 @@ func rewriteValueWasm_OpSignExt8to16_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (SignExt8to16 x:(I64Load8S _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load8S { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (SignExt8to16 x) // cond: // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56])) @@ -4595,6 +4657,20 @@ func rewriteValueWasm_OpSignExt8to32_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (SignExt8to32 x:(I64Load8S _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load8S { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (SignExt8to32 x) // cond: // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56])) @@ -4618,6 +4694,20 @@ func rewriteValueWasm_OpSignExt8to64_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (SignExt8to64 x:(I64Load8S _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load8S { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (SignExt8to64 x) // cond: // result: (I64ShrS (I64Shl x (I64Const [56])) (I64Const [56])) @@ -5232,6 +5322,23 @@ func rewriteValueWasm_OpWasmI64Eq_0(v *Value) bool { v.AddArg(v0) return true } + // match: (I64Eq x (I64Const [0])) + // cond: + // result: (I64Eqz x) + for { + _ = v.Args[1] + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpWasmI64Const { + break + } + if v_1.AuxInt != 0 { + break + } + v.reset(OpWasmI64Eqz) + v.AddArg(x) + return true + } return false } func rewriteValueWasm_OpWasmI64Eqz_0(v *Value) bool { @@ -5540,6 +5647,25 @@ func rewriteValueWasm_OpWasmI64Ne_0(v *Value) bool { v.AddArg(v0) return true } + // match: (I64Ne x (I64Const [0])) + // cond: + // result: (I64Eqz (I64Eqz x)) + for { + _ = v.Args[1] + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpWasmI64Const { + break + } + if v_1.AuxInt != 0 { + break + } + v.reset(OpWasmI64Eqz) + v0 := b.NewValue0(v.Pos, OpWasmI64Eqz, typ.Bool) + v0.AddArg(x) + v.AddArg(v0) + return true + } return false } func rewriteValueWasm_OpWasmI64Or_0(v *Value) bool { @@ -5586,6 +5712,72 @@ func rewriteValueWasm_OpWasmI64Or_0(v *Value) bool { } return false } +func rewriteValueWasm_OpWasmI64Shl_0(v *Value) bool { + // match: (I64Shl (I64Const [x]) (I64Const [y])) + // cond: + // result: (I64Const [x << uint64(y)]) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpWasmI64Const { + break + } + x := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpWasmI64Const { + break + } + y := v_1.AuxInt + v.reset(OpWasmI64Const) + v.AuxInt = x << uint64(y) + return true + } + return false +} +func rewriteValueWasm_OpWasmI64ShrS_0(v *Value) bool { + // match: (I64ShrS (I64Const [x]) (I64Const [y])) + // cond: + // result: (I64Const [x >> uint64(y)]) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpWasmI64Const { + break + } + x := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpWasmI64Const { + break + } + y := v_1.AuxInt + v.reset(OpWasmI64Const) + v.AuxInt = x >> uint64(y) + return true + } + return false +} +func rewriteValueWasm_OpWasmI64ShrU_0(v *Value) bool { + // match: (I64ShrU (I64Const [x]) (I64Const [y])) + // cond: + // result: (I64Const [int64(uint64(x) >> uint64(y))]) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpWasmI64Const { + break + } + x := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpWasmI64Const { + break + } + y := v_1.AuxInt + v.reset(OpWasmI64Const) + v.AuxInt = int64(uint64(x) >> uint64(y)) + return true + } + return false +} func rewriteValueWasm_OpWasmI64Store_0(v *Value) bool { // match: (I64Store [off] (I64AddConst [off2] ptr) val mem) // cond: isU32Bit(off+off2) @@ -6138,6 +6330,20 @@ func rewriteValueWasm_OpZeroExt16to32_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (ZeroExt16to32 x:(I64Load16U _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load16U { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (ZeroExt16to32 x) // cond: // result: (I64ShrU (I64Shl x (I64Const [48])) (I64Const [48])) @@ -6161,6 +6367,20 @@ func rewriteValueWasm_OpZeroExt16to64_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (ZeroExt16to64 x:(I64Load16U _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load16U { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (ZeroExt16to64 x) // cond: // result: (I64ShrU (I64Shl x (I64Const [48])) (I64Const [48])) @@ -6184,6 +6404,20 @@ func rewriteValueWasm_OpZeroExt32to64_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (ZeroExt32to64 x:(I64Load32U _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load32U { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (ZeroExt32to64 x) // cond: // result: (I64ShrU (I64Shl x (I64Const [32])) (I64Const [32])) @@ -6207,6 +6441,20 @@ func rewriteValueWasm_OpZeroExt8to16_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (ZeroExt8to16 x:(I64Load8U _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load8U { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (ZeroExt8to16 x) // cond: // result: (I64ShrU (I64Shl x (I64Const [56])) (I64Const [56])) @@ -6230,6 +6478,20 @@ func rewriteValueWasm_OpZeroExt8to32_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (ZeroExt8to32 x:(I64Load8U _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load8U { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (ZeroExt8to32 x) // cond: // result: (I64ShrU (I64Shl x (I64Const [56])) (I64Const [56])) @@ -6253,6 +6515,20 @@ func rewriteValueWasm_OpZeroExt8to64_0(v *Value) bool { _ = b typ := &b.Func.Config.Types _ = typ + // match: (ZeroExt8to64 x:(I64Load8U _ _)) + // cond: + // result: x + for { + x := v.Args[0] + if x.Op != OpWasmI64Load8U { + break + } + _ = x.Args[1] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } // match: (ZeroExt8to64 x) // cond: // result: (I64ShrU (I64Shl x (I64Const [56])) (I64Const [56]))