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