From patchwork Mon Jun 14 23:09:12 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix CSE bogus RTL creation Date: Mon, 14 Jun 2010 13:09:12 -0000 From: Paul Brook X-Patchwork-Id: 55595 Message-Id: <201006150009.13542.paul@codesourcery.com> To: gcc-patches@gcc.gnu.org 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 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; }