(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)
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 {
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
package codegen
-import "unsafe"
+import (
+ "cmp"
+ "unsafe"
+)
// This file contains code generation tests related to the comparison
// operators.
// arm64:`CMP`,`CSET`,`CSEL`
return (p1.X-p3.X)*(p2.Y-p3.Y)-(p2.X-p3.X)*(p1.Y-p3.Y) < 0
}
+
+func cmpstring1(x, y string) int {
+ // amd64:".*cmpstring"
+ if x < y {
+ return -1
+ }
+ // amd64:-".*cmpstring"
+ if x > y {
+ return +1
+ }
+ return 0
+}
+func cmpstring2(x, y string) int {
+ // We want to fail if there are two calls to cmpstring.
+ // They will both have the same line number, so a test
+ // like in cmpstring1 will not work. Instead, we
+ // look for spill/restore instructions, which only
+ // need to exist if there are 2 calls.
+ //amd64:-`MOVQ\t.*\(SP\)`
+ return cmp.Compare(x, y)
+}