From d0964e172b83db45d167b21e93b79fe86b158760 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 15 Jun 2023 09:14:12 -0700 Subject: [PATCH] cmd/compile: optimize s==s for strings 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 Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot Run-TryBot: Keith Randall --- .../compile/internal/ssa/_gen/generic.rules | 5 ++ .../compile/internal/ssa/rewritegeneric.go | 47 +++++++++++++++++++ test/codegen/strings.go | 10 ++++ 3 files changed, 62 insertions(+) diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index cdb346321e..7047f6588f 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -2121,6 +2121,11 @@ && isSameCall(callAux, "runtime.memequal") => (MakeResult (ConstBool [true]) mem) +(Static(Call|LECall) {callAux} p q _ mem) + && isSameCall(callAux, "runtime.memequal") + && isSamePtr(p, q) + => (MakeResult (ConstBool [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)) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index e5bd8bc36f..781965f7b0 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -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 [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 [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 {ir.Syms.Zerobase} (SB)) mem) diff --git a/test/codegen/strings.go b/test/codegen/strings.go index 94512f5cd3..f98c062d1b 100644 --- a/test/codegen/strings.go +++ b/test/codegen/strings.go @@ -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 -- 2.44.0