diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 00e8fcbe32e..8583cfae40c 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -989,6 +989,10 @@ (Const64 [0]) (Const64 [0])) +// Special rule to help constant slicing; len > 0 implies cap > 0 implies Slicemask is all 1 +(SliceMake (AddPtr x (And64 y (Slicemask _))) w:(Const64 [c]) z) && c > 0 => (SliceMake (AddPtr x y) w z) +(SliceMake (AddPtr x (And32 y (Slicemask _))) w:(Const32 [c]) z) && c > 0 => (SliceMake (AddPtr x y) w z) + // interface ops (ConstInterface) => (IMake diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index fe61ceaff2e..c9cff8651b7 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -422,6 +422,8 @@ func rewriteValuegeneric(v *Value) bool { return rewriteValuegeneric_OpSliceCap(v) case OpSliceLen: return rewriteValuegeneric_OpSliceLen(v) + case OpSliceMake: + return rewriteValuegeneric_OpSliceMake(v) case OpSlicePtr: return rewriteValuegeneric_OpSlicePtr(v) case OpSlicemask: @@ -30645,6 +30647,91 @@ func rewriteValuegeneric_OpSliceLen(v *Value) bool { } return false } +func rewriteValuegeneric_OpSliceMake(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (SliceMake (AddPtr x (And64 y (Slicemask _))) w:(Const64 [c]) z) + // cond: c > 0 + // result: (SliceMake (AddPtr x y) w z) + for { + if v_0.Op != OpAddPtr { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpAnd64 { + break + } + _ = v_0_1.Args[1] + v_0_1_0 := v_0_1.Args[0] + v_0_1_1 := v_0_1.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_1_0, v_0_1_1 = _i0+1, v_0_1_1, v_0_1_0 { + y := v_0_1_0 + if v_0_1_1.Op != OpSlicemask { + continue + } + w := v_1 + if w.Op != OpConst64 { + continue + } + c := auxIntToInt64(w.AuxInt) + z := v_2 + if !(c > 0) { + continue + } + v.reset(OpSliceMake) + v0 := b.NewValue0(v.Pos, OpAddPtr, t) + v0.AddArg2(x, y) + v.AddArg3(v0, w, z) + return true + } + break + } + // match: (SliceMake (AddPtr x (And32 y (Slicemask _))) w:(Const32 [c]) z) + // cond: c > 0 + // result: (SliceMake (AddPtr x y) w z) + for { + if v_0.Op != OpAddPtr { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpAnd32 { + break + } + _ = v_0_1.Args[1] + v_0_1_0 := v_0_1.Args[0] + v_0_1_1 := v_0_1.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_1_0, v_0_1_1 = _i0+1, v_0_1_1, v_0_1_0 { + y := v_0_1_0 + if v_0_1_1.Op != OpSlicemask { + continue + } + w := v_1 + if w.Op != OpConst32 { + continue + } + c := auxIntToInt32(w.AuxInt) + z := v_2 + if !(c > 0) { + continue + } + v.reset(OpSliceMake) + v0 := b.NewValue0(v.Pos, OpAddPtr, t) + v0.AddArg2(x, y) + v.AddArg3(v0, w, z) + return true + } + break + } + return false +} func rewriteValuegeneric_OpSlicePtr(v *Value) bool { v_0 := v.Args[0] // match: (SlicePtr (SliceMake (SlicePtr x) _ _)) diff --git a/test/prove.go b/test/prove.go index 70a27865cfd..6d2bb0962be 100644 --- a/test/prove.go +++ b/test/prove.go @@ -511,10 +511,10 @@ func f19() (e int64, err error) { func sm1(b []int, x int) { // Test constant argument to slicemask. - useSlice(b[2:8]) // ERROR "Proved slicemask not needed$" + useSlice(b[2:8]) // optimized away earlier by rewrite // Test non-constant argument with known limits. if cap(b) > 10 { - useSlice(b[2:]) + useSlice(b[2:]) // ERROR "Proved slicemask not needed$" } }