]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: optimize s==s for strings
authorKeith Randall <khr@golang.org>
Thu, 15 Jun 2023 16:14:12 +0000 (09:14 -0700)
committerKeith Randall <khr@golang.org>
Wed, 26 Jul 2023 17:17:28 +0000 (17:17 +0000)
s==s is always true for strings. This comes up in NaN testing in
generic code, where we want x==x to compile completely away except for
float types.

Fixes #60777

Change-Id: I3ce054b5121354de2f9751b010fb409f148cb637
Reviewed-on: https://go-review.googlesource.com/c/go/+/503795
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>

src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/codegen/strings.go

index cdb346321e561c28e170354b11978c5b2d0bbc9d..7047f6588fa3874c78daf97b652fbce0a135eff4 100644 (file)
   && isSameCall(callAux, "runtime.memequal")
   => (MakeResult (ConstBool <typ.Bool> [true]) mem)
 
+(Static(Call|LECall) {callAux} p q _ mem)
+  && isSameCall(callAux, "runtime.memequal")
+  && isSamePtr(p, q)
+  => (MakeResult (ConstBool <typ.Bool> [true]) mem)
+
 // Turn known-size calls to memclrNoHeapPointers into a Zero.
 // Note that we are using types.Types[types.TUINT8] instead of sptr.Type.Elem() - see issue 55122 and CL 431496 for more details.
 (SelectN [0] call:(StaticCall {sym} sptr (Const(64|32) [c]) mem))
index e5bd8bc36f7d61d4653d7399b034f38ad345b4de..781965f7b04ad8d0045d886d190d686d48ad4fa6 100644 (file)
@@ -397,6 +397,8 @@ func rewriteValuegeneric(v *Value) bool {
                return rewriteValuegeneric_OpSlicemask(v)
        case OpSqrt:
                return rewriteValuegeneric_OpSqrt(v)
+       case OpStaticCall:
+               return rewriteValuegeneric_OpStaticCall(v)
        case OpStaticLECall:
                return rewriteValuegeneric_OpStaticLECall(v)
        case OpStore:
@@ -28219,6 +28221,31 @@ func rewriteValuegeneric_OpSqrt(v *Value) bool {
        }
        return false
 }
+func rewriteValuegeneric_OpStaticCall(v *Value) bool {
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (StaticCall {callAux} p q _ mem)
+       // cond: isSameCall(callAux, "runtime.memequal") && isSamePtr(p, q)
+       // result: (MakeResult (ConstBool <typ.Bool> [true]) mem)
+       for {
+               if len(v.Args) != 4 {
+                       break
+               }
+               callAux := auxToCall(v.Aux)
+               mem := v.Args[3]
+               p := v.Args[0]
+               q := v.Args[1]
+               if !(isSameCall(callAux, "runtime.memequal") && isSamePtr(p, q)) {
+                       break
+               }
+               v.reset(OpMakeResult)
+               v0 := b.NewValue0(v.Pos, OpConstBool, typ.Bool)
+               v0.AuxInt = boolToAuxInt(true)
+               v.AddArg2(v0, mem)
+               return true
+       }
+       return false
+}
 func rewriteValuegeneric_OpStaticLECall(v *Value) bool {
        b := v.Block
        config := b.Func.Config
@@ -28506,6 +28533,26 @@ func rewriteValuegeneric_OpStaticLECall(v *Value) bool {
                v.AddArg2(v0, mem)
                return true
        }
+       // match: (StaticLECall {callAux} p q _ mem)
+       // cond: isSameCall(callAux, "runtime.memequal") && isSamePtr(p, q)
+       // result: (MakeResult (ConstBool <typ.Bool> [true]) mem)
+       for {
+               if len(v.Args) != 4 {
+                       break
+               }
+               callAux := auxToCall(v.Aux)
+               mem := v.Args[3]
+               p := v.Args[0]
+               q := v.Args[1]
+               if !(isSameCall(callAux, "runtime.memequal") && isSamePtr(p, q)) {
+                       break
+               }
+               v.reset(OpMakeResult)
+               v0 := b.NewValue0(v.Pos, OpConstBool, typ.Bool)
+               v0.AuxInt = boolToAuxInt(true)
+               v.AddArg2(v0, mem)
+               return true
+       }
        // match: (StaticLECall {callAux} _ (Const64 [0]) (Const64 [0]) mem)
        // cond: isSameCall(callAux, "runtime.makeslice")
        // result: (MakeResult (Addr <v.Type.FieldType(0)> {ir.Syms.Zerobase} (SB)) mem)
index 94512f5cd3253bfa0c3c9aabd6eac3086b8d281c..f98c062d1bbd0eb4e4709e93f8ee4a4f0c354f96 100644 (file)
@@ -67,4 +67,14 @@ func ConstantLoad() {
        bsink = []byte("0123456789ab")
 }
 
+// self-equality is always true. See issue 60777.
+func EqualSelf(s string) bool {
+       // amd64:`MOVL\t\$1, AX`,-`.*memequal.*`
+       return s == s
+}
+func NotEqualSelf(s string) bool {
+       // amd64:`XORL\tAX, AX`,-`.*memequal.*`
+       return s != s
+}
+
 var bsink []byte