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]

[patch] Fix PR target/35054


Hi,

the problem here is that postreload-gcse doesn't iterator over all 
constituents of a multi-reg hardreg.  In the testcase this leads to a 
(clobber:SC ax)  (clobbering eax and edx) not being noted as destroying 
%edx, so it thought a reload from stack to %edx later wasn't needed.  
Fixed by changing the interface a bit, and iterating over all hardregs.

Regstrapping in progress on i686, x86_64.  Okay for trunk?  The testcase 
is architecture independend, but probably only breaks for i?86 (the others 
have too many registers free).


Ciao,
Michael.

	* postreload-gcse.c (record_last_reg_set_info_regno): Renamed
	from record_last_reg_set_info.
	(record_last_reg_set_info): Take an RTX argument, iterate over all
	constituent hardregs.
	(record_last_set_info, record_opr_changes): Change calls to
	new signature or to record_last_reg_set_info_regno.

	* gcc.dg/pr35054.c: New test.

Index: postreload-gcse.c
===================================================================
--- postreload-gcse.c	(revision 131996)
+++ postreload-gcse.c	(working copy)
@@ -175,7 +175,8 @@ static void free_mem (void);
 
 /* Support for hash table construction and transformations.  */
 static bool oprs_unchanged_p (rtx, rtx, bool);
-static void record_last_reg_set_info (rtx, int);
+static void record_last_reg_set_info (rtx, rtx);
+static void record_last_reg_set_info_regno (rtx, int);
 static void record_last_mem_set_info (rtx);
 static void record_last_set_info (rtx, const_rtx, void *);
 static void record_opr_changes (rtx);
@@ -645,7 +646,19 @@ load_killed_in_block_p (int uid_limit, r
 /* Record register first/last/block set information for REGNO in INSN.  */
 
 static inline void
-record_last_reg_set_info (rtx insn, int regno)
+record_last_reg_set_info (rtx insn, rtx reg)
+{
+  unsigned int regno, end_regno;
+
+  regno = REGNO (reg);
+  end_regno = END_HARD_REGNO (reg);
+  do
+    reg_avail_info[regno] = INSN_CUID (insn);
+  while (++regno < end_regno);
+}
+
+static inline void
+record_last_reg_set_info_regno (rtx insn, int regno)
 {
   reg_avail_info[regno] = INSN_CUID (insn);
 }
@@ -680,7 +693,7 @@ record_last_set_info (rtx dest, const_rt
     dest = SUBREG_REG (dest);
 
   if (REG_P (dest))
-    record_last_reg_set_info (last_set_insn, REGNO (dest));
+    record_last_reg_set_info (last_set_insn, dest);
   else if (MEM_P (dest))
     {
       /* Ignore pushes, they don't clobber memory.  They may still
@@ -691,7 +704,7 @@ record_last_set_info (rtx dest, const_rt
       if (! push_operand (dest, GET_MODE (dest)))
 	record_last_mem_set_info (last_set_insn);
       else
-	record_last_reg_set_info (last_set_insn, STACK_POINTER_REGNUM);
+	record_last_reg_set_info_regno (last_set_insn, STACK_POINTER_REGNUM);
     }
 }
 
@@ -722,7 +735,7 @@ record_opr_changes (rtx insn)
   /* Also record autoincremented REGs for this insn as changed.  */
   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
     if (REG_NOTE_KIND (note) == REG_INC)
-      record_last_reg_set_info (insn, REGNO (XEXP (note, 0)));
+      record_last_reg_set_info (insn, XEXP (note, 0));
 
   /* Finally, if this is a call, record all call clobbers.  */
   if (CALL_P (insn))
@@ -732,7 +745,7 @@ record_opr_changes (rtx insn)
 
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 	if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
-	  record_last_reg_set_info (insn, regno);
+	  record_last_reg_set_info_regno (insn, regno);
 
       for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
 	if (GET_CODE (XEXP (link, 0)) == CLOBBER)
@@ -741,11 +754,7 @@ record_opr_changes (rtx insn)
 	    if (REG_P (x))
 	      {
 		gcc_assert (HARD_REGISTER_P (x));
-	        regno = REGNO (x);
-		end_regno = END_HARD_REGNO (x);
-		do
-		  record_last_reg_set_info (insn, regno);
-		while (++regno < end_regno);
+		record_last_reg_set_info (insn, x);
 	      }
 	  }

 
/* { dg-do run } */
/* { dg-options "-O2 -fgcse-after-reload" } */

extern void abort (void);

__attribute__((noinline)) __complex__ float
give_neg1 (void)
{
  __complex__ float res;
  __real__ res = -1.0;
  __imag__ res = 1.0;
  return res;
}

__attribute__((noinline)) __complex__ float
mycacoshf (__complex__ float x)
{
  __complex__ float res;
  res = give_neg1 ();

  /* We have to use the positive branch.  */
  if (__real__ res < 0.0)
    {
      unsigned a,b,c,d,e,f;
      res = -res; 
      asm __volatile__ ("" : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f));
    }
  return res;
}

int main()
{
  __complex__ float res = mycacoshf(1.0);
  if (__imag__ res >= 0.0)
    abort();
  return 0;
}


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