<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 25, 2016 at 10:53 AM, Lawrence Hu via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lawrence<br>
Date: Mon Jan 25 12:53:39 2016<br>
New Revision: 258700<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=258700&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=258700&view=rev</a><br>
Log:<br></blockquote><div><br></div><div>This could've used a commit message ^</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Differential Revision: <a href="http://reviews.llvm.org/D13151" rel="noreferrer" target="_blank">http://reviews.llvm.org/D13151</a><br>
<br>
Added:<br>
llvm/trunk/test/Transforms/LoopReroll/ptrindvar.ll<br>
Modified:<br>
llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp?rev=258700&r1=258699&r2=258700&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp?rev=258700&r1=258699&r2=258700&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp Mon Jan 25 12:53:39 2016<br>
@@ -396,6 +396,7 @@ namespace {<br>
bool instrDependsOn(Instruction *I,<br>
UsesTy::iterator Start,<br>
UsesTy::iterator End);<br>
+ void replaceIV(Instruction *Inst, Instruction *IV, const SCEV *IterCount);<br>
<br>
LoopReroll *Parent;<br>
<br>
@@ -460,6 +461,48 @@ static bool hasUsesOutsideLoop(Instructi<br>
return false;<br>
}<br>
<br>
+static const SCEVConstant *getIncrmentFactorSCEV(ScalarEvolution *SE,<br>
+ const SCEV *SCEVExpr,<br>
+ Instruction &IV) {<br>
+ const SCEVMulExpr *MulSCEV = dyn_cast<SCEVMulExpr>(SCEVExpr);<br>
+<br>
+ // If StepRecurrence of a SCEVExpr is a constant (c1 * c2, c2 = sizeof(ptr)),<br>
+ // Return c1.<br>
+ if (!MulSCEV && IV.getType()->isPointerTy())<br>
+ if (const SCEVConstant *IncSCEV = dyn_cast<SCEVConstant>(SCEVExpr)) {<br>
+ const PointerType *PTy = cast<PointerType>(IV.getType());<br>
+ Type *ElTy = PTy->getElementType();<br>
+ const SCEV *SizeOfExpr =<br>
+ SE->getSizeOfExpr(SE->getEffectiveSCEVType(IV.getType()), ElTy);<br>
+ if (IncSCEV->getValue()->getValue().isNegative()) {<br>
+ const SCEV *NewSCEV =<br>
+ SE->getUDivExpr(SE->getNegativeSCEV(SCEVExpr), SizeOfExpr);<br>
+ return dyn_cast<SCEVConstant>(SE->getNegativeSCEV(NewSCEV));<br>
+ } else {<br>
+ return dyn_cast<SCEVConstant>(SE->getUDivExpr(SCEVExpr, SizeOfExpr));<br>
+ }<br>
+ }<br>
+<br>
+ if (!MulSCEV)<br>
+ return nullptr;<br>
+<br>
+ // If StepRecurrence of a SCEVExpr is a c * sizeof(x), where c is constant,<br>
+ // Return c.<br>
+ const SCEVConstant *CIncSCEV = nullptr;<br>
+ for (const SCEV *Operand : MulSCEV->operands()) {<br>
+ if (const SCEVConstant *Constant = dyn_cast<SCEVConstant>(Operand)) {<br>
+ CIncSCEV = Constant;<br>
+ } else if (const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Operand)) {<br>
+ Type *AllocTy;<br>
+ if (!Unknown->isSizeOf(AllocTy))<br>
+ break;<br>
+ } else {<br>
+ return nullptr;<br>
+ }<br>
+ }<br>
+ return CIncSCEV;<br>
+}<br>
+<br>
// Collect the list of loop induction variables with respect to which it might<br>
// be possible to reroll the loop.<br>
void LoopReroll::collectPossibleIVs(Loop *L,<br>
@@ -469,7 +512,7 @@ void LoopReroll::collectPossibleIVs(Loop<br>
IE = Header->getFirstInsertionPt(); I != IE; ++I) {<br>
if (!isa<PHINode>(I))<br>
continue;<br>
- if (!I->getType()->isIntegerTy())<br>
+ if (!I->getType()->isIntegerTy() && !I->getType()->isPointerTy())<br>
continue;<br>
<br>
if (const SCEVAddRecExpr *PHISCEV =<br>
@@ -478,9 +521,14 @@ void LoopReroll::collectPossibleIVs(Loop<br>
continue;<br>
if (!PHISCEV->isAffine())<br>
continue;<br>
- if (const SCEVConstant *IncSCEV =<br>
- dyn_cast<SCEVConstant>(PHISCEV->getStepRecurrence(*SE))) {<br>
- const APInt &AInt = IncSCEV->getAPInt().abs();<br>
+ const SCEVConstant *IncSCEV = nullptr;<br>
+ if (I->getType()->isPointerTy())<br>
+ IncSCEV =<br>
+ getIncrmentFactorSCEV(SE, PHISCEV->getStepRecurrence(*SE), *I);<br>
+ else<br>
+ IncSCEV = dyn_cast<SCEVConstant>(PHISCEV->getStepRecurrence(*SE));<br>
+ if (IncSCEV) {<br>
+ const APInt &AInt = IncSCEV->getValue()->getValue().abs();<br>
if (IncSCEV->getValue()->isZero() || AInt.uge(MaxInc))<br>
continue;<br>
IVToIncMap[&*I] = IncSCEV->getValue()->getSExtValue();<br>
@@ -651,10 +699,12 @@ static bool isSimpleArithmeticOp(User *I<br>
<br>
static bool isLoopIncrement(User *U, Instruction *IV) {<br>
BinaryOperator *BO = dyn_cast<BinaryOperator>(U);<br>
- if (!BO || BO->getOpcode() != Instruction::Add)<br>
+<br>
+ if ((BO && BO->getOpcode() != Instruction::Add) ||<br>
+ (!BO && !isa<GetElementPtrInst>(U)))<br>
return false;<br>
<br>
- for (auto *UU : BO->users()) {<br>
+ for (auto *UU : U->users()) {<br>
PHINode *PN = dyn_cast<PHINode>(UU);<br>
if (PN && PN == IV)<br>
return true;<br>
@@ -1272,61 +1322,84 @@ void LoopReroll::DAGRootTracker::replace<br>
<br>
++J;<br>
}<br>
- bool Negative = IVToIncMap[IV] < 0;<br>
- const DataLayout &DL = Header->getModule()->getDataLayout();<br>
<br>
// We need to create a new induction variable for each different BaseInst.<br>
- for (auto &DRS : RootSets) {<br>
+ for (auto &DRS : RootSets)<br>
// Insert the new induction variable.<br>
- const SCEVAddRecExpr *RealIVSCEV =<br>
- cast<SCEVAddRecExpr>(SE->getSCEV(DRS.BaseInst));<br>
- const SCEV *Start = RealIVSCEV->getStart();<br>
- const SCEVAddRecExpr *H = cast<SCEVAddRecExpr>(SE->getAddRecExpr(<br>
- Start, SE->getConstant(RealIVSCEV->getType(), Negative ? -1 : 1), L,<br>
- SCEV::FlagAnyWrap));<br>
- { // Limit the lifetime of SCEVExpander.<br>
- SCEVExpander Expander(*SE, DL, "reroll");<br>
- Value *NewIV = Expander.expandCodeFor(H, IV->getType(), &Header->front());<br>
-<br>
- for (auto &KV : Uses) {<br>
- if (KV.second.find_first() == 0)<br>
- KV.first->replaceUsesOfWith(DRS.BaseInst, NewIV);<br>
- }<br>
-<br>
- if (BranchInst *BI = dyn_cast<BranchInst>(Header->getTerminator())) {<br>
- // FIXME: Why do we need this check?<br>
- if (Uses[BI].find_first() == IL_All) {<br>
- const SCEV *ICSCEV = RealIVSCEV->evaluateAtIteration(IterCount, *SE);<br>
-<br>
- // Iteration count SCEV minus 1<br>
- const SCEV *ICMinus1SCEV = SE->getMinusSCEV(<br>
- ICSCEV, SE->getConstant(ICSCEV->getType(), Negative ? -1 : 1));<br>
-<br>
- Value *ICMinus1; // Iteration count minus 1<br>
- if (isa<SCEVConstant>(ICMinus1SCEV)) {<br>
- ICMinus1 = Expander.expandCodeFor(ICMinus1SCEV, NewIV->getType(), BI);<br>
- } else {<br>
- BasicBlock *Preheader = L->getLoopPreheader();<br>
- if (!Preheader)<br>
- Preheader = InsertPreheaderForLoop(L, DT, LI, PreserveLCSSA);<br>
+ replaceIV(DRS.BaseInst, IV, IterCount);<br>
<br>
- ICMinus1 = Expander.expandCodeFor(ICMinus1SCEV, NewIV->getType(),<br>
- Preheader->getTerminator());<br>
- }<br>
+ SimplifyInstructionsInBlock(Header, TLI);<br>
+ DeleteDeadPHIs(Header, TLI);<br>
+}<br>
<br>
- Value *Cond =<br>
- new ICmpInst(BI, CmpInst::ICMP_EQ, NewIV, ICMinus1, "exitcond");<br>
- BI->setCondition(Cond);<br>
+void LoopReroll::DAGRootTracker::replaceIV(Instruction *Inst,<br>
+ Instruction *InstIV,<br>
+ const SCEV *IterCount) {<br>
+ BasicBlock *Header = L->getHeader();<br>
+ int64_t Inc = IVToIncMap[InstIV];<br>
+ bool Negative = Inc < 0;<br>
+<br>
+ const SCEVAddRecExpr *RealIVSCEV = cast<SCEVAddRecExpr>(SE->getSCEV(Inst));<br>
+ const SCEV *Start = RealIVSCEV->getStart();<br>
<br>
- if (BI->getSuccessor(1) != Header)<br>
- BI->swapSuccessors();<br>
+ const SCEV *SizeOfExpr = nullptr;<br>
+ const SCEV *IncrExpr =<br>
+ SE->getConstant(RealIVSCEV->getType(), Negative ? -1 : 1);<br>
+ if (auto *PTy = dyn_cast<PointerType>(Inst->getType())) {<br>
+ Type *ElTy = PTy->getElementType();<br>
+ SizeOfExpr =<br>
+ SE->getSizeOfExpr(SE->getEffectiveSCEVType(Inst->getType()), ElTy);<br>
+ IncrExpr = SE->getMulExpr(IncrExpr, SizeOfExpr);<br>
+ }<br>
+ const SCEV *NewIVSCEV =<br>
+ SE->getAddRecExpr(Start, IncrExpr, L, SCEV::FlagAnyWrap);<br>
+<br>
+ { // Limit the lifetime of SCEVExpander.<br>
+ const DataLayout &DL = Header->getModule()->getDataLayout();<br>
+ SCEVExpander Expander(*SE, DL, "reroll");<br>
+ Value *NewIV =<br>
+ Expander.expandCodeFor(NewIVSCEV, InstIV->getType(), &Header->front());<br>
+<br>
+ for (auto &KV : Uses)<br>
+ if (KV.second.find_first() == 0)<br>
+ KV.first->replaceUsesOfWith(Inst, NewIV);<br>
+<br>
+ if (BranchInst *BI = dyn_cast<BranchInst>(Header->getTerminator())) {<br>
+ // FIXME: Why do we need this check?<br>
+ if (Uses[BI].find_first() == IL_All) {<br>
+ const SCEV *ICSCEV = RealIVSCEV->evaluateAtIteration(IterCount, *SE);<br>
+<br>
+ // Iteration count SCEV minus or plus 1<br>
+ const SCEV *MinusPlus1SCEV =<br>
+ SE->getConstant(ICSCEV->getType(), Negative ? -1 : 1);<br>
+ if (Inst->getType()->isPointerTy()) {<br>
+ assert(SizeOfExpr && "SizeOfExpr is not initialized");<br>
+ MinusPlus1SCEV = SE->getMulExpr(MinusPlus1SCEV, SizeOfExpr);<br>
}<br>
+<br>
+ const SCEV *ICMinusPlus1SCEV = SE->getMinusSCEV(ICSCEV, MinusPlus1SCEV);<br>
+ // Iteration count minus 1<br>
+ Value *ICMinusPlus1 = nullptr;<br>
+ if (isa<SCEVConstant>(ICMinusPlus1SCEV)) {<br>
+ ICMinusPlus1 =<br>
+ Expander.expandCodeFor(ICMinusPlus1SCEV, NewIV->getType(), BI);<br>
+ } else {<br>
+ BasicBlock *Preheader = L->getLoopPreheader();<br>
+ if (!Preheader)<br>
+ Preheader = InsertPreheaderForLoop(L, DT, LI, PreserveLCSSA);<br>
+ ICMinusPlus1 = Expander.expandCodeFor(<br>
+ ICMinusPlus1SCEV, NewIV->getType(), Preheader->getTerminator());<br>
+ }<br>
+<br>
+ Value *Cond =<br>
+ new ICmpInst(BI, CmpInst::ICMP_EQ, NewIV, ICMinusPlus1, "exitcond");<br>
+ BI->setCondition(Cond);<br>
+<br>
+ if (BI->getSuccessor(1) != Header)<br>
+ BI->swapSuccessors();<br>
}<br>
}<br>
}<br>
-<br>
- SimplifyInstructionsInBlock(Header, TLI);<br>
- DeleteDeadPHIs(Header, TLI);<br>
}<br>
<br>
// Validate the selected reductions. All iterations must have an isomorphic<br>
<br>
Added: llvm/trunk/test/Transforms/LoopReroll/ptrindvar.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopReroll/ptrindvar.ll?rev=258700&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopReroll/ptrindvar.ll?rev=258700&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/LoopReroll/ptrindvar.ll (added)<br>
+++ llvm/trunk/test/Transforms/LoopReroll/ptrindvar.ll Mon Jan 25 12:53:39 2016<br>
@@ -0,0 +1,81 @@<br>
+; RUN: opt -S -loop-reroll %s | FileCheck %s<br>
+target triple = "aarch64--linux-gnu"<br>
+<br>
+define i32 @test(i32* readonly %buf, i32* readnone %end) #0 {<br>
+entry:<br>
+ %cmp.9 = icmp eq i32* %buf, %end<br>
+ br i1 %cmp.9, label %while.end, label %while.body.preheader<br>
+<br>
+while.body.preheader:<br>
+ br label %while.body<br>
+<br>
+while.body:<br>
+;CHECK-LABEL: while.body:<br>
+;CHECK-NEXT: %indvar = phi i64 [ %indvar.next, %while.body ], [ 0, %while.body.preheader ]<br>
+;CHECK-NEXT: %S.011 = phi i32 [ %add, %while.body ], [ undef, %while.body.preheader ]<br>
+;CHECK-NEXT: %scevgep = getelementptr i32, i32* %buf, i64 %indvar<br>
+;CHECK-NEXT: %4 = load i32, i32* %scevgep, align 4<br>
+;CHECK-NEXT: %add = add nsw i32 %4, %S.011<br>
+;CHECK-NEXT: %indvar.next = add i64 %indvar, 1<br>
+;CHECK-NEXT: %exitcond = icmp eq i32* %scevgep, %scevgep5<br>
+;CHECK-NEXT: br i1 %exitcond, label %while.end.loopexit, label %while.body<br>
+<br>
+ %S.011 = phi i32 [ %add2, %while.body ], [ undef, %while.body.preheader ]<br>
+ %buf.addr.010 = phi i32* [ %add.ptr, %while.body ], [ %buf, %while.body.preheader ]<br>
+ %0 = load i32, i32* %buf.addr.010, align 4<br>
+ %add = add nsw i32 %0, %S.011<br>
+ %arrayidx1 = getelementptr inbounds i32, i32* %buf.addr.010, i64 1<br>
+ %1 = load i32, i32* %arrayidx1, align 4<br>
+ %add2 = add nsw i32 %add, %1<br>
+ %add.ptr = getelementptr inbounds i32, i32* %buf.addr.010, i64 2<br>
+ %cmp = icmp eq i32* %add.ptr, %end<br>
+ br i1 %cmp, label %while.end.loopexit, label %while.body<br>
+<br>
+while.end.loopexit:<br>
+ %add2.lcssa = phi i32 [ %add2, %while.body ]<br>
+ br label %while.end<br>
+<br>
+while.end:<br>
+ %S.0.lcssa = phi i32 [ undef, %entry ], [ %add2.lcssa, %while.end.loopexit ]<br>
+ ret i32 %S.0.lcssa<br>
+}<br>
+<br>
+define i32 @test2(i32* readonly %buf, i32* readnone %end) #0 {<br>
+entry:<br>
+ %cmp.9 = icmp eq i32* %buf, %end<br>
+ br i1 %cmp.9, label %while.end, label %while.body.preheader<br>
+<br>
+while.body.preheader:<br>
+ br label %while.body<br>
+<br>
+while.body:<br>
+;CHECK-LABEL: while.body:<br>
+;CHECK-NEXT: %indvar = phi i64 [ %indvar.next, %while.body ], [ 0, %while.body.preheader ]<br>
+;CHECK-NEXT: %S.011 = phi i32 [ %add, %while.body ], [ undef, %while.body.preheader ]<br>
+;CHECK-NEXT: %4 = mul i64 %indvar, -1<br>
+;CHECK-NEXT: %scevgep = getelementptr i32, i32* %buf, i64 %4<br>
+;CHECK-NEXT: %5 = load i32, i32* %scevgep, align 4<br>
+;CHECK-NEXT: %add = add nsw i32 %5, %S.011<br>
+;CHECK-NEXT: %indvar.next = add i64 %indvar, 1<br>
+;CHECK-NEXT: %exitcond = icmp eq i32* %scevgep, %scevgep5<br>
+;CHECK-NEXT: br i1 %exitcond, label %while.end.loopexit, label %while.body<br>
+<br>
+ %S.011 = phi i32 [ %add2, %while.body ], [ undef, %while.body.preheader ]<br>
+ %buf.addr.010 = phi i32* [ %add.ptr, %while.body ], [ %buf, %while.body.preheader ]<br>
+ %0 = load i32, i32* %buf.addr.010, align 4<br>
+ %add = add nsw i32 %0, %S.011<br>
+ %arrayidx1 = getelementptr inbounds i32, i32* %buf.addr.010, i64 -1<br>
+ %1 = load i32, i32* %arrayidx1, align 4<br>
+ %add2 = add nsw i32 %add, %1<br>
+ %add.ptr = getelementptr inbounds i32, i32* %buf.addr.010, i64 -2<br>
+ %cmp = icmp eq i32* %add.ptr, %end<br>
+ br i1 %cmp, label %while.end.loopexit, label %while.body<br>
+<br>
+while.end.loopexit:<br>
+ %add2.lcssa = phi i32 [ %add2, %while.body ]<br>
+ br label %while.end<br>
+<br>
+while.end:<br>
+ %S.0.lcssa = phi i32 [ undef, %entry ], [ %add2.lcssa, %while.end.loopexit ]<br>
+ ret i32 %S.0.lcssa<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>