diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/compile/internal/ssa/_gen/generic.rules | 9 | ||||
-rw-r--r-- | src/cmd/compile/internal/ssa/rewritegeneric.go | 30 | ||||
-rw-r--r-- | src/cmp/cmp.go | 14 |
3 files changed, 49 insertions, 4 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 { diff --git a/src/cmp/cmp.go b/src/cmp/cmp.go index 4d1af6a98c..a13834c398 100644 --- a/src/cmp/cmp.go +++ b/src/cmp/cmp.go @@ -40,13 +40,19 @@ func Less[T Ordered](x, y T) bool { func Compare[T Ordered](x, y T) int { xNaN := isNaN(x) yNaN := isNaN(y) - if xNaN && yNaN { - return 0 + if xNaN { + if yNaN { + return 0 + } + return -1 + } + if yNaN { + return +1 } - if xNaN || x < y { + if x < y { return -1 } - if yNaN || x > y { + if x > y { return +1 } return 0 |