Skip to content

Commit 810b08b

Browse files
kels-ngcherrymui
authored andcommitted
cmd/compile: inline memequal(x, const, sz) for small sizes
This CL adds late expanded memequal(x, const, sz) inlining for 2, 4, 8 bytes size. This PoC is using the same method as CL 248404. This optimization fires about 100 times in Go compiler (1675 occurrences reduced to 1574, so -6%). Also, added unit-tests to codegen/comparisions.go file. Updates #37275 Change-Id: Ia52808d573cb706d1da8166c5746ede26f46c5da Reviewed-on: https://go-review.googlesource.com/c/go/+/328291 Reviewed-by: Cherry Mui <[email protected]> Run-TryBot: Cherry Mui <[email protected]> Trust: David Chase <[email protected]>
1 parent ce72766 commit 810b08b

File tree

4 files changed

+186
-1
lines changed

4 files changed

+186
-1
lines changed

src/cmd/compile/internal/ssa/gen/generic.rules

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2011,12 +2011,30 @@
20112011
=> (Invalid)
20122012

20132013
// for late-expanded calls, recognize memequal applied to a single constant byte
2014-
// TODO figure out breakeven number of bytes for this optimization.
2014+
// Support is limited by 1, 2, 4, 8 byte sizes
20152015
(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [1]) mem)
20162016
&& isSameCall(callAux, "runtime.memequal")
20172017
&& symIsRO(scon)
20182018
=> (MakeResult (Eq8 (Load <typ.Int8> sptr mem) (Const8 <typ.Int8> [int8(read8(scon,0))])) mem)
20192019

2020+
(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [2]) mem)
2021+
&& isSameCall(callAux, "runtime.memequal")
2022+
&& symIsRO(scon)
2023+
&& canLoadUnaligned(config)
2024+
=> (MakeResult (Eq16 (Load <typ.Int16> sptr mem) (Const16 <typ.Int16> [int16(read16(scon,0,config.ctxt.Arch.ByteOrder))])) mem)
2025+
2026+
(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [4]) mem)
2027+
&& isSameCall(callAux, "runtime.memequal")
2028+
&& symIsRO(scon)
2029+
&& canLoadUnaligned(config)
2030+
=> (MakeResult (Eq32 (Load <typ.Int32> sptr mem) (Const32 <typ.Int32> [int32(read32(scon,0,config.ctxt.Arch.ByteOrder))])) mem)
2031+
2032+
(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [8]) mem)
2033+
&& isSameCall(callAux, "runtime.memequal")
2034+
&& symIsRO(scon)
2035+
&& canLoadUnaligned(config) && config.PtrSize == 8
2036+
=> (MakeResult (Eq64 (Load <typ.Int64> sptr mem) (Const64 <typ.Int64> [int64(read64(scon,0,config.ctxt.Arch.ByteOrder))])) mem)
2037+
20202038
// Evaluate constant address comparisons.
20212039
(EqPtr x x) => (ConstBool [true])
20222040
(NeqPtr x x) => (ConstBool [false])

src/cmd/compile/internal/ssa/rewrite.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,11 @@ func isSameCall(sym interface{}, name string) bool {
415415
return fn != nil && fn.String() == name
416416
}
417417

418+
// canLoadUnaligned reports if the achitecture supports unaligned load operations
419+
func canLoadUnaligned(c *Config) bool {
420+
return c.ctxt.Arch.Alignment == 1
421+
}
422+
418423
// nlz returns the number of leading zeros.
419424
func nlz64(x int64) int { return bits.LeadingZeros64(uint64(x)) }
420425
func nlz32(x int32) int { return bits.LeadingZeros32(uint32(x)) }

src/cmd/compile/internal/ssa/rewritegeneric.go

Lines changed: 100 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/codegen/comparisons.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,3 +538,65 @@ func CmpToOneU_ex2(a uint8, b uint16, c uint32, d uint64) int {
538538
}
539539
return 0
540540
}
541+
542+
// Check that small memequals are replaced with eq instructions
543+
544+
func equalConstString1() bool {
545+
a := string("A")
546+
b := string("Z")
547+
// amd64:-".*memequal"
548+
// arm64:-".*memequal"
549+
return a == b
550+
}
551+
552+
func equalVarString1(a string) bool {
553+
b := string("Z")
554+
// amd64:-".*memequal"
555+
// arm64:-".*memequal"
556+
return a[:1] == b
557+
}
558+
559+
func equalConstString2() bool {
560+
a := string("AA")
561+
b := string("ZZ")
562+
// amd64:-".*memequal"
563+
// arm64:-".*memequal"
564+
return a == b
565+
}
566+
567+
func equalVarString2(a string) bool {
568+
b := string("ZZ")
569+
// amd64:-".*memequal"
570+
// arm64:-".*memequal"
571+
return a[:2] == b
572+
}
573+
574+
func equalConstString4() bool {
575+
a := string("AAAA")
576+
b := string("ZZZZ")
577+
// amd64:-".*memequal"
578+
// arm64:-".*memequal"
579+
return a == b
580+
}
581+
582+
func equalVarString4(a string) bool {
583+
b := string("ZZZZ")
584+
// amd64:-".*memequal"
585+
// arm64:-".*memequal"
586+
return a[:4] == b
587+
}
588+
589+
func equalConstString8() bool {
590+
a := string("AAAAAAAA")
591+
b := string("ZZZZZZZZ")
592+
// amd64:-".*memequal"
593+
// arm64:-".*memequal"
594+
return a == b
595+
}
596+
597+
func equalVarString8(a string) bool {
598+
b := string("ZZZZZZZZ")
599+
// amd64:-".*memequal"
600+
// arm64:-".*memequal"
601+
return a[:8] == b
602+
}

0 commit comments

Comments
 (0)