From 8aa57f1e9dec8f7fc032aea82ecc19e2bb74cdcb Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Thu, 24 May 2018 04:11:05 +0200 Subject: [PATCH] cmd/compile: fix write barrier control value on wasm This commit fixes a regression with wasm caused by a367f44c18. It adds optimizations to the lowering rules of wasm to ensure that the lowered version of the code generated for write barriers is simple enough so it can be processed by Liveness.markUnsafePoints. Change-Id: Ic98f0dd3791fe1df23dcb34d2457fbde7ffce441 Reviewed-on: https://go-review.googlesource.com/114375 Run-TryBot: Cherry Zhang Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/plive.go | 2 +- src/cmd/compile/internal/ssa/gen/Wasm.rules | 15 +- src/cmd/compile/internal/ssa/rewriteWasm.go | 276 ++++++++++++++++++++ 3 files changed, 291 insertions(+), 2 deletions(-) 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])) -- 2.48.1