[PATCH] fix non-canonical RTL produced by expand
Paolo Bonzini
paolo.bonzini@lu.unisi.ch
Wed Sep 14 11:44:00 GMT 2005
I found one thing while researching non-canonical RTL produced by
expand. The thing is that expand_binop, while expanding multi-word
operations, produces RTL like this:
(set (subreg:SI (reg:DI 64) 0)
(and:SI (subreg:SI (reg:DI 63) 0)
(mem:SI (reg/f:SI 62) [2 S4 A64])))
which was extracted from the .expand dump of this:
unsigned long long b, w;
int f(int wtm, long long mask)
{
unsigned long long *p[2];
p[0] = &b;
p[1] = &w;
if (*p[!wtm] & mask)
return wtm;
else
return -1;
}
As nice as it may seem, this RTL is not canonical. The subreg is placed
first by expand_binop because it only tries to canonicalize the position
of REGs, and does not rely on commutative_operand_precedence:
if (((target == 0 || REG_P (target))
? ((REG_P (op1)
&& !REG_P (op0))
|| target == op1)
: rtx_equal_p (op1, target))
|| GET_CODE (op0) == CONST_INT)
{
temp = op1;
op1 = op0;
op0 = temp;
}
This almost always produces canonical expressions because all objects
(RTX class = RTX_OBJECT) have the same precedence with respect to
canonicalization. The notable exception is expanding multi-word
operations: in this case operand_subword could be a SUBREG for the first
operand but not for the first. In this case, according to
commutative_operand_precedence, the SUBREG should go last. However,
only CSE is able to fix this bad choice of operand order.
In my tree (which performs less CSE than mainline), better code would be
produced from the above RTL than from the canonical (and (mem)
(subreg)). This results in a 3% performance decrease on crafty, which
this simple patch fixes.
Bootstrapped/regtested i686-pc-linux-gnu. Ok for mainline or 4.2?
Paolo
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: fix-com-op-prec.patch
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20050914/224b099f/attachment.ksh>
More information about the Gcc-patches
mailing list