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

login
register
mail settings
Submitter Jeff Law
Date Feb. 10, 2014, 6:41 a.m.
Message ID <52F87488.3050905@redhat.com>
Download mbox | patch
Permalink /patch/318673/
State New
Headers show

Comments

Jeff Law - Feb. 10, 2014, 6:41 a.m.
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?

Patch

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  <law@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  <law@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  <law@redhat.com>
+
+	PR middle-end-52306
+	* gcc.c-torture/compile/pr52306.c: New test.
+
 2014-02-07  Jakub Jelinek  <jakub@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 0000000..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*, const unsigned char*);
+
+static void xsltGetInheritedNsList(
+    struct xsltTemplate *template,
+    struct xmlNode *node)
+{
+    struct xmlNs *cur;
+    struct xmlNs **ret;
+    int nbns = 0;
+    int maxns = 10;
+    int i;
+
+    if (template == 0
+	|| template->inheritedNsNr != 0
+	|| template->inheritedNs != 0)
+	return;
+
+    while (node != 0) {
+	cur = node->nsDef;
+	ret = (struct xmlNs**) xmlMalloc((maxns + 1) * sizeof(struct xmlNs*));
+	for (i = 0; i < nbns; i++)
+	    if (cur->prefix == ret[i]->prefix
+		|| xmlStrEqual(cur->prefix, 0))
+		break;
+
+	if (i >= nbns) {
+	    if (nbns >= maxns)
+		return;
+	    ret[nbns++] = cur;
+	}
+    }
+}
+
+static void
+xsltParseStylesheetTemplate(struct xmlNode *template)
+{
+    struct xsltTemplate *ret;
+    unsigned char *prop;
+
+    ret = xsltNewTemplate();
+    if (ret == 0)
+	return;
+    xsltGetInheritedNsList(ret, template);
+    xsltGenericDebug();
+    xsltGetQNameURI(&prop);
+    xmlStrEqual(0, ret->name);
+}
+
+void xsltParseStylesheetTop(struct xmlNode *cur)
+{
+    xmlStrEqual(0, 0);
+
+    while (cur != 0) {
+	if (xmlStrEqual(cur->name, 0))
+	    ;
+	else if (xmlStrEqual(cur->name, 0))
+	    ;
+	else if (xmlStrEqual(cur->name, 0))
+	    xsltParseStylesheetTemplate(cur);
+    }
+}
+