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 <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
This commit is contained in:
Keith Randall 2023-06-15 09:14:12 -07:00
parent f0894a00f4
commit d0964e172b
3 changed files with 62 additions and 0 deletions

View file

@ -2121,6 +2121,11 @@
&& 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))

View 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)

View 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