===================================================================
@@ -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);
- }
}
}
===================================================================
@@ -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