Re: [RFA][middle-end/52306] Fix reload from creating invalid RTL

2014-02-10 Thread Ulrich Weigand
Jeff Law wrote:

 Anyway, we're processing the input reload for insn 73.  We see that insn 
 71's SET_DEST is the same as the input reload.  The input reload's 
 reloadreg is a0.  Replacing (reg:SI 48) with a0 in insn 71 produces an 
 insn which is recognized and which satisfies its constraints.  However, 
 we have a0 used within an increment addressing mode and elsewhere in the 
 same insn, which is invalid RTL.  Eventually we blow up in cselib due to 
 the invalid RTL.

I see, this analysis makes sense to me, and the fix looks straightforward.
Thanks for looking into this!

   PR middle-end/52306
   * reload1.c (emit_input_reload_insns): Do not create invalid RTL
   when changing the SET_DEST of a prior insn to avoid an input
   reload.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  ulrich.weig...@de.ibm.com



[RFA][middle-end/52306] Fix reload from creating invalid RTL

2014-02-09 Thread Jeff Law
As mentioned in the PR, we emit_input_reload_insns has this little 
optimization:


 /* If we are reloading a pseudo-register that was set by the previous
 insn, see if we can get rid of that pseudo-register entirely
 by redirecting the previous insn into our reload register.  */



When this optimization applies we change SET_DEST of that previous insn 
to be RELOADREG for the current insn's input reload.


Here's the relevant insns:

(insn 246 70 247 10 (set (reg:SI 8 %a0)
(reg:SI 54 [ ivtmp.11 ])) j.c:44 -1
 (nil))
(insn 247 246 71 10 (set (reg:SI 54 [ ivtmp.11 ])
(plus:SI (reg:SI 54 [ ivtmp.11 ])
(const_int 4 [0x4]))) j.c:44 141 {*addsi3_internal}
 (nil))
(insn 71 247 240 10 (set (reg/f:SI 48 [ D.1497 ])
(mem/f:SI (post_inc:SI (reg:SI 8 %a0)) [3 MEM[base: 0B, index: 
ivtmp.11_45, offset: 0B]+0 S4 A16])) j.c:44 39 {*movsi_m68k2}

 (expr_list:REG_INC (reg:SI 8 %a0)
(expr_list:REG_INC (reg:SI 8 %a0)
(nil
(note 240 71 73 NOTE_INSN_DELETED)
(insn 73 240 74 10 (set (cc0)
(compare (reg/f:SI 0 %d0 [orig:46 D.1493 ] [46])
(mem/f:SI (reg/f:SI 48 [ D.1497 ]) [3 _30-prefix+0 S4 
A16]))) j.c:44 16 {*m68k.md:492}

 (expr_list:REG_DEAD (reg/f:SI 48 [ D.1497 ])
(nil)))

Insns 246 and 247 are the reloads for the MEM inside insn 71 which has 
an autoincrement addressing mode.   Note carefully that insn 247 also 
does an increment and will set the equivalent memory location for the 
pseudo -- the autoincrement left in insn 71 is put there by reload in 
the hopes the value will be useful.


Anyway, we're processing the input reload for insn 73.  We see that insn 
71's SET_DEST is the same as the input reload.  The input reload's 
reloadreg is a0.  Replacing (reg:SI 48) with a0 in insn 71 produces an 
insn which is recognized and which satisfies its constraints.  However, 
we have a0 used within an increment addressing mode and elsewhere in the 
same insn, which is invalid RTL.  Eventually we blow up in cselib due to 
the invalid RTL.


This shows up in both the testcases in that BZ as well as an m68k bootstrap.

m68k bootstrap is in progress and will probably take a very long time. 
I've verified the resulting RTL for the reduced testcase in the PR looks 
good and the m68k bootstrap progresses further than it did before (still 
in the stage2 build)


OK for the trunk?


diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1237904..84c0ba1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-02-09  Jeff Law  l...@redhat.com
+
+   PR middle-end/52306
+   * reload1.c (emit_input_reload_insns): Do not create invalid RTL
+   when changing the SET_DEST of a prior insn to avoid an input
+   reload.
+
 2014-02-07  Jeff Law  l...@redhat.com
 
PR target/40977
diff --git a/gcc/reload1.c b/gcc/reload1.c
index bb761fe..b789ee8 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -7362,9 +7362,18 @@ emit_input_reload_insns (struct insn_chain *chain, 
struct reload *rl,
  /* Store into the reload register instead of the pseudo.  */
  SET_DEST (PATTERN (temp)) = reloadreg;
 
- /* Verify that resulting insn is valid.  */
+ /* Verify that resulting insn is valid. 
+
+Note that we have replaced the destination of TEMP with
+RELOADREG.  If TEMP references RELOADREG within an
+autoincrement addressing mode, then the resulting insn
+is ill-formed and we must reject this optimization.  */
  extract_insn (temp);
- if (constrain_operands (1))
+ if (constrain_operands (1)
+#ifdef AUTO_INC_DEC
+  ! find_reg_note (temp, REG_INC, reloadreg)
+#endif
+ )
{
  /* If the previous insn is an output reload, the source is
 a reload register, and its spill_reg_store entry will
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a50fa4b..214259c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-02-09  Jeff Law  l...@redhat.com
+
+   PR middle-end-52306
+   * gcc.c-torture/compile/pr52306.c: New test.
+
 2014-02-07  Jakub Jelinek  ja...@redhat.com
 
PR preprocessor/56824
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr52306.c 
b/gcc/testsuite/gcc.c-torture/compile/pr52306.c
new file mode 100644
index 000..e82cb2a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr52306.c
@@ -0,0 +1,84 @@
+/* PR middle-end/52306 */
+
+struct xmlNs {
+const unsigned char *prefix;
+};
+
+struct xmlNode {
+const unsigned char *name;
+struct xmlNs *ns;
+struct xmlNs *nsDef;
+};
+
+struct xsltTemplate {
+const unsigned char *name;
+int inheritedNsNr;
+void *inheritedNs;
+};
+
+struct xsltTemplate *xsltNewTemplate(void);
+void xsltGetQNameURI(unsigned char**);
+long xmlMalloc(unsigned long);
+void xsltGenericDebug(void);
+int xmlStrEqual(const unsigned char*,