aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/ssa/_gen/generic.rules9
-rw-r--r--src/cmd/compile/internal/ssa/rewritegeneric.go30
2 files changed, 39 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules
index 4c475d31e0..398601e81b 100644
--- a/src/cmd/compile/internal/ssa/_gen/generic.rules
+++ b/src/cmd/compile/internal/ssa/_gen/generic.rules
@@ -2794,3 +2794,12 @@
(Load <t> (OffPtr [off] (Convert (Addr {sym} _) _) ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
(Load <t> (OffPtr [off] (ITab (IMake (Addr {sym} _) _))) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
(Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {sym} _) _) _))) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
+
+// Calling cmpstring a second time with the same arguments in the
+// same memory state can reuse the results of the first call.
+// See issue 61725.
+// Note that this could pretty easily generalize to any pure function.
+(StaticLECall {f} x y m:(SelectN [1] c:(StaticLECall {g} x y mem)))
+ && isSameCall(f, "runtime.cmpstring")
+ && isSameCall(g, "runtime.cmpstring")
+=> (MakeResult (SelectN [0] <typ.Int> c) m)
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index 468e9fa9c6..98c94bc1ba 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -29311,6 +29311,36 @@ func rewriteValuegeneric_OpStaticLECall(v *Value) bool {
v.AddArg2(v0, mem)
return true
}
+ // match: (StaticLECall {f} x y m:(SelectN [1] c:(StaticLECall {g} x y mem)))
+ // cond: isSameCall(f, "runtime.cmpstring") && isSameCall(g, "runtime.cmpstring")
+ // result: (MakeResult (SelectN [0] <typ.Int> c) m)
+ for {
+ if len(v.Args) != 3 {
+ break
+ }
+ f := auxToCall(v.Aux)
+ _ = v.Args[2]
+ x := v.Args[0]
+ y := v.Args[1]
+ m := v.Args[2]
+ if m.Op != OpSelectN || auxIntToInt64(m.AuxInt) != 1 {
+ break
+ }
+ c := m.Args[0]
+ if c.Op != OpStaticLECall || len(c.Args) != 3 {
+ break
+ }
+ g := auxToCall(c.Aux)
+ if x != c.Args[0] || y != c.Args[1] || !(isSameCall(f, "runtime.cmpstring") && isSameCall(g, "runtime.cmpstring")) {
+ break
+ }
+ v.reset(OpMakeResult)
+ v0 := b.NewValue0(v.Pos, OpSelectN, typ.Int)
+ v0.AuxInt = int64ToAuxInt(0)
+ v0.AddArg(c)
+ v.AddArg2(v0, m)
+ return true
+ }
return false
}
func rewriteValuegeneric_OpStore(v *Value) bool {