This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix CSE bogus RTL creation
- From: Paul Brook <paul at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 15 Jun 2010 00:09:12 +0100
- Subject: [PATCH] Fix CSE bogus RTL creation
The patch below fixes a bug observed on an ARM target. The problematic code
starts with (mem (plus (reg) (reg))). CSE then replaces the first REG by a
CONST_INT. This results in invalid rtl: (plus (const_int) (reg)) - it is
expected that the CONST_INT be the second argument of the PLUS. This works its
way through the compiler and ends up confusing the assembly output patterns.
The patch below fixes this by calling simplify_rtx if any substitutions are
done. This should ensure that the result if canonical RTL.
My original fix tested specifically for my example above. However it was
suggested that I should use simplify_rtx instead, to catch similar latent
bugs.
Unfortunately the original testcase if very large and fragile. I am unable to
construct a testcase to reproduce this reliably.
Tested on arm-none-eabi and x86_64-linux.
Ok?
Paul
2010-06-14 Paul Brook <paul@codesourcery.com>
gcc/
* cse.c (cse_process_notes_1): Call simplify_rtx is a substitution
was made.
Index: gcc/cse.c
===================================================================
--- gcc/cse.c (revision 160724)
+++ gcc/cse.c (working copy)
@@ -5989,6 +5989,7 @@ cse_process_notes_1 (rtx x, rtx object,
enum rtx_code code = GET_CODE (x);
const char *fmt = GET_RTX_FORMAT (code);
int i;
+ bool did_change = false;
switch (code)
{
@@ -6057,7 +6058,18 @@ cse_process_notes_1 (rtx x, rtx object,
for (i = 0; i < GET_RTX_LENGTH (code); i++)
if (fmt[i] == 'e')
validate_change (object, &XEXP (x, i),
- cse_process_notes (XEXP (x, i), object, changed), 0);
+ cse_process_notes (XEXP (x, i), object, &did_change), 0);
+
+ /* We may need to rebuild the expression after substitution.
+ e.g. if the first operand of a PLUS is replaced by a constant. */
+ if (did_change)
+ {
+ rtx simplified;
+ *changed = true;
+ simplified = simplify_rtx(x);
+ if (simplified)
+ x = simplified;
+ }
return x;
}