diff mbox

patch to fix pr58968

Message ID 5277C859.9050407@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov Nov. 4, 2013, 4:16 p.m. UTC
The following patch fixes

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58968


  It is actually the 3rd try to fix the problem.  Removing no-ops move
may result in mode-switching crashes on x86/x86-64 as it expects a
specific code (by the way reload has the same problem on x86/x86-64).

  The patch was successfully bootstrapped and tested on x86/x86-64 and
ppc64 (with LRA).

  Committed as rev. 204353.

2013-11-04  Vladimir Makarov  <vmakarov@redhat.com>

        PR rtl-optimization/58968
        * lra-spills.c (return_regno_p): New function.
          (lra_final_code_change): Use it.

2013-11-04  Vladimir Makarov  <vmakarov@redhat.com>

        PR rtl-optimization/58968
        * gfortran.dg/pr58968.f: New
diff mbox

Patch

Index: lra-spills.c
===================================================================
--- lra-spills.c	(revision 204352)
+++ lra-spills.c	(working copy)
@@ -618,6 +618,33 @@  alter_subregs (rtx *loc, bool final_p)
   return res;
 }
 
+/* Return true if REGNO is used for return in the current
+   function.  */
+static bool
+return_regno_p (unsigned int regno)
+{
+  rtx outgoing = crtl->return_rtx;
+
+  if (! outgoing)
+    return false;
+
+  if (REG_P (outgoing))
+    return REGNO (outgoing) == regno;
+  else if (GET_CODE (outgoing) == PARALLEL)
+    {
+      int i;
+
+      for (i = 0; i < XVECLEN (outgoing, 0); i++)
+	{
+	  rtx x = XEXP (XVECEXP (outgoing, 0, i), 0);
+
+	  if (REG_P (x) && REGNO (x) == regno)
+	    return true;
+	}
+    }
+  return false;
+}
+
 /* Final change of pseudos got hard registers into the corresponding
    hard registers and removing temporary clobbers.  */
 void
@@ -625,7 +652,7 @@  lra_final_code_change (void)
 {
   int i, hard_regno;
   basic_block bb;
-  rtx insn, curr, set;
+  rtx insn, curr;
   int max_regno = max_reg_num ();
 
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
@@ -636,7 +663,6 @@  lra_final_code_change (void)
     FOR_BB_INSNS_SAFE (bb, insn, curr)
       if (INSN_P (insn))
 	{
-	  bool change_p;
 	  rtx pat = PATTERN (insn);
 
 	  if (GET_CODE (pat) == CLOBBER && LRA_TEMP_CLOBBER_P (pat))
@@ -649,12 +675,24 @@  lra_final_code_change (void)
 	      continue;
 	    }
 
-	  set = single_set (insn);
-	  change_p = (set != NULL
-		      && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))
-		      && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER
-		      && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER);
-	  
+	  /* IRA can generate move insns involving pseudos.  It is
+	     better remove them earlier to speed up compiler a bit.
+	     It is also better to do it here as they might not pass
+	     final RTL check in LRA, (e.g. insn moving a control
+	     register into itself).  So remove an useless move insn
+	     unless next insn is USE marking the return reg (we should
+	     save this as some subsequent optimizations assume that
+	     such original insns are saved).  */
+	  if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET
+	      && REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat))
+	      && REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat))
+	      && ! return_regno_p (REGNO (SET_SRC (pat))))
+	    {
+	      lra_invalidate_insn_data (insn);
+	      delete_insn (insn);
+	      continue;
+	    }
+	
 	  lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
 	  struct lra_static_insn_data *static_id = id->insn_static_data;
 	  bool insn_change_p = false;
@@ -668,20 +706,5 @@  lra_final_code_change (void)
 	      }
 	  if (insn_change_p)
 	    lra_update_operator_dups (id);
-
-	  if (change_p && REGNO (SET_SRC (set)) == REGNO (SET_DEST (set)))
-	    {
-	      /* Remove an useless move insn but only involving
-		 pseudos as some subsequent optimizations are based on
-		 that move insns involving originally hard registers
-		 are preserved.  IRA can generate move insns involving
-		 pseudos.  It is better remove them earlier to speed
-		 up compiler a bit.  It is also better to do it here
-		 as they might not pass final RTL check in LRA,
-		 (e.g. insn moving a control register into
-		 itself).  */
-	      lra_invalidate_insn_data (insn);
-	      delete_insn (insn);
-	    }
 	}
 }
Index: testsuite/gfortran.dg/pr58968.f
===================================================================
--- testsuite/gfortran.dg/pr58968.f	(revision 0)
+++ testsuite/gfortran.dg/pr58968.f	(working copy)
@@ -0,0 +1,96 @@ 
+C PR rtl-optimization/58968.f
+C { dg-do compile { target powerpc*-*-*} }
+C { dg-options "-mcpu=power7 -O3 -w -ffast-math  -funroll-loops" }
+      SUBROUTINE MAKTABS(IW,SOME,LBOX1,LBOX2,LBOX3,NSPACE,NA,NB,
+     *            LBST,X,
+     *            NX,IAMA,IAMI,IBMA,IBMI,MNUM,IDIM,MSTA,IBO,
+     *            IDSYM,ISYM1,NSYM,
+     *            NACT,LWRK,KTAB,LGMUL,
+     *            LCON,LCOA,LCOB,
+     *            LANDET,LBNDET,NAST,NBST,LSYMA,LSYMB,LGCOM,
+     *            MINI,MAXI,LSPA,LSPB,LDISB,
+     *            LSAS,LSBS,LSAC,LSBC,
+     *            ITGA,ITGB,IAST,IBST,NCI,NA1EX,NB1EX,FDIRCT)
+      IMPLICIT DOUBLE PRECISION(A-H,O-Z)
+      LOGICAL SOME
+      DIMENSION LBOX1(NSPACE),LBOX2(NSPACE),LBOX3(NSPACE),LBST(NSPACE)
+      DIMENSION X(NX)
+      DIMENSION IAMA(NSPACE),IAMI(NSPACE),IBMA(NSPACE),IBMI(NSPACE)
+      DIMENSION MNUM(NSPACE),IDIM(NSPACE),MSTA(NSPACE+1),IBO(NACT)
+      DIMENSION LWRK(43),KTAB(NSYM),LGMUL(NSYM,NSYM)
+      DIMENSION LCON(NA)
+      DIMENSION LCOA(NSYM,ITGA),LCOB(NSYM,ITGB)
+      DIMENSION LANDET(NSPACE,ITGA),LBNDET(NSPACE,ITGB)
+      DIMENSION NAST(ITGA+1),NBST(ITGB+1)
+      DIMENSION LSYMA(IAST),LSYMB(IBST)
+      DIMENSION LGCOM(ITGB,ITGA)
+      DIMENSION MINI(NSPACE),MAXI(NSPACE)
+      DIMENSION LSPA(IAST),LSPB(IBST)
+      DIMENSION LDISB(NSYM,ITGB,ITGA)
+      DIMENSION LSAS(NSYM+1,ITGA),LSBS(NSYM+1,ITGB)
+      DIMENSION LSAC(IAST),LSBC(IBST)
+      LOGICAL FDIRCT
+      LCOA = 0
+      LCOB = 0
+      ISTA1 = LBST(1)
+      CALL RESETCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX2)
+      NAST(1) = 0
+      NBST(1) = 0
+      DO II=1,ITGA
+         ITOT = 1
+         DO JJ=1,NSPACE
+            ITOT = ITOT * LANDET(JJ,II)
+         ENDDO
+         NAST(II+1) = NAST(II) + ITOT
+      ENDDO
+      DO II=1,ITGB
+         ITOT = 1
+         DO JJ=1,NSPACE
+            ITOT = ITOT * LBNDET(JJ,II)
+         ENDDO
+         NBST(II+1) = NBST(II) + ITOT
+      ENDDO
+      ICOMP = 0
+      CALL RESETCO(LBOX1,NSPACE,NA,IAMA,IAMI,LBOX3)
+      NA1EX = 0
+      NB1EX = 0
+      CALL RESETCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX3)
+      DO IIB = 1,ITGB
+         CALL RESETDE(LBOX1,NSPACE,NB,MSTA,LCON)
+         DO KKB=NBST(IIB)+1,NBST(IIB+1)
+            DO II=1,NSPACE
+               LBOX2(II) = LBOX1(II)
+            ENDDO
+            IEBS = NB+1
+            DO ISPB1=NSPACE,1,-1
+               IOC1 = LBOX1(ISPB1)
+               IEBE = IEBS - 1
+               IEBS = IEBS - IOC1
+               LBOX2(ISPB1) = LBOX2(ISPB1)-1
+               DO IB1=IEBE,IEBS,-1
+                  IO1 = LCON(IB1)
+                  IGBE = IEBE - LBOX1(ISPB1)
+                  DO ISPB2=ISPB1,NSPACE
+                     IGBS = IGBE + 1
+                     IGBE = IGBE + LBOX1(ISPB2)
+                     LBOX2(ISPB2) = LBOX2(ISPB2) + 1
+                     IGBA = MAX(IB1+1,IGBS)
+                     DO IGAP=IGBA,IGBE+1
+                        DO JJ=ISTA,IEND
+                           NB1EX = NB1EX + 1
+                        ENDDO
+                        ISTA = LCON(IGAP)+1
+                        IEND = LCON(IGAP+1)-1
+                        IF (IGAP.EQ.IGBE) IEND=MSTA(ISPB2+1)-1
+                     ENDDO
+                     LBOX2(ISPB2) = LBOX2(ISPB2) - 1
+                  ENDDO
+               ENDDO
+               LBOX2(ISPB1) = LBOX2(ISPB1) + 1
+            ENDDO
+            CALL MOVEUP2(LBOX1,NSPACE,NB,MSTA,LCON)
+         ENDDO
+         CALL PUSHCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX3,IEND)
+      ENDDO 
+      RETURN
+      END