This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix non-canonical RTL produced by expand, take 2
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 23 Nov 2005 18:54:47 +0100
- Subject: [PATCH] Fix non-canonical RTL produced by expand, take 2
This patch makes expand output canonical RTL for binary commutative
operations. The original patch, at
http://gcc.gnu.org/ml/gcc-patches/2005-09/msg00941.html, did not put a
REG first if the operands are both in the rtx class RTX_OBJECT and none
is equal to the target. This detail alone caused a regression in gap on
powerpc.
If the operands have the same precedence, this patch instead matches
exactly what expand is doing now. If the operands have different
precedence, CSE will always fix it (but it won't with fwprop -- this
patch fixes a regression on crafty caused by the fwprop patch).
Bootstrapped/regtested i686-pc-linux-gnu, tested on
powerpc-apple-darwin8.2.0 that the gap assembly code is the same with or
without the patch.
Ok for mainline?
Paolo
Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.297
diff -u -r1.297 optabs.c
--- optabs.c 29 Sep 2005 21:49:35 -0000 1.297
+++ optabs.c 10 Oct 2005 11:11:07 -0000
@@ -998,6 +998,30 @@
return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
}
+/* Return whether OP0 and OP1 should be swapped when expanding a commutative
+ binop. Order them according to commutative_operand_precedence and, if
+ possible, try to put TARGET or a pseudo first. */
+static bool
+swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
+{
+ int op0_prec = commutative_operand_precedence (op0);
+ int op1_prec = commutative_operand_precedence (op1);
+
+ if (op0_prec < op1_prec)
+ return true;
+
+ if (op0_prec > op1_prec)
+ return false;
+
+ /* With equal precedence, both orders are ok, but it is better if the
+ first operand is TARGET, or if both TARGET and OP0 are pseudos. */
+ if (target == 0 || REG_P (target))
+ return (REG_P (op1) && !REG_P (op0)) || target == op1;
+ else
+ return rtx_equal_p (op1, target);
+}
+
+
/* Generate code to perform an operation specified by BINOPTAB
on operands OP0 and OP1, with result having machine-mode MODE.
@@ -1073,12 +1097,7 @@
{
commutative_op = 1;
- if (((target == 0 || REG_P (target))
- ? ((REG_P (op1)
- && !REG_P (op0))
- || target == op1)
- : rtx_equal_p (op1, target))
- || GET_CODE (op0) == CONST_INT)
+ if (swap_commutative_operands_with_target (target, op0, op1))
{
temp = op1;
op1 = op0;