diff mbox

[x32] PATCH: PR target/47744: [x32] ICE: in reload_cse_simplify_operands, at postreload.c:403

Message ID 20110301192539.GA9243@intel.com
State New
Headers show

Commit Message

H.J. Lu March 1, 2011, 7:25 p.m. UTC
On Fri, Feb 18, 2011 at 11:06:01AM -0800, H.J. Lu wrote:
> On Tue, Feb 15, 2011 at 05:32:30AM -0800, H.J. Lu wrote:
> > Hi,
> > 
> > For x32 , IRA may generate
> > 
> >      (set (reg:SI 40 r11)
> >            (plus:SI (plus:SI (mult:SI (reg:SI 1 dx)
> > 		             (const_int 8))
> > 		    (subreg:SI (plus:DI (reg/f:DI 7 sp)
> > 					(const_int CONST1)) 0))
> > 	   (const_int CONST2)))
> > 
> > This patch translates it into
> > 
> >      (set (reg:SI 40 r11)
> >            (plus:SI (plus:SI (mult:SI (reg:SI 1 dx)
> > 		             (const_int 8))
> > 		    (reg/f:SI 7 sp))
> > 	   (const_int [CONST1 + CONST2])))
> > 
> > Checked into x32 branch.
> > 
> > H.J.
> > ---
> > From e1ceb6fc008e8139d20955d023fb20f347da8386 Mon Sep 17 00:00:00 2001
> > From: H.J. Lu <hjl.tools@gmail.com>
> > Date: Tue, 15 Feb 2011 05:20:06 -0800
> > Subject: [PATCH 2/2] Process (reg + const) base for TARGET_X32.
> > 
> > ---
> >  gcc/ChangeLog.x32                      |    6 +++
> >  gcc/config/i386/i386.c                 |   57 ++++++++++++++++++++++++++++++++
> >  gcc/testsuite/ChangeLog.x32            |    5 +++
> >  gcc/testsuite/gcc.dg/torture/pr47744.c |   21 ++++++++++++
> >  4 files changed, 89 insertions(+), 0 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/torture/pr47744.c
> > 
> > diff --git a/gcc/ChangeLog.x32 b/gcc/ChangeLog.x32
> > index b189b74..68e2bb8 100644
> > --- a/gcc/ChangeLog.x32
> > +++ b/gcc/ChangeLog.x32
> > @@ -1,3 +1,9 @@
> > +2011-02-15  H.J. Lu  <hongjiu.lu@intel.com>
> > +
> > +	PR target/47744
> > +	* config/i386/i386.c (ix86_decompose_address): Process
> > +	(reg + const) base for TARGET_X32.
> > +
> >  2011-02-14  H.J. Lu  <hongjiu.lu@intel.com>
> >  
> >  	* config/i386/i386.c (ix86_output_addr_vec_elt): Output
> 
> 
> I checked in this patch to add ix86_simplify_base_disp and use it
> for TARGET_X32 after reload is completed.
> 

I checked this patch into x32 branch to translate:

   (set (reg:SI 40 r11)
        (plus:SI (plus:SI (reg:SI 1 dx)
			  (subreg:SI (plus:DI (reg/f:DI 7 sp)
					      (const_int CONST1)) 0))
		 (const_int CONST2)))

into

   (set (reg:SI 40 r11)
        (plus:SI (plus:SI (reg:SI 1 dx)
			  (reg/f:SI 7 sp))
		 (const_int [CONST1 + CONST2])))


H.J.
----
diff mbox

Patch

diff --git a/gcc/ChangeLog.x32 b/gcc/ChangeLog.x32
index 191ed24..497866d 100644
--- a/gcc/ChangeLog.x32
+++ b/gcc/ChangeLog.x32
@@ -1,5 +1,12 @@ 
 2011-03-01  H.J. Lu  <hongjiu.lu@intel.com>
 
+	PR target/47744
+	* config/i386/i386.c (ix86_simplify_base_disp): Add PLUS base
+	support.
+	(ix86_decompose_address): Updated.
+
+2011-03-01  H.J. Lu  <hongjiu.lu@intel.com>
+
 	PR target/47926
 	* config/i386/i386.c (ix86_trampoline_init): Use movl instead
 	of movabs for x32.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 4f7433d..ad5bbc3 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -11620,10 +11620,26 @@  ix86_live_on_entry (bitmap regs)
 				   (const_int 8))
 			  (reg/f:SI 7 sp))
 		 (const_int [CONST1 + CONST2])))
-    */
+
+   If PLUS is true, we also translate
+
+   (set (reg:SI 40 r11)
+        (plus:SI (plus:SI (reg:SI 1 dx)
+			  (subreg:SI (plus:DI (reg/f:DI 7 sp)
+					      (const_int CONST1)) 0))
+		 (const_int CONST2)))
+
+   into
+
+   (set (reg:SI 40 r11)
+        (plus:SI (plus:SI (reg:SI 1 dx)
+			  (reg/f:SI 7 sp))
+		 (const_int [CONST1 + CONST2])))
+
+ */
 
 static void
-ix86_simplify_base_disp (rtx *base_p, rtx *disp_p)
+ix86_simplify_base_disp (rtx *base_p, rtx *disp_p, bool plus)
 {
   rtx base = *base_p;
   rtx disp;
@@ -11649,13 +11665,33 @@  ix86_simplify_base_disp (rtx *base_p, rtx *disp_p)
       if (REG_P (op0) && CONST_INT_P (op1))
 	{
 	  base = op0;
-	  addend  = op1;
+	  addend = op1;
 	}
       else if (REG_P (op1) && CONST_INT_P (op0))
 	{
 	  base = op1;
 	  addend = op0;
 	}
+      else if (plus
+	       && GET_CODE (op1) == SUBREG
+	       && GET_MODE (op1) == ptr_mode)
+	{
+	  op1 = SUBREG_REG (op1);
+	  if (GET_CODE (op1) == PLUS)
+	    {
+	      addend = XEXP (op1, 1);
+	      op1 = XEXP (op1, 0);
+	      if (REG_P (op1) && CONST_INT_P (addend))
+		{
+		  op1 = gen_rtx_REG (ptr_mode, REGNO (op1));
+		  *base_p = gen_rtx_PLUS (ptr_mode, op0, op1);
+		}
+	      else
+		return;
+	    }
+	  else
+	    return;
+	}
       else
 	return;
 
@@ -11664,7 +11700,8 @@  ix86_simplify_base_disp (rtx *base_p, rtx *disp_p)
       else
 	*disp_p = GEN_INT (INTVAL (disp) + INTVAL (addend));
 
-      *base_p = gen_rtx_REG (ptr_mode, REGNO (base));
+      if (!plus)
+	*base_p = gen_rtx_REG (ptr_mode, REGNO (base));
     }
 }
 
@@ -11706,15 +11743,20 @@  ix86_decompose_address (rtx addr, struct ix86_address *out)
 	  addends[n++] = XEXP (op, 1);
 	  op = XEXP (op, 0);
 	  /* Support 32bit address in x32 mode.  */
-	  if (TARGET_X32
-	      && reload_completed
-	      && GET_CODE (op) == ZERO_EXTEND
-	      && GET_MODE (op) == Pmode
-	      && GET_CODE (XEXP (op, 0)) == PLUS)
+	  if (TARGET_X32 && reload_completed)
 	    {
-	      op = XEXP (op, 0);
-	      if (n == 1)
-		ix86_simplify_base_disp (&op, &addends[0]);
+	      if (GET_CODE (op) == ZERO_EXTEND
+		  && GET_MODE (op) == Pmode
+		  && GET_CODE (XEXP (op, 0)) == PLUS)
+		{
+		  op = XEXP (op, 0);
+		  if (n == 1)
+		    ix86_simplify_base_disp (&op, &addends[0], false);
+		}
+	      else if (n == 1
+		       && GET_CODE (op) == PLUS
+		       && GET_MODE (op) == ptr_mode)
+		ix86_simplify_base_disp (&op, &addends[0], true);
 	    }
 	}
       while (GET_CODE (op) == PLUS);
@@ -11816,7 +11858,7 @@  ix86_decompose_address (rtx addr, struct ix86_address *out)
     disp = NULL_RTX;
 
   if (TARGET_X32 && reload_completed)
-    ix86_simplify_base_disp (&base, &disp);
+    ix86_simplify_base_disp (&base, &disp, false);
 
   base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
 
diff --git a/gcc/testsuite/ChangeLog.x32 b/gcc/testsuite/ChangeLog.x32
index 1e0dd89..c57f5ca 100644
--- a/gcc/testsuite/ChangeLog.x32
+++ b/gcc/testsuite/ChangeLog.x32
@@ -1,3 +1,8 @@ 
+2011-03-01  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR target/47744
+	* gcc.dg/torture/pr47744-3.c: New.
+
 2011-02-19  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR middle-end/47364
diff --git a/gcc/testsuite/gcc.dg/torture/pr47744-3.c b/gcc/testsuite/gcc.dg/torture/pr47744-3.c
new file mode 100644
index 0000000..5a5dd33
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr47744-3.c
@@ -0,0 +1,74 @@ 
+/* { dg-do compile } */
+
+typedef union rtunion_def {
+  struct rtx_def *rtx;
+} rtunion;
+typedef struct rtx_def {
+  unsigned short code;
+  rtunion fld[1];
+} *rtx;
+extern rtx recog_operand[];
+extern rtx *recog_operand_loc[];
+extern int reload_n_operands;
+extern void find_dummy_reload (int, int);
+extern int asm_noperands (rtx);
+extern int n_occurrences (char **);
+char operands_match[10][10];
+void find_reloads (rtx insn, int n_alternatives, int commutative)
+{
+  register int i, j;
+  int noperands;
+  char *constraints[10];
+  int address_reloaded[10];
+  int this_alternative[10];
+  char this_alternative_win[10];
+  int this_alternative_matches[10];
+  int this_alternative_number;
+  rtx body = ((insn)->fld[3].rtx);
+  int operand_mode[10];
+  if (body->code == 1)
+    {
+      reload_n_operands = noperands = asm_noperands (body);
+      n_alternatives = n_occurrences (constraints);
+    }
+  for (this_alternative_number = 0;
+       this_alternative_number < n_alternatives;
+       this_alternative_number++)
+    for (i = 0;
+	 i < noperands;
+	 i++)
+      {
+	register char *p = constraints[i];
+	register int win = 0;
+	int badop = 1;
+	int c;
+	register rtx operand = recog_operand[i];
+	int force_reload = 0;
+	this_alternative_win[i] = 0;
+	this_alternative[i] = 1;
+	while (*p && (c = *p++) != ',')
+	  switch (c)
+	    {
+	    case '4':
+	      c -= '0';
+	      this_alternative_matches[i] = c;
+	      if ((c != commutative
+		   || i != commutative + 1)
+		  && operands_match[c][i])
+		win = this_alternative_win[c];
+	      else
+		find_dummy_reload (operand_mode[i], this_alternative[c]);
+	      if (! win || force_reload)
+		for (j = 0; j < i; j++)
+		  if (this_alternative_matches[j]
+		      == this_alternative_matches[i])
+		    badop = 1;
+	      break;
+	    case '<':
+	      if (operand->code == 2
+		  && ! address_reloaded[i]
+		  && operand->fld[0].rtx->code == 3)
+		win = 1;
+	    }
+      }
+}