diff mbox

[lra] patch to fix a x86 wrong code generation

Message ID 4E05464D.7000704@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov June 25, 2011, 2:22 a.m. UTC
The following patch solves a bug which results in a wrong code 
generation of Maeno's algorithm of matrix multiplications on x86.

The patch was successfully bootstrapped on x86, ppc64, ia64.

2011-06-24  Vladimir Makarov <vmakarov@redhat.com>

         * lra-constraints.c (extract_loc_address_regs): Add an argument.
         Don't process the reg as an index reg on the top address level
         when it is added to the symbol.
         (extract_address_regs): Pass new argument to
         extract_loc_address_regs.
diff mbox

Patch

Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 175386)
+++ lra-constraints.c	(working copy)
@@ -383,8 +383,8 @@  ok_for_base_p_nonstrict (rtx reg, enum m
   return ok_for_base_p_1 (regno, mode, outer_code, index_code);
 }
 
-/* Process address part with location *LOC to extract address
-   characteristics.
+/* Process address part (or all address if TOP_P) with location *LOC
+   to extract address characteristics.
 
    If CONTEXT_P is false, we are looking at the base part of an
    address, otherwise we are looking at the index part.
@@ -393,7 +393,7 @@  ok_for_base_p_nonstrict (rtx reg, enum m
    give the context that the rtx appears in; MODIFY_P if *LOC is
    modified.  */
 static void
-extract_loc_address_regs (enum machine_mode mode,
+extract_loc_address_regs (bool top_p, enum machine_mode mode,
 			  rtx *loc, bool context_p, enum rtx_code outer_code,
 			  enum rtx_code index_code,
 			  bool modify_p, struct address *ad)
@@ -447,8 +447,8 @@  extract_loc_address_regs (enum machine_m
 	   must be in the first operand.  */
 	if (MAX_REGS_PER_ADDRESS == 1)
 	  {
-	    extract_loc_address_regs (mode, arg0_loc, false, PLUS, code1,
-				      modify_p, ad);
+	    extract_loc_address_regs (false, mode, arg0_loc, false, PLUS,
+				      code1, modify_p, ad);
 	    gcc_assert (CONSTANT_P (arg1)); /* It should be a displacement.  */
 	    ad->disp_loc = arg1_loc;
 	  }
@@ -458,11 +458,11 @@  extract_loc_address_regs (enum machine_m
 	   addresses are in canonical form.  */
 	else if (INDEX_REG_CLASS == base_reg_class (VOIDmode, PLUS, SCRATCH))
 	  {
-	    extract_loc_address_regs (mode, arg0_loc, false, PLUS, code1,
-				      modify_p, ad);
+	    extract_loc_address_regs (false, mode, arg0_loc, false, PLUS,
+				      code1, modify_p, ad);
 	    if (! CONSTANT_P (arg1))
-	      extract_loc_address_regs (mode, arg1_loc, true, PLUS, code0,
-					modify_p, ad);
+	      extract_loc_address_regs (false, mode, arg1_loc, true, PLUS,
+					code0, modify_p, ad);
 	    else
 	      ad->disp_loc = arg1_loc;
 	  }
@@ -471,15 +471,17 @@  extract_loc_address_regs (enum machine_m
 	   change what class the first operand must be.  */
 	else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
 	  {
-	    extract_loc_address_regs (mode, arg0_loc, context_p, PLUS, code1,
-				      modify_p, ad);
+	    extract_loc_address_regs (false, mode, arg0_loc, context_p, PLUS,
+				      code1, modify_p, ad);
 	    ad->disp_loc = arg1_loc;
 	  }
 	/* If the second operand is a symbolic constant, the first
-	   operand must be an index register.  */
+	   operand must be an index register but only if this part is
+	   all the address.  */
 	else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
 	  {
-	    extract_loc_address_regs (mode, arg0_loc, true, PLUS, code1,
+	    extract_loc_address_regs (false, mode, arg0_loc,
+				      top_p ? true : context_p, PLUS, code1,
 				      modify_p, ad);
 	    ad->disp_loc = arg1_loc;
 	  }
@@ -493,9 +495,9 @@  extract_loc_address_regs (enum machine_m
 		     || ok_for_index_p_nonstrict (arg0)))
 	  {
 	    extract_loc_address_regs
-	      (mode, arg0_loc, ! base_ok_p, PLUS, REG, modify_p, ad);
+	      (false, mode, arg0_loc, ! base_ok_p, PLUS, REG, modify_p, ad);
 	    extract_loc_address_regs
-	      (mode, arg1_loc, base_ok_p, PLUS, REG, modify_p, ad);
+	      (false, mode, arg1_loc, base_ok_p, PLUS, REG, modify_p, ad);
 	  }
 	else if (code0 == REG && code1 == REG
 		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
@@ -504,38 +506,38 @@  extract_loc_address_regs (enum machine_m
 		     || ok_for_index_p_nonstrict (arg1)))
 	  {
 	    extract_loc_address_regs 
-	      (mode, arg0_loc, base_ok_p, PLUS, REG, modify_p, ad);
+	      (false, mode, arg0_loc, base_ok_p, PLUS, REG, modify_p, ad);
 	    extract_loc_address_regs 
-	      (mode, arg1_loc, ! base_ok_p, PLUS, REG, modify_p, ad);
+	      (false, mode, arg1_loc, ! base_ok_p, PLUS, REG, modify_p, ad);
 	  }
 	/* If one operand is known to be a pointer, it must be the
 	   base with the other operand the index.  Likewise if the
 	   other operand is a MULT.  */
 	else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT)
 	  {
-	    extract_loc_address_regs (mode, arg0_loc, false, PLUS, code1,
-				      modify_p, ad);
+	    extract_loc_address_regs (false, mode, arg0_loc, false, PLUS,
+				      code1, modify_p, ad);
 	    if (code1 == MULT)
 	      ad->index_loc = arg1_loc;
-	    extract_loc_address_regs (mode, arg1_loc, true, PLUS, code0,
+	    extract_loc_address_regs (false, mode, arg1_loc, true, PLUS, code0,
 				      modify_p, ad);
 	  }
 	else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT)
 	  {
-	    extract_loc_address_regs (mode, arg0_loc, true, PLUS, code1,
+	    extract_loc_address_regs (false, mode, arg0_loc, true, PLUS, code1,
 				      modify_p, ad);
 	    if (code1 == MULT)
 	      ad->index_loc = arg0_loc;
-	    extract_loc_address_regs (mode, arg1_loc, false, PLUS, code0,
-				      modify_p, ad);
+	    extract_loc_address_regs (false, mode, arg1_loc, false, PLUS,
+				      code0, modify_p, ad);
 	  }
 	/* Otherwise, count equal chances that each might be a base or
 	   index register.  This case should be rare.  */
 	else
 	  {
-	    extract_loc_address_regs (mode, arg0_loc, false, PLUS, code1,
-				      modify_p, ad);
-	    extract_loc_address_regs (mode, arg1_loc, true, PLUS, code0,
+	    extract_loc_address_regs (false, mode, arg0_loc, false, PLUS,
+				      code1, modify_p, ad);
+	    extract_loc_address_regs (false, mode, arg1_loc, true, PLUS, code0,
 				      modify_p, ad);
 	  }
       }
@@ -546,22 +548,22 @@  extract_loc_address_regs (enum machine_m
 	 up in the wrong place.  */
     case POST_MODIFY:
     case PRE_MODIFY:
-      extract_loc_address_regs (mode, &XEXP (x, 0), false, code,
+      extract_loc_address_regs (false, mode, &XEXP (x, 0), false, code,
 				GET_CODE (XEXP (XEXP (x, 1), 1)), true,
 				ad);
       gcc_assert (rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)));
       ad->base_reg_loc2 = &XEXP (XEXP (x, 1), 0);
       if (REG_P (XEXP (XEXP (x, 1), 1)))
-	extract_loc_address_regs (mode, &XEXP (XEXP (x, 1), 1), true, code,
-				  REG, modify_p, ad);
+	extract_loc_address_regs (false, mode, &XEXP (XEXP (x, 1), 1), true,
+				  code, REG, modify_p, ad);
       break;
 
     case POST_INC:
     case PRE_INC:
     case POST_DEC:
     case PRE_DEC:
-      extract_loc_address_regs (mode, &XEXP (x, 0), false, code, SCRATCH,
-				true, ad);
+      extract_loc_address_regs (false, mode, &XEXP (x, 0), false, code,
+				SCRATCH, true, ad);
       break;
 
     case REG:
@@ -583,7 +585,7 @@  extract_loc_address_regs (enum machine_m
 
 	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
 	  if (fmt[i] == 'e')
-	    extract_loc_address_regs (mode, &XEXP (x, i), context_p,
+	    extract_loc_address_regs (false, mode, &XEXP (x, i), context_p,
 				      code, SCRATCH, modify_p, ad);
       }
     }
@@ -596,15 +598,15 @@  extract_loc_address_regs (enum machine_m
    MEM_MODE should be VOIDmode.  */
 static void
 extract_address_regs (enum machine_mode mem_mode,
-		       rtx *loc, enum rtx_code outer_code, struct address *ad)
+		      rtx *loc, enum rtx_code outer_code, struct address *ad)
 {
   ad->base_reg_loc = ad->base_reg_loc2
     = ad->index_reg_loc = ad->index_loc = ad->disp_loc = NULL;
   ad->base_outer_code = SCRATCH;
   ad->index_code = SCRATCH;
   ad->base_modify_p = false;
-  extract_loc_address_regs (mem_mode, loc, false, outer_code, SCRATCH,
-			     false, ad);  
+  extract_loc_address_regs (true, mem_mode, loc, false, outer_code, SCRATCH,
+			    false, ad);  
   if (ad->index_loc == NULL)
     /* SUBREG ??? */
     ad->index_loc = ad->index_reg_loc;