Skip to content

Commit

Permalink
cmd/compile: inline memequal(x, const, sz) for small sizes
Browse files Browse the repository at this point in the history
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 golang#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]>
  • Loading branch information
kels-ng authored and cherrymui committed Oct 6, 2021
1 parent ce72766 commit 810b08b
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/cmd/compile/internal/ssa/gen/generic.rules
Original file line number Diff line number Diff line change
Expand Up @@ -2011,12 +2011,30 @@
=> (Invalid)

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

(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [2]) mem)
&& isSameCall(callAux, "runtime.memequal")
&& symIsRO(scon)
&& canLoadUnaligned(config)
=> (MakeResult (Eq16 (Load <typ.Int16> sptr mem) (Const16 <typ.Int16> [int16(read16(scon,0,config.ctxt.Arch.ByteOrder))])) mem)

(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [4]) mem)
&& isSameCall(callAux, "runtime.memequal")
&& symIsRO(scon)
&& canLoadUnaligned(config)
=> (MakeResult (Eq32 (Load <typ.Int32> sptr mem) (Const32 <typ.Int32> [int32(read32(scon,0,config.ctxt.Arch.ByteOrder))])) mem)

(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [8]) mem)
&& isSameCall(callAux, "runtime.memequal")
&& symIsRO(scon)
&& canLoadUnaligned(config) && config.PtrSize == 8
=> (MakeResult (Eq64 (Load <typ.Int64> sptr mem) (Const64 <typ.Int64> [int64(read64(scon,0,config.ctxt.Arch.ByteOrder))])) mem)

// Evaluate constant address comparisons.
(EqPtr x x) => (ConstBool [true])
(NeqPtr x x) => (ConstBool [false])
Expand Down
5 changes: 5 additions & 0 deletions src/cmd/compile/internal/ssa/rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,11 @@ func isSameCall(sym interface{}, name string) bool {
return fn != nil && fn.String() == name
}

// canLoadUnaligned reports if the achitecture supports unaligned load operations
func canLoadUnaligned(c *Config) bool {
return c.ctxt.Arch.Alignment == 1
}

// nlz returns the number of leading zeros.
func nlz64(x int64) int { return bits.LeadingZeros64(uint64(x)) }
func nlz32(x int32) int { return bits.LeadingZeros32(uint32(x)) }
Expand Down
100 changes: 100 additions & 0 deletions src/cmd/compile/internal/ssa/rewritegeneric.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions test/codegen/comparisons.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,65 @@ func CmpToOneU_ex2(a uint8, b uint16, c uint32, d uint64) int {
}
return 0
}

// Check that small memequals are replaced with eq instructions

func equalConstString1() bool {
a := string("A")
b := string("Z")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a == b
}

func equalVarString1(a string) bool {
b := string("Z")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a[:1] == b
}

func equalConstString2() bool {
a := string("AA")
b := string("ZZ")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a == b
}

func equalVarString2(a string) bool {
b := string("ZZ")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a[:2] == b
}

func equalConstString4() bool {
a := string("AAAA")
b := string("ZZZZ")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a == b
}

func equalVarString4(a string) bool {
b := string("ZZZZ")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a[:4] == b
}

func equalConstString8() bool {
a := string("AAAAAAAA")
b := string("ZZZZZZZZ")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a == b
}

func equalVarString8(a string) bool {
b := string("ZZZZZZZZ")
// amd64:-".*memequal"
// arm64:-".*memequal"
return a[:8] == b
}

0 comments on commit 810b08b

Please sign in to comment.