<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>