]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add rule for post-decomposed growslice optimization
authorKeith Randall <khr@golang.org>
Fri, 28 Oct 2022 21:14:24 +0000 (14:14 -0700)
committerKeith Randall <khr@google.com>
Mon, 31 Oct 2022 21:40:49 +0000 (21:40 +0000)
The recently added rule only works before decomposing slices.
Add a rule that works after decomposing slices.

The reason we need the latter is because although the length may
be a constant, it can be hidden inside a slice that is not constant
(its pointer or capacity might be changing). By applying this
optimization after decomposing slices, we can find more cases
where it applies.

Fixes #56440

Change-Id: I0094e59eee3065ab4d210defdda8227a6e897420
Reviewed-on: https://go-review.googlesource.com/c/go/+/446277
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/codegen/issue56440.go

index 0fc0f5443397b02cf87cab76c84289dd81b128bf..d5f9e5be636b56ced91c8fec8f45142cacb3efc8 100644 (file)
 // The exception here is that if the new length is a constant, avoiding spilling it
 // is pointless and its constantness is sometimes useful for subsequent optimizations.
 // See issue 56440.
+// Note there are 2 rules here, one for the pre-decomposed []T result and one for
+// the post-decomposed (*T,int,int) result. (The latter is generated after call expansion.)
 (SliceLen (SelectN [0] (StaticLECall {sym} _ newLen:(Const(64|32)) _ _ _ _))) && isSameCall(sym, "runtime.growslice") => newLen
+(SelectN [1] (StaticCall {sym} _ newLen:(Const(64|32)) _ _ _ _)) && v.Type.IsInteger() && isSameCall(sym, "runtime.growslice") => newLen
 
 // Collapse moving A -> B -> C into just A -> C.
 // Later passes (deadstore, elim unread auto) will remove the A -> B move, if possible.
index 6598c0e483f9e63678f2bc1466c5d55f75ef91b4..a76f55813f8c804e772c3e1f3187c52e0020f18b 100644 (file)
@@ -26621,6 +26621,38 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool {
                v.copyOf(x)
                return true
        }
+       // match: (SelectN [1] (StaticCall {sym} _ newLen:(Const64) _ _ _ _))
+       // cond: v.Type.IsInteger() && isSameCall(sym, "runtime.growslice")
+       // result: newLen
+       for {
+               if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpStaticCall || len(v_0.Args) != 6 {
+                       break
+               }
+               sym := auxToCall(v_0.Aux)
+               _ = v_0.Args[1]
+               newLen := v_0.Args[1]
+               if newLen.Op != OpConst64 || !(v.Type.IsInteger() && isSameCall(sym, "runtime.growslice")) {
+                       break
+               }
+               v.copyOf(newLen)
+               return true
+       }
+       // match: (SelectN [1] (StaticCall {sym} _ newLen:(Const32) _ _ _ _))
+       // cond: v.Type.IsInteger() && isSameCall(sym, "runtime.growslice")
+       // result: newLen
+       for {
+               if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpStaticCall || len(v_0.Args) != 6 {
+                       break
+               }
+               sym := auxToCall(v_0.Aux)
+               _ = v_0.Args[1]
+               newLen := v_0.Args[1]
+               if newLen.Op != OpConst32 || !(v.Type.IsInteger() && isSameCall(sym, "runtime.growslice")) {
+                       break
+               }
+               v.copyOf(newLen)
+               return true
+       }
        return false
 }
 func rewriteValuegeneric_OpSignExt16to32(v *Value) bool {
index 36b52ace03c41186d0acf6861ba17cc82471873f..c6c1e667890ab99e284c97b1c33cce3d6b2b3c82 100644 (file)
@@ -16,3 +16,19 @@ func f(x []int) int {
        // amd64:`MOVQ\t40\(.*\),`
        return x[len(s)]
 }
+
+func g(x []int, p *bool) int {
+       s := make([]int, 3)
+       for {
+               s = s[:3]
+               if cap(s) < 5 {
+                       s = make([]int, 3, 5)
+               }
+               s = append(s, 4, 5)
+               if *p {
+                       // amd64:`MOVQ\t40\(.*\),`
+                       return x[len(s)]
+               }
+       }
+       return 0
+}