This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix PR middle-end/14988


Hi,

This is the PR that tracks the failure of the 7 cxg20?? tests in the ACATS 
testsuite at -O2 on x86, on mainline and 3.4 branch.

The problem comes from the initialization of Z in

 procedure main is
   Z : Complex := (0.0, 0.0);
   X : Long_Long_Float;
 begin
   X := My_Argument (Z);
   if X /= 0.0 then
      Oops;
   end if;
 end main;

Since optimization is enabled, Z is first given a CONCAT of two pseudo-regs 
with mode XFmode.  As Z is passed by reference to My_Argument, it is later 
put on the stack by put_var_into_stack.

When passed a CONCAT, put_var_into_stack works on each part sequentially:

      /* A CONCAT contains two pseudos; put them both in the stack.
	 We do it so they end up consecutive.

      put_reg_into_stack (function, hipart, part_type, part_mode,
			  part_mode, volatilep, 0, 0, 0);
      put_reg_into_stack (function, lopart, part_type, part_mode,
			  part_mode, volatilep, 0, 0, 0);


The problem is that they don't end up consecutive in memory, because each 
part is passed through the LOCAL_ALIGNMENT macro in assign_stack_local_1 
and the x86 back-end wants 128-bit alignment for the 96-bit XFmode so there 
is 4-byte hole.


The proposed fix is to add a new parameter to put_reg_into_stack, namely 
consecutive_p, so as to instruct the function to put the second register in
a slot adjacent to the first one.  It is essentially passed down to 
assign_stack_local_1, which then uses BITS_PER_UNIT instead of 
LOCAL_ALIGNMENT.

However, put_reg_into_stack already has 9 parameters so I tried to reclaim 
one before adding mine.  I think that the 'promoted_mode' parameter is 
redundant: it can be calculated as GET_MODE (reg).  So I removed it and also 
turned the 3 predicates into 'bool' parameters.

Bootstrapped/regtested on i586-redhat-linux-gnu (3.4 branch and mainline).  
OK for mainline?  What about 3.4 branch?


2004-04-23  Eric Botcazou  <ebotcazou@act-europe.fr>

	PR middle-end/14988
	* function.c (assign_stack_local_1): Use BITS_PER_UNIT alignment
	when passed -2 as 'align'.
	(put_var_into_stack): Use 'bool' as the type for the three local
	predicates.  Adjust calls to put_reg_into_stack.
	When passed a CONCAT, instruct put_reg_into_stack to use
	a consecutive stack slot for the second part.
	(put_reg_into_stack): Remove 'promoted_mode' parameter, add
	'consecutive_p' parameter.  Turn the three predicates into 'bool'
 	parameters.  Retrieve the register mode from 'reg'.
	When consecutive_p is true, instruct assign_stack_local_1 to use
	BITS_PER_UNIT alignment.
	(put_addressof_into_stack):  Use 'bool' as the type for the two local
	predicates.  Adjust call to put_reg_into_stack.


-- 
Eric Botcazou
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.483.4.10
diff -u -p -r1.483.4.10 function.c
--- function.c	15 Mar 2004 23:22:47 -0000	1.483.4.10
+++ function.c	22 Apr 2004 10:39:14 -0000
@@ -236,7 +236,7 @@ static rtx assign_stack_local_1 (enum ma
 				 struct function *);
 static struct temp_slot *find_temp_slot_from_address (rtx);
 static void put_reg_into_stack (struct function *, rtx, tree, enum machine_mode,
-				enum machine_mode, int, unsigned int, int, htab_t);
+				unsigned int, bool, bool, bool, htab_t);
 static void schedule_fixup_var_refs (struct function *, rtx, tree, enum machine_mode,
 				     htab_t);
 static void fixup_var_refs (rtx, enum machine_mode, int, rtx, htab_t);
@@ -506,6 +506,7 @@ get_frame_size (void)
    ALIGN controls the amount of alignment for the address of the slot:
    0 means according to MODE,
    -1 means use BIGGEST_ALIGNMENT and round size to multiple of that,
+   -2 means use BITS_PER_UNIT,
    positive specifies alignment boundary in bits.
 
    We do not round to stack_boundary here.
@@ -543,6 +544,8 @@ assign_stack_local_1 (enum machine_mode 
       alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
       size = CEIL_ROUND (size, alignment);
     }
+  else if (align == -2)
+    alignment = 1; /* BITS_PER_UNIT / BITS_PER_UNIT */
   else
     alignment = align / BITS_PER_UNIT;
 
@@ -1291,9 +1294,9 @@ put_var_into_stack (tree decl, int resca
   enum machine_mode promoted_mode, decl_mode;
   struct function *function = 0;
   tree context;
-  int can_use_addressof;
-  int volatilep = TREE_CODE (decl) != SAVE_EXPR && TREE_THIS_VOLATILE (decl);
-  int usedp = (TREE_USED (decl)
+  bool can_use_addressof_p;
+  bool volatile_p = TREE_CODE (decl) != SAVE_EXPR && TREE_THIS_VOLATILE (decl);
+  bool used_p = (TREE_USED (decl)
 	       || (TREE_CODE (decl) != SAVE_EXPR && DECL_INITIAL (decl) != 0));
 
   context = decl_function_context (decl);
@@ -1340,7 +1343,7 @@ put_var_into_stack (tree decl, int resca
   /* If this variable lives in the current function and we don't need to put it
      in the stack for the sake of setjmp or the non-locality, try to keep it in
      a register until we know we actually need the address.  */
-  can_use_addressof
+  can_use_addressof_p
     = (function == 0
        && ! (TREE_CODE (decl) != SAVE_EXPR && DECL_NONLOCAL (decl))
        && optimize > 0
@@ -1353,7 +1356,8 @@ put_var_into_stack (tree decl, int resca
 
   /* If we can't use ADDRESSOF, make sure we see through one we already
      generated.  */
-  if (! can_use_addressof && GET_CODE (reg) == MEM
+  if (! can_use_addressof_p
+      && GET_CODE (reg) == MEM
       && GET_CODE (XEXP (reg, 0)) == ADDRESSOF)
     reg = XEXP (XEXP (reg, 0), 0);
 
@@ -1361,11 +1365,11 @@ put_var_into_stack (tree decl, int resca
 
   if (GET_CODE (reg) == REG)
     {
-      if (can_use_addressof)
+      if (can_use_addressof_p)
 	gen_mem_addressof (reg, decl, rescan);
       else
-	put_reg_into_stack (function, reg, TREE_TYPE (decl), promoted_mode,
-			    decl_mode, volatilep, 0, usedp, 0);
+	put_reg_into_stack (function, reg, TREE_TYPE (decl), decl_mode,
+			    0, volatile_p, used_p, false, 0);
     }
   else if (GET_CODE (reg) == CONCAT)
     {
@@ -1381,14 +1385,14 @@ put_var_into_stack (tree decl, int resca
 #ifdef FRAME_GROWS_DOWNWARD
       /* Since part 0 should have a lower address, do it second.  */
       put_reg_into_stack (function, hipart, part_type, part_mode,
-			  part_mode, volatilep, 0, 0, 0);
+			  0, volatile_p, false, false, 0);
       put_reg_into_stack (function, lopart, part_type, part_mode,
-			  part_mode, volatilep, 0, 0, 0);
+			  0, volatile_p, false, true, 0);
 #else
       put_reg_into_stack (function, lopart, part_type, part_mode,
-			  part_mode, volatilep, 0, 0, 0);
+			  0, volatile_p, false, false, 0);
       put_reg_into_stack (function, hipart, part_type, part_mode,
-			  part_mode, volatilep, 0, 0, 0);
+			  0, volatile_p, false, true, 0);
 #endif
 
       /* Change the CONCAT into a combined MEM for both parts.  */
@@ -1409,7 +1413,7 @@ put_var_into_stack (tree decl, int resca
       /* Prevent sharing of rtl that might lose.  */
       if (GET_CODE (XEXP (reg, 0)) == PLUS)
 	XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
-      if (usedp && rescan)
+      if (used_p && rescan)
 	{
 	  schedule_fixup_var_refs (function, reg, TREE_TYPE (decl),
 				   promoted_mode, 0);
@@ -1423,20 +1427,24 @@ put_var_into_stack (tree decl, int resca
 
 /* Subroutine of put_var_into_stack.  This puts a single pseudo reg REG
    into the stack frame of FUNCTION (0 means the current function).
+   TYPE is the user-level data type of the value hold in the register.
    DECL_MODE is the machine mode of the user-level data type.
-   PROMOTED_MODE is the machine mode of the register.
-   VOLATILE_P is nonzero if this is for a "volatile" decl.
-   USED_P is nonzero if this reg might have already been used in an insn.  */
+   ORIGINAL_REGNO must be set if the real regno is not visible in REG.
+   VOLATILE_P is true if this is for a "volatile" decl.
+   USED_P is true if this reg might have already been used in an insn.
+   CONSECUTIVE_P is true if the stack slot assigned to reg must be
+   consecutive with the previous stack slot.  */
 
 static void
 put_reg_into_stack (struct function *function, rtx reg, tree type,
-		    enum machine_mode promoted_mode,
-		    enum machine_mode decl_mode, int volatile_p,
-		    unsigned int original_regno, int used_p, htab_t ht)
+		    enum machine_mode decl_mode, unsigned int original_regno,
+		    bool volatile_p, bool used_p, bool consecutive_p,
+		    htab_t ht)
 {
   struct function *func = function ? function : cfun;
-  rtx new = 0;
+  enum machine_mode mode = GET_MODE (reg);
   unsigned int regno = original_regno;
+  rtx new = 0;
 
   if (regno == 0)
     regno = REGNO (reg);
@@ -1449,7 +1457,8 @@ put_reg_into_stack (struct function *fun
     }
 
   if (new == 0)
-    new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func);
+    new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode),
+				consecutive_p ? -2 : 0, func);
 
   PUT_CODE (reg, MEM);
   PUT_MODE (reg, decl_mode);
@@ -1471,7 +1480,7 @@ put_reg_into_stack (struct function *fun
     }
 
   if (used_p)
-    schedule_fixup_var_refs (function, reg, type, promoted_mode, ht);
+    schedule_fixup_var_refs (function, reg, type, mode, ht);
 }
 
 /* Make sure that all refs to the variable, previously made
@@ -2907,7 +2916,7 @@ static void
 put_addressof_into_stack (rtx r, htab_t ht)
 {
   tree decl, type;
-  int volatile_p, used_p;
+  bool volatile_p, used_p;
 
   rtx reg = XEXP (r, 0);
 
@@ -2926,12 +2935,12 @@ put_addressof_into_stack (rtx r, htab_t 
   else
     {
       type = NULL_TREE;
-      volatile_p = 0;
-      used_p = 1;
+      volatile_p = false;
+      used_p = true;
     }
 
-  put_reg_into_stack (0, reg, type, GET_MODE (reg), GET_MODE (reg),
-		      volatile_p, ADDRESSOF_REGNO (r), used_p, ht);
+  put_reg_into_stack (0, reg, type, GET_MODE (reg), ADDRESSOF_REGNO (r),
+		      volatile_p, used_p, false, ht);
 }
 
 /* List of replacements made below in purge_addressof_1 when creating

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]