@@ -1981,17 +1981,36 @@ static bool foldFCmpToFPClassTest(CmpInst *Cmp, const TargetLowering &TLI,
1981
1981
return true ;
1982
1982
}
1983
1983
1984
- static bool isRemOfLoopIncrementWithLoopInvariant (Instruction *Rem,
1985
- const LoopInfo *LI,
1986
- Value *&RemAmtOut,
1987
- PHINode *&LoopIncrPNOut) {
1984
+ static bool isRemOfLoopIncrementWithLoopInvariant (
1985
+ Instruction *Rem, const LoopInfo *LI, Value *&RemAmtOut, Value *&AddInstOut,
1986
+ Value *&AddOffsetOut, PHINode *&LoopIncrPNOut) {
1988
1987
Value *Incr, *RemAmt;
1989
1988
// NB: If RemAmt is a power of 2 it *should* have been transformed by now.
1990
1989
if (!match (Rem, m_URem (m_Value (Incr), m_Value (RemAmt))))
1991
1990
return false ;
1992
1991
1992
+ Value *AddInst, *AddOffset;
1993
1993
// Find out loop increment PHI.
1994
1994
auto *PN = dyn_cast<PHINode>(Incr);
1995
+ if (PN != nullptr ) {
1996
+ AddInst = nullptr ;
1997
+ AddOffset = nullptr ;
1998
+ } else {
1999
+ // Search through a NUW add on top of the loop increment.
2000
+ Value *V0, *V1;
2001
+ if (!match (Incr, m_NUWAdd (m_Value (V0), m_Value (V1))))
2002
+ return false ;
2003
+
2004
+ AddInst = Incr;
2005
+ PN = dyn_cast<PHINode>(V0);
2006
+ if (PN != nullptr ) {
2007
+ AddOffset = V1;
2008
+ } else {
2009
+ PN = dyn_cast<PHINode>(V1);
2010
+ AddOffset = V0;
2011
+ }
2012
+ }
2013
+
1995
2014
if (!PN)
1996
2015
return false ;
1997
2016
@@ -2031,6 +2050,8 @@ static bool isRemOfLoopIncrementWithLoopInvariant(Instruction *Rem,
2031
2050
// Set output variables.
2032
2051
RemAmtOut = RemAmt;
2033
2052
LoopIncrPNOut = PN;
2053
+ AddInstOut = AddInst;
2054
+ AddOffsetOut = AddOffset;
2034
2055
2035
2056
return true ;
2036
2057
}
@@ -2045,15 +2066,14 @@ static bool isRemOfLoopIncrementWithLoopInvariant(Instruction *Rem,
2045
2066
// Rem = (Start nuw+ IncrLoopInvariant) % RemAmtLoopInvariant;
2046
2067
// for(i = Start; i < End; ++i, ++rem)
2047
2068
// Rem = rem == RemAmtLoopInvariant ? 0 : Rem;
2048
- //
2049
- // Currently only implemented for `IncrLoopInvariant` being zero.
2050
2069
static bool foldURemOfLoopIncrement (Instruction *Rem, const DataLayout *DL,
2051
2070
const LoopInfo *LI,
2052
2071
SmallSet<BasicBlock *, 32 > &FreshBBs,
2053
2072
bool IsHuge) {
2054
- Value *RemAmt;
2073
+ Value *AddOffset, * RemAmt, *AddInst ;
2055
2074
PHINode *LoopIncrPN;
2056
- if (!isRemOfLoopIncrementWithLoopInvariant (Rem, LI, RemAmt, LoopIncrPN))
2075
+ if (!isRemOfLoopIncrementWithLoopInvariant (Rem, LI, RemAmt, AddInst,
2076
+ AddOffset, LoopIncrPN))
2057
2077
return false ;
2058
2078
2059
2079
// Only non-constant remainder as the extra IV is probably not profitable
@@ -2071,6 +2091,23 @@ static bool foldURemOfLoopIncrement(Instruction *Rem, const DataLayout *DL,
2071
2091
2072
2092
Loop *L = LI->getLoopFor (LoopIncrPN->getParent ());
2073
2093
Value *Start = LoopIncrPN->getIncomingValueForBlock (L->getLoopPreheader ());
2094
+ // If we have add create initial value for remainder.
2095
+ // The logic here is:
2096
+ // (urem (add nuw Start, IncrLoopInvariant), RemAmtLoopInvariant
2097
+ //
2098
+ // Only proceed if the expression simplifies (otherwise we can't fully
2099
+ // optimize out the urem).
2100
+ if (AddInst) {
2101
+ assert (AddOffset && " We found an add but missing values" );
2102
+ // Without dom-condition/assumption cache we aren't likely to get much out
2103
+ // of a context instruction.
2104
+ Start = simplifyAddInst (Start, AddOffset,
2105
+ match (AddInst, m_NSWAdd (m_Value (), m_Value ())),
2106
+ /* IsNUW=*/ true , *DL);
2107
+ if (!Start)
2108
+ return false ;
2109
+ }
2110
+
2074
2111
// If we can't fully optimize out the `rem`, skip this transform.
2075
2112
Start = simplifyURemInst (Start, RemAmt, *DL);
2076
2113
if (!Start)
@@ -2098,9 +2135,12 @@ static bool foldURemOfLoopIncrement(Instruction *Rem, const DataLayout *DL,
2098
2135
FreshBBs.insert (LoopIncrPN->getParent ());
2099
2136
FreshBBs.insert (L->getLoopLatch ());
2100
2137
FreshBBs.insert (Rem->getParent ());
2101
-
2138
+ if (AddInst)
2139
+ FreshBBs.insert (cast<Instruction>(AddInst)->getParent ());
2102
2140
replaceAllUsesWith (Rem, NewRem, FreshBBs, IsHuge);
2103
2141
Rem->eraseFromParent ();
2142
+ if (AddInst && AddInst->use_empty ())
2143
+ cast<Instruction>(AddInst)->eraseFromParent ();
2104
2144
return true ;
2105
2145
}
2106
2146
0 commit comments