This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]