[polly] r179586 - Support SCoPs with multiple entry edges.

Tobias Grosser grosser at fim.uni-passau.de
Tue Apr 16 01:04:43 PDT 2013


Author: grosser
Date: Tue Apr 16 03:04:42 2013
New Revision: 179586

URL: http://llvm.org/viewvc/llvm-project?rev=179586&view=rev
Log:
Support SCoPs with multiple entry edges.

Regions that have multiple entry edges are very common. A simple if condition
yields e.g. such a region:

  if
 /   \
then  else
 \   /
for_region

This for_region contains two entry edges 'then' -> 'for_region' and 'else' -> 'for_region'.

Previously we scheduled the RegionSimplify pass to translate such regions into
simple regions. With this patch, we now support them natively when the region is
in -loop-simplify form, which means the entry block should not be a loop header.

Contributed by:  Star Tan <tanmx_star at yeah.net>

Added:
    polly/trunk/test/Isl/CodeGen/simple_non_single_entry.ll
    polly/trunk/test/ScopDetect/simple_non_single_entry.ll
      - copied, changed from r179485, polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll
Modified:
    polly/trunk/include/polly/Support/ScopHelper.h
    polly/trunk/lib/Analysis/ScopDetection.cpp
    polly/trunk/lib/CodeGen/CodeGeneration.cpp
    polly/trunk/lib/CodeGen/IslCodeGeneration.cpp
    polly/trunk/lib/Support/ScopHelper.cpp
    polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll

Modified: polly/trunk/include/polly/Support/ScopHelper.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ScopHelper.h?rev=179586&r1=179585&r2=179586&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ScopHelper.h (original)
+++ polly/trunk/include/polly/Support/ScopHelper.h Tue Apr 16 03:04:42 2013
@@ -28,6 +28,7 @@ class BasicBlock;
 }
 
 namespace polly {
+class Scop;
 /// Temporary Hack for extended regiontree.
 ///
 /// @brief Cast the region to loop.
@@ -51,6 +52,14 @@ bool hasInvokeEdge(const llvm::PHINode *
 llvm::Value *getPointerOperand(llvm::Instruction &Inst);
 llvm::BasicBlock *createSingleExitEdge(llvm::Region *R, llvm::Pass *P);
 
+/// @brief Simplify the region in a scop to have a single entry edge
+///        and a single exit edge.
+///
+/// @param S  The scop that is simplified.
+/// @param P  The pass that is currently running.
+///
+void simplifyRegion(polly::Scop *S, llvm::Pass *P);
+
 /// @brief Split the entry block of a function to store the newly inserted
 ///        allocations outside of all Scops.
 ///

Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=179586&r1=179585&r2=179586&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Tue Apr 16 03:04:42 2013
@@ -133,7 +133,7 @@ BADSCOP_STAT(FuncCall, "Function call wi
 BADSCOP_STAT(AffFunc, "Expression not affine");
 BADSCOP_STAT(Scalar, "Found scalar dependency");
 BADSCOP_STAT(Alias, "Found base address alias");
-BADSCOP_STAT(SimpleRegion, "Region not simple");
+BADSCOP_STAT(SimpleLoop, "Loop not in -loop-simplify form");
 BADSCOP_STAT(Other, "Others");
 
 //===----------------------------------------------------------------------===//
@@ -549,15 +549,17 @@ bool ScopDetection::isValidRegion(Detect
     return false;
   }
 
+  if (!R.getEnteringBlock()){
+    Loop *L = LI->getLoopFor(R.getEntry());
+    if (L && !L->isLoopSimplifyForm())
+      INVALID(SimpleLoop, "Loop not in simplify form is invalid!");
+  }
+
   // SCoP cannot contain the entry block of the function, because we need
   // to insert alloca instruction there when translate scalar to array.
   if (R.getEntry() == &(R.getEntry()->getParent()->getEntryBlock()))
     INVALID(Other, "Region containing entry block of function is invalid!");
 
-  // Only regions that have a single entry are allowed.
-  if (!R.getEnteringBlock())
-    INVALID(SimpleRegion, "Region has multiple entries: " << R.getNameStr());
-
   if (!isValidExit(Context))
     return false;
 

Modified: polly/trunk/lib/CodeGen/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/CodeGeneration.cpp?rev=179586&r1=179585&r2=179586&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/CodeGeneration.cpp Tue Apr 16 03:04:42 2013
@@ -986,16 +986,10 @@ public:
   bool runOnScop(Scop &S) {
     ParallelLoops.clear();
 
-    Region &R = S.getRegion();
+    assert(!S.getRegion().isTopLevelRegion()
+           && "Top level regions are not supported");
 
-    assert(!R.isTopLevelRegion() && "Top level regions are not supported");
-    assert(R.getEnteringBlock() && "Only support regions with a single entry");
-
-    if (!R.getExitingBlock()) {
-      BasicBlock *newExit = createSingleExitEdge(&R, this);
-      for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI)
-        (*RI)->replaceExitRecursive(newExit);
-    }
+    simplifyRegion(&S, this);
 
     BasicBlock *StartBlock = executeScopConditionally(S, this);
 

Modified: polly/trunk/lib/CodeGen/IslCodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/IslCodeGeneration.cpp?rev=179586&r1=179585&r2=179586&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/IslCodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/IslCodeGeneration.cpp Tue Apr 16 03:04:42 2013
@@ -1026,16 +1026,10 @@ public:
   bool runOnScop(Scop &S) {
     IslAstInfo &AstInfo = getAnalysis<IslAstInfo>();
 
-    Region &R = S.getRegion();
+    assert(!S.getRegion().isTopLevelRegion()
+           && "Top level regions are not supported");
 
-    assert(!R.isTopLevelRegion() && "Top level regions are not supported");
-    assert(R.getEnteringBlock() && "Only support regions with a single entry");
-
-    if (!R.getExitingBlock()) {
-      BasicBlock *newExit = createSingleExitEdge(&R, this);
-      for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI)
-        (*RI)->replaceExitRecursive(newExit);
-    }
+    simplifyRegion(&S, this);
 
     BasicBlock *StartBlock = executeScopConditionally(S, this);
     isl_ast_node *Ast = AstInfo.getAst();

Modified: polly/trunk/lib/Support/ScopHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/ScopHelper.cpp?rev=179586&r1=179585&r2=179586&view=diff
==============================================================================
--- polly/trunk/lib/Support/ScopHelper.cpp (original)
+++ polly/trunk/lib/Support/ScopHelper.cpp Tue Apr 16 03:04:42 2013
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "polly/Support/ScopHelper.h"
+#include "polly/ScopInfo.h"
 
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/RegionInfo.h"
@@ -86,6 +87,32 @@ BasicBlock *polly::createSingleExitEdge(
   return SplitBlockPredecessors(BB, Preds, ".region", P);
 }
 
+void polly::simplifyRegion(Scop *S, Pass *P){
+  Region *R = &S->getRegion();
+
+  // Create single entry edge if the region has multiple entry edges.
+  if (!R->getEnteringBlock()){
+    BasicBlock *OldEntry = R->getEntry();
+    BasicBlock *NewEntry = SplitBlock (OldEntry, OldEntry->begin(), P);
+
+    for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI)
+      if ((*SI)->getBasicBlock() == OldEntry) {
+        (*SI)->setBasicBlock(NewEntry);
+        break;
+      }
+
+    R->replaceEntryRecursive(NewEntry);
+  }
+
+  // Create single exit edge if the region has multiple exit edges.
+  if (!R->getExitingBlock()) {
+    BasicBlock *NewExit = createSingleExitEdge(R, P);
+
+    for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI)
+      (*RI)->replaceExitRecursive(NewExit);
+  }
+}
+
 void polly::splitEntryBlockForAlloca(BasicBlock *EntryBlock, Pass *P) {
   // Find first non-alloca instruction. Every basic block has a non-alloc
   // instruction, as every well formed basic block has a terminator.

Added: polly/trunk/test/Isl/CodeGen/simple_non_single_entry.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/simple_non_single_entry.ll?rev=179586&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/simple_non_single_entry.ll (added)
+++ polly/trunk/test/Isl/CodeGen/simple_non_single_entry.ll Tue Apr 16 03:04:42 2013
@@ -0,0 +1,71 @@
+; RUN: opt %loadPolly -polly-codegen-isl -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen-isl -S < %s | FileCheck %s -check-prefix=CHECK-CODE
+
+; void f(long A[], long N) {
+;   long i;
+;
+;  if (true){
+;    i = 0;
+;    goto next;
+;  }else{
+;    i = 1;
+;    goto next;
+; }
+;
+; next:
+;  if (true)
+;    goto for.i;
+;  else
+;    goto for.i;
+;
+; for.i:
+;   for (i = 0; i < N; ++i)
+;     A[i] = i;
+; }
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i64* %A, i64 %N) nounwind {
+entry:
+  fence seq_cst
+  br i1 true, label %then1, label %else1
+
+then1:
+  br label %next
+
+else1:
+  br label %next
+
+next:
+  br i1 true, label %then, label %else
+
+then:
+  br label %for.i.head
+
+else:
+  br label %for.i.head
+
+for.i.head:
+  br label %for.i.head1
+
+for.i.head1:
+  br label %for.i
+
+for.i:
+  %indvar = phi i64 [ 0, %for.i.head1], [ %indvar.next, %for.i ]
+  fence seq_cst
+  %scevgep = getelementptr i64* %A, i64 %indvar
+  store i64 %indvar, i64* %scevgep
+  %indvar.next = add nsw i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, %N
+  br i1 %exitcond, label %return, label %for.i
+
+return:
+  fence seq_cst
+  ret void
+}
+
+; CHECK: Create LLVM-IR from SCoPs' for region: 'next.split => polly.merge_new_and_old'
+; CHECK-CODE: polly.split_new_and_old
+; CHECK-CODE: polly.merge_new_and_old

Modified: polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll?rev=179586&r1=179585&r2=179586&view=diff
==============================================================================
--- polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll (original)
+++ polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll Tue Apr 16 03:04:42 2013
@@ -1,7 +1,5 @@
 ; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
-; RUN: opt %loadPolly -polly-region-simplify -polly-detect -analyze < %s | FileCheck %s -check-prefix=CHECK-SIMPLIFY
 ; RUN: opt %loadPolly -polly-detect -polly-codegen-scev -analyze < %s | FileCheck %s
-; RUN: opt %loadPolly -polly-region-simplify -polly-detect -polly-codegen-scev -analyze < %s | FileCheck %s -check-prefix=CHECK-SIMPLIFY
 
 ; void f(long A[], long N) {
 ;   long i;
@@ -16,6 +14,8 @@
 ;     A[i] = i;
 ; }
 
+; We will not detect this scop, as the loop is not in -loop-simplify form.
+
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
 target triple = "x86_64-unknown-linux-gnu"
 
@@ -44,4 +44,3 @@ return:
 }
 
 ; CHECK-NOT: Valid Region for Scop
-; CHECK-SIMPLIFY: Valid Region for Scop: for.i => return

Copied: polly/trunk/test/ScopDetect/simple_non_single_entry.ll (from r179485, polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll)
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopDetect/simple_non_single_entry.ll?p2=polly/trunk/test/ScopDetect/simple_non_single_entry.ll&p1=polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll&r1=179485&r2=179586&rev=179586&view=diff
==============================================================================
--- polly/trunk/test/ScopDetect/simple_loop_non_single_entry.ll (original)
+++ polly/trunk/test/ScopDetect/simple_non_single_entry.ll Tue Apr 16 03:04:42 2013
@@ -1,17 +1,24 @@
 ; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
-; RUN: opt %loadPolly -polly-region-simplify -polly-detect -analyze < %s | FileCheck %s -check-prefix=CHECK-SIMPLIFY
 ; RUN: opt %loadPolly -polly-detect -polly-codegen-scev -analyze < %s | FileCheck %s
-; RUN: opt %loadPolly -polly-region-simplify -polly-detect -polly-codegen-scev -analyze < %s | FileCheck %s -check-prefix=CHECK-SIMPLIFY
 
 ; void f(long A[], long N) {
 ;   long i;
 ;
+;  if (true){
+;    i = 0;
+;    goto next;
+;  }else{
+;    i = 1;
+;    goto next;
+; }
+;
+; next:
 ;  if (true)
-;    goto loop;
+;    goto for.i;
 ;  else
-;    goto loop;
+;    goto for.i;
 ;
-; loop:
+; for.i:
 ;   for (i = 0; i < N; ++i)
 ;     A[i] = i;
 ; }
@@ -22,16 +29,32 @@ target triple = "x86_64-unknown-linux-gn
 define void @f(i64* %A, i64 %N) nounwind {
 entry:
   fence seq_cst
+  br i1 true, label %then1, label %else1
+
+then1:
+  br label %next
+
+else1:
+  br label %next
+
+next:
   br i1 true, label %then, label %else
 
 then:
-  br label %for.i
+  br label %for.i.head
 
 else:
+  br label %for.i.head
+
+for.i.head:
+  br label %for.i.head1
+
+for.i.head1:
   br label %for.i
 
 for.i:
-  %indvar = phi i64 [ 0, %then ], [ 0, %else], [ %indvar.next, %for.i ]
+  %indvar = phi i64 [ 0, %for.i.head1], [ %indvar.next, %for.i ]
+  fence seq_cst
   %scevgep = getelementptr i64* %A, i64 %indvar
   store i64 %indvar, i64* %scevgep
   %indvar.next = add nsw i64 %indvar, 1
@@ -43,5 +66,4 @@ return:
   ret void
 }
 
-; CHECK-NOT: Valid Region for Scop
-; CHECK-SIMPLIFY: Valid Region for Scop: for.i => return
+; CHECK: Valid Region for Scop: next => for.i.head1





More information about the llvm-commits mailing list