gofrontend/gccgo: Improve identity comparison #21618
Labels
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone
The issue
gofrontend
currently generates very inefficient code forT$equal
andt1 == t2
when dealing with identity-comparable types (i.e. integers, pointers, and unpadded structs and arrays of such).For example:
T$equal
, and calls memcmp int1 == t2
. Fort1 == t2
,gofrontend
has a trick to turn this into a single 8-byte compare if the struct is aligned and size<=16 bytes, but it's not the case here.A solution
In 2016 gcc introduced the
__builtin_memcmp_eq
builtin that knows how to lower memcmp efficiently when the result is only used for equality comparison (i.e. equality with 0 instead of 3-way ordering). This is typically useful when the size is a constexpr (as is the case here).The basic idea is to replace a larger chain of integer comparisons loaded from contiguous memory locations into a smaller chain of bigger integer comparisons. Benefits are twofold:
As a first step, I’m simply proposing to replace calls to
runtime.memequal
with calls to__builtin_memcmp_eq
. This only improves the generated code.In first second example above, this would change the generated code (
gccgo -march=haswell -m64 -O3 -c test.go
) from:t1 == t2
T$equal
To (in both cases):
This is both smaller in terms of code size and much more efficient.
Going further
Simplifying
gofrontend
This also allows removing any specific code for handling sizes smaller than 16 bytes since they are already handled by gcc.
More performance improvements
This should be extended to piecewise-identity-comparable structs. For example, the following structure should be compared with three builtin calls (
{a}
,{c,d,e}
, and{f,g}
) and a float compare.The text was updated successfully, but these errors were encountered: