[polly] r181986 - LoopGenerators: Construct loops such that they are already loop rotated

Tobias Grosser grosser at fim.uni-passau.de
Wed May 15 23:40:06 PDT 2013


Author: grosser
Date: Thu May 16 01:40:06 2013
New Revision: 181986

URL: http://llvm.org/viewvc/llvm-project?rev=181986&view=rev
Log:
LoopGenerators: Construct loops such that they are already loop rotated

                BeforeBB
                   |
                   v
                GuardBB
                /      \
       __  PreHeaderBB  \
      /  \    /         |
   latch  HeaderBB      |
      \  /    \         /
       <       \       /
                \     /
                ExitBB

This does not only remove the need for an explicit loop rotate pass, but it also
gives us the possibility to skip the construction of the guard condition in case
the loop is known to be executed at least once. We do not yet exploit this, but
by implementing this analysis in the isl code generator we should be able to
remove more guards than the generic loop rotate pass can.  Another point is that
loop rotation can introduce additional PHI nodes, which may hide that a loop can
be executed in parallel. This change avoids this complication and will make it
easier to move the openmp code generation into a separate pass.

Modified:
    polly/trunk/include/polly/CodeGen/LoopGenerators.h
    polly/trunk/lib/CodeGen/CodeGeneration.cpp
    polly/trunk/lib/CodeGen/IslCodeGeneration.cpp
    polly/trunk/lib/CodeGen/LoopGenerators.cpp
    polly/trunk/test/Cloog/CodeGen/MemAccess/codegen_simple_md.ll
    polly/trunk/test/Cloog/CodeGen/OpenMP/simple_nested_loop.ll
    polly/trunk/test/Isl/single_loop_param_less_equal.ll
    polly/trunk/test/Isl/single_loop_param_less_than.ll

Modified: polly/trunk/include/polly/CodeGen/LoopGenerators.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/CodeGen/LoopGenerators.h?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/include/polly/CodeGen/LoopGenerators.h (original)
+++ polly/trunk/include/polly/CodeGen/LoopGenerators.h Thu May 16 01:40:06 2013
@@ -36,10 +36,11 @@ using namespace llvm;
 /// @param Builder    The builder used to create the loop.
 /// @param P          A pointer to the pass that uses this function. It is used
 ///                   to update analysis information.
+/// @param ExitBlock  The block the loop will exit to.
 /// @param Predicate  The predicate used to generate the upper loop bound.
 /// @return Value*    The newly created induction variable for this loop.
 Value *createLoop(Value *LowerBound, Value *UpperBound, Value *Stride,
-                  IRBuilder<> &Builder, Pass *P, BasicBlock *&AfterBlock,
+                  IRBuilder<> &Builder, Pass *P, BasicBlock *&ExitBlock,
                   ICmpInst::Predicate Predicate);
 
 class OMPGenerator {

Modified: polly/trunk/lib/CodeGen/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/CodeGeneration.cpp?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/CodeGeneration.cpp Thu May 16 01:40:06 2013
@@ -468,14 +468,14 @@ void ClastStmtCodeGen::codegen(const cla
 
 void ClastStmtCodeGen::codegenForSequential(const clast_for *f) {
   Value *LowerBound, *UpperBound, *IV, *Stride;
-  BasicBlock *AfterBB;
+  BasicBlock *ExitBlock;
   Type *IntPtrTy = getIntPtrTy();
 
   LowerBound = ExpGen.codegen(f->LB, IntPtrTy);
   UpperBound = ExpGen.codegen(f->UB, IntPtrTy);
   Stride = Builder.getInt(APInt_from_MPZ(f->stride));
 
-  IV = createLoop(LowerBound, UpperBound, Stride, Builder, P, AfterBB,
+  IV = createLoop(LowerBound, UpperBound, Stride, Builder, P, ExitBlock,
                   CmpInst::ICMP_SLE);
 
   // Add loop iv to symbols.
@@ -486,7 +486,7 @@ void ClastStmtCodeGen::codegenForSequent
 
   // Loop is finished, so remove its iv from the live symbols.
   ClastVars.erase(f->iterator);
-  Builder.SetInsertPoint(AfterBB->begin());
+  Builder.SetInsertPoint(ExitBlock->begin());
 }
 
 // Helper class to determine all scalar parameters used in the basic blocks of a

Modified: polly/trunk/lib/CodeGen/IslCodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/IslCodeGeneration.cpp?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/IslCodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/IslCodeGeneration.cpp Thu May 16 01:40:06 2013
@@ -780,7 +780,7 @@ void IslNodeBuilder::createForSequential
   isl_id *IteratorID;
   Value *ValueLB, *ValueUB, *ValueInc;
   Type *MaxType;
-  BasicBlock *AfterBlock;
+  BasicBlock *ExitBlock;
   Value *IV;
   CmpInst::Predicate Predicate;
 
@@ -814,21 +814,14 @@ void IslNodeBuilder::createForSequential
   if (MaxType != ValueInc->getType())
     ValueInc = Builder.CreateSExt(ValueInc, MaxType);
 
-  // TODO: In case we can proof a loop is executed at least once, we can
-  //       generate the condition iv != UB + stride (consider possible
-  //       overflow). This condition will allow LLVM to prove the loop is
-  //       executed at least once, which will enable a lot of loop invariant
-  //       code motion.
-
-  IV =
-      createLoop(ValueLB, ValueUB, ValueInc, Builder, P, AfterBlock, Predicate);
+  IV = createLoop(ValueLB, ValueUB, ValueInc, Builder, P, ExitBlock, Predicate);
   IDToValue[IteratorID] = IV;
 
   create(Body);
 
   IDToValue.erase(IteratorID);
 
-  Builder.SetInsertPoint(AfterBlock->begin());
+  Builder.SetInsertPoint(ExitBlock->begin());
 
   isl_ast_node_free(For);
   isl_ast_expr_free(Iterator);

Modified: polly/trunk/lib/CodeGen/LoopGenerators.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/LoopGenerators.cpp?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/LoopGenerators.cpp (original)
+++ polly/trunk/lib/CodeGen/LoopGenerators.cpp Thu May 16 01:40:06 2013
@@ -22,53 +22,84 @@
 using namespace llvm;
 using namespace polly;
 
+// We generate a loop of the following structure
+//
+//              BeforeBB
+//                 |
+//                 v
+//              GuardBB
+//              /      \
+//     __  PreHeaderBB  \
+//    /  \    /         |
+// latch  HeaderBB      |
+//    \  /    \         /
+//     <       \       /
+//              \     /
+//              ExitBB
+//
+// GuardBB checks if the loop is executed at least once. If this is the case
+// we branch to PreHeaderBB and subsequently to the HeaderBB, which contains the
+// loop iv 'polly.indvar', the incremented loop iv 'polly.indvar_next' as well
+// as the condition to check if we execute another iteration of the loop. After
+// the loop has finished, we branch to ExitBB.
+//
+// TODO: We currently always create the GuardBB. If we can prove the loop is
+//       always executed at least once, we can get rid of this branch.
 Value *polly::createLoop(Value *LB, Value *UB, Value *Stride,
-                         IRBuilder<> &Builder, Pass *P, BasicBlock *&AfterBlock,
+                         IRBuilder<> &Builder, Pass *P, BasicBlock *&ExitBB,
                          ICmpInst::Predicate Predicate) {
+
   DominatorTree &DT = P->getAnalysis<DominatorTree>();
   Function *F = Builder.GetInsertBlock()->getParent();
   LLVMContext &Context = F->getContext();
 
-  BasicBlock *PreheaderBB = Builder.GetInsertBlock();
-  BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.loop_header", F);
-  BasicBlock *BodyBB = BasicBlock::Create(Context, "polly.loop_body", F);
-  BasicBlock *AfterBB = SplitBlock(PreheaderBB, Builder.GetInsertPoint()++, P);
-  AfterBB->setName("polly.loop_after");
-
-  PreheaderBB->getTerminator()->setSuccessor(0, HeaderBB);
-  DT.addNewBlock(HeaderBB, PreheaderBB);
-
-  Builder.SetInsertPoint(HeaderBB);
-
-  // Use the type of upper and lower bound.
-  assert(LB->getType() == UB->getType() &&
-         "Different types for upper and lower bound.");
-
+  assert(LB->getType() == UB->getType() && "Types of loop bounds do not match");
   IntegerType *LoopIVType = dyn_cast<IntegerType>(UB->getType());
   assert(LoopIVType && "UB is not integer?");
 
-  // IV
-  PHINode *IV = Builder.CreatePHI(LoopIVType, 2, "polly.loopiv");
-  IV->addIncoming(LB, PreheaderBB);
-
-  Stride = Builder.CreateZExtOrBitCast(Stride, LoopIVType);
-  Value *IncrementedIV = Builder.CreateNSWAdd(IV, Stride, "polly.next_loopiv");
-
-  // Exit condition.
-  Value *CMP;
-  CMP = Builder.CreateICmp(Predicate, IV, UB);
-
-  Builder.CreateCondBr(CMP, BodyBB, AfterBB);
-  DT.addNewBlock(BodyBB, HeaderBB);
+  BasicBlock *BeforeBB = Builder.GetInsertBlock();
+  BasicBlock *GuardBB = BasicBlock::Create(Context, "polly.loop_if", F);
+  BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.loop_header", F);
+  BasicBlock *PreHeaderBB =
+      BasicBlock::Create(Context, "polly.loop_preheader", F);
 
-  Builder.SetInsertPoint(BodyBB);
+  // ExitBB
+  ExitBB = SplitBlock(BeforeBB, Builder.GetInsertPoint()++, P);
+  ExitBB->setName("polly.loop_exit");
+
+  // BeforeBB
+  BeforeBB->getTerminator()->setSuccessor(0, GuardBB);
+
+  // GuardBB
+  DT.addNewBlock(GuardBB, BeforeBB);
+  Builder.SetInsertPoint(GuardBB);
+  Value *LoopGuard;
+  LoopGuard = Builder.CreateICmp(Predicate, LB, UB);
+  LoopGuard->setName("polly.loop_guard");
+  Builder.CreateCondBr(LoopGuard, PreHeaderBB, ExitBB);
+
+  // PreHeaderBB
+  DT.addNewBlock(PreHeaderBB, GuardBB);
+  Builder.SetInsertPoint(PreHeaderBB);
   Builder.CreateBr(HeaderBB);
-  IV->addIncoming(IncrementedIV, BodyBB);
-  DT.changeImmediateDominator(AfterBB, HeaderBB);
 
-  Builder.SetInsertPoint(BodyBB->begin());
-  AfterBlock = AfterBB;
+  // HeaderBB
+  DT.addNewBlock(HeaderBB, PreHeaderBB);
+  Builder.SetInsertPoint(HeaderBB);
+  PHINode *IV = Builder.CreatePHI(LoopIVType, 2, "polly.indvar");
+  IV->addIncoming(LB, PreHeaderBB);
+  Stride = Builder.CreateZExtOrBitCast(Stride, LoopIVType);
+  Value *IncrementedIV = Builder.CreateNSWAdd(IV, Stride, "polly.indvar_next");
+  Value *LoopCondition;
+  UB = Builder.CreateSub(UB, Stride, "polly.adjust_ub");
+  LoopCondition = Builder.CreateICmp(Predicate, IV, UB);
+  LoopCondition->setName("polly.loop_cond");
+  Builder.CreateCondBr(LoopCondition, HeaderBB, ExitBB);
+  IV->addIncoming(IncrementedIV, HeaderBB);
+  DT.changeImmediateDominator(ExitBB, GuardBB);
 
+  // The loop body should be added here.
+  Builder.SetInsertPoint(HeaderBB->getFirstNonPHI());
   return IV;
 }
 

Modified: polly/trunk/test/Cloog/CodeGen/MemAccess/codegen_simple_md.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Cloog/CodeGen/MemAccess/codegen_simple_md.ll?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/test/Cloog/CodeGen/MemAccess/codegen_simple_md.ll (original)
+++ polly/trunk/test/Cloog/CodeGen/MemAccess/codegen_simple_md.ll Thu May 16 01:40:06 2013
@@ -59,16 +59,16 @@ for.end6:
 ; WITHCONST:  %p_mul_coeff = mul i64 16, [[REG1]]
 ; WITHCONST:  %p_sum_coeff = add i64 5, %p_mul_coeff
 ; WITHCONST:  [[REG2:%[0-9]+]] = sext i32 %{{[0-9]+}} to i64
-; WITHCONST:  %p_mul_coeff6 = mul i64 2, [[REG2]]
-; WITHCONST:  %p_sum_coeff7 = add i64 %p_sum_coeff, %p_mul_coeff6
-; WITHCONST:  %p_newarrayidx_ = getelementptr [1040 x i32]* @A, i64 0, i64 %p_sum_coeff7
+; WITHCONST:  %p_mul_coeff8 = mul i64 2, [[REG2]]
+; WITHCONST:  %p_sum_coeff9 = add i64 %p_sum_coeff, %p_mul_coeff8
+; WITHCONST:  %p_newarrayidx_ = getelementptr [1040 x i32]* @A, i64 0, i64 %p_sum_coeff9
 ; WITHCONST:  store i32 100, i32* %p_newarrayidx_
 
 ; WITHOUTCONST:  [[REG1:%[0-9]+]] = sext i32 %{{[0-9]+}} to i64
 ; WITHOUTCONST:  %p_mul_coeff = mul i64 16, [[REG1]]
 ; WITHOUTCONST:  %p_sum_coeff = add i64 0, %p_mul_coeff
 ; WITHOUTCONST:  [[REG2:%[0-9]+]] = sext i32 %{{[0-9]+}} to i64
-; WITHOUTCONST:  %p_mul_coeff6 = mul i64 2, [[REG2]]
-; WITHOUTCONST:  %p_sum_coeff7 = add i64 %p_sum_coeff, %p_mul_coeff6
-; WITHOUTCONST:  %p_newarrayidx_ = getelementptr [1040 x i32]* @A, i64 0, i64 %p_sum_coeff7
+; WITHOUTCONST:  %p_mul_coeff8 = mul i64 2, [[REG2]]
+; WITHOUTCONST:  %p_sum_coeff9 = add i64 %p_sum_coeff, %p_mul_coeff8
+; WITHOUTCONST:  %p_newarrayidx_ = getelementptr [1040 x i32]* @A, i64 0, i64 %p_sum_coeff9
 ; WITHOUTCONST:  store i32 100, i32* %p_newarrayidx_

Modified: polly/trunk/test/Cloog/CodeGen/OpenMP/simple_nested_loop.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Cloog/CodeGen/OpenMP/simple_nested_loop.ll?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/test/Cloog/CodeGen/OpenMP/simple_nested_loop.ll (original)
+++ polly/trunk/test/Cloog/CodeGen/OpenMP/simple_nested_loop.ll Thu May 16 01:40:06 2013
@@ -80,7 +80,7 @@ declare void @llvm.memset.p0i8.i32(i8* n
 
 ; CHECK: %omp.userContext = alloca { i32 }
 ; CHECK: getelementptr inbounds { i32 }* %omp.userContext, i32 0, i32 0
-; CHECK: store i32 %polly.loopiv, i32* %1
+; CHECK: store i32 %polly.indvar, i32* %0
 ; CHECK: %omp_data = bitcast { i32 }* %omp.userContext to i8*
 ; CHECK: call void @GOMP_parallel_loop_runtime_start(void (i8*)* @loop_openmp.omp_subfn, i8* %omp_data, i32 0, i32 0, i32 10, i32 1)
 ; CHECK: call void @loop_openmp.omp_subfn(i8* %omp_data)

Modified: polly/trunk/test/Isl/single_loop_param_less_equal.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/single_loop_param_less_equal.ll?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/test/Isl/single_loop_param_less_equal.ll (original)
+++ polly/trunk/test/Isl/single_loop_param_less_equal.ll Thu May 16 01:40:06 2013
@@ -34,21 +34,26 @@ ret:
 ; CHECK:   Stmt_loop_body(c1)
 
 ; CODEGEN: polly.start:
-; CODEGEN:   br label %polly.loop_header
+; CODEGEN:   br label %polly.loop_if
 
-; CODEGEN: polly.loop_after:
+; CODEGEN: polly.loop_exit:
 ; CODEGEN:   br label %polly.merge_new_and_old
 
-; CODEGEN: polly.loop_header:
-; CODEGEN:   %polly.loopiv = phi i64 [ 0, %polly.start ], [ %polly.next_loopiv, %polly.stmt.loop.body ]
-; CODEGEN:   %polly.next_loopiv = add nsw i64 %polly.loopiv, 1
-; CODEGEN:   %0 = icmp sle i64 %polly.loopiv, %n
-; CODEGEN:   br i1 %0, label %polly.loop_body, label %polly.loop_after
+; CODEGEN: polly.loop_if:
+; CODEGEN:   %polly.loop_guard = icmp sle i64 0, %n
+; CODEGEN:   br i1 %polly.loop_guard, label %polly.loop_preheader, label %polly.loop_exit
 
-; CODEGEN: polly.loop_body:
+; CODEGEN: polly.loop_header:
+; CODEGEN:   %polly.indvar = phi i64 [ 0, %polly.loop_preheader ], [ %polly.indvar_next, %polly.stmt.loop.body ]
 ; CODEGEN:   br label %polly.stmt.loop.body
 
 ; CODEGEN: polly.stmt.loop.body:
-; CODEGEN:   %p_scevgep.moved.to.loop.body = getelementptr [1024 x i32]* @A, i64 0, i64 %polly.loopiv
+; CODEGEN:   %p_scevgep.moved.to.loop.body = getelementptr [1024 x i32]* @A, i64 0, i64 %polly.indvar
 ; CODEGEN:   store i32 1, i32* %p_scevgep.moved.to.loop.body
+; CODEGEN:   %polly.indvar_next = add nsw i64 %polly.indvar, 1
+; CODEGEN:   %polly.adjust_ub = sub i64 %n, 1
+; CODEGEN:   %polly.loop_cond = icmp sle i64 %polly.indvar, %polly.adjust_ub
+; CODEGEN:   br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
+
+; CODEGEN: polly.loop_preheader:
 ; CODEGEN:   br label %polly.loop_header

Modified: polly/trunk/test/Isl/single_loop_param_less_than.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/single_loop_param_less_than.ll?rev=181986&r1=181985&r2=181986&view=diff
==============================================================================
--- polly/trunk/test/Isl/single_loop_param_less_than.ll (original)
+++ polly/trunk/test/Isl/single_loop_param_less_than.ll Thu May 16 01:40:06 2013
@@ -33,21 +33,26 @@ ret:
 ; CHECK:   Stmt_loop_body(c1)
 
 ; CODEGEN: polly.start:
-; CODEGEN:   br label %polly.loop_header
+; CODEGEN:   br label %polly.loop_if
 
-; CODEGEN: polly.loop_after:
+; CODEGEN: polly.loop_exit:
 ; CODEGEN:   br label %polly.merge_new_and_old
 
-; CODEGEN: polly.loop_header:
-; CODEGEN:   %polly.loopiv = phi i64 [ 0, %polly.start ], [ %polly.next_loopiv, %polly.stmt.loop.body ]
-; CODEGEN:   %polly.next_loopiv = add nsw i64 %polly.loopiv, 1
-; CODEGEN:   %0 = icmp slt i64 %polly.loopiv, %n
-; CODEGEN:   br i1 %0, label %polly.loop_body, label %polly.loop_after
+; CODEGEN: polly.loop_if:
+; CODEGEN:   %polly.loop_guard = icmp slt i64 0, %n
+; CODEGEN:   br i1 %polly.loop_guard, label %polly.loop_preheader, label %polly.loop_exit
 
-; CODEGEN: polly.loop_body:
+; CODEGEN: polly.loop_header:
+; CODEGEN:   %polly.indvar = phi i64 [ 0, %polly.loop_preheader ], [ %polly.indvar_next, %polly.stmt.loop.body ]
 ; CODEGEN:   br label %polly.stmt.loop.body
 
 ; CODEGEN: polly.stmt.loop.body:
-; CODEGEN:   %p_scevgep.moved.to.loop.body = getelementptr [1024 x i32]* @A, i64 0, i64 %polly.loopiv
+; CODEGEN:   %p_scevgep.moved.to.loop.body = getelementptr [1024 x i32]* @A, i64 0, i64 %polly.indvar
 ; CODEGEN:   store i32 1, i32* %p_scevgep.moved.to.loop.body
-; CODEGEN:   br label %polly.loop_header
+; CODEGEN:   %polly.indvar_next = add nsw i64 %polly.indvar, 1
+; CODEGEN:   %polly.adjust_ub = sub i64 %n, 1
+; CODEGEN:   %polly.loop_cond = icmp slt i64 %polly.indvar, %polly.adjust_ub
+; CODEGEN:   br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
+
+; CODEGEN: polly.loop_preheader:
+; CODEGENL   br label %polly.loop_header





More information about the llvm-commits mailing list