[llvm-commits] [polly] r131352 - in /polly/trunk: include/polly/Support/ScopHelper.h lib/CodeGeneration.cpp lib/Support/ScopHelper.cpp test/CodeGen/split_edges.ll test/CodeGen/split_edges_2.ll
Tobias Grosser
grosser at fim.uni-passau.de
Sat May 14 12:01:49 PDT 2011
Author: grosser
Date: Sat May 14 14:01:49 2011
New Revision: 131352
URL: http://llvm.org/viewvc/llvm-project?rev=131352&view=rev
Log:
CodeGeneration: Do not delete the old version of the Scop.
Instead of deleting the old code, keep it on the side in an if-branch. It will
either be deleted by the dead code elimination or we can use it as fallback.
Added:
polly/trunk/test/CodeGen/split_edges.ll
polly/trunk/test/CodeGen/split_edges_2.ll
Modified:
polly/trunk/include/polly/Support/ScopHelper.h
polly/trunk/lib/CodeGeneration.cpp
polly/trunk/lib/Support/ScopHelper.cpp
Modified: polly/trunk/include/polly/Support/ScopHelper.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ScopHelper.h?rev=131352&r1=131351&r2=131352&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ScopHelper.h (original)
+++ polly/trunk/include/polly/Support/ScopHelper.h Sat May 14 14:01:49 2011
@@ -72,7 +72,6 @@
llvm::Value *getPointerOperand(llvm::Instruction &Inst);
// Helper function for LLVM-IR about Scop.
- llvm::BasicBlock *createSingleEntryEdge(llvm::Region *R, llvm::Pass *P);
llvm::BasicBlock *createSingleExitEdge(llvm::Region *R, llvm::Pass *P);
/// @brief Split the entry block of a function to store the newly inserted
Modified: polly/trunk/lib/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGeneration.cpp?rev=131352&r1=131351&r2=131352&view=diff
==============================================================================
--- polly/trunk/lib/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGeneration.cpp Sat May 14 14:01:49 2011
@@ -34,6 +34,7 @@
#include "llvm/Support/IRBuilder.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Module.h"
#include "llvm/ADT/SetVector.h"
@@ -1271,6 +1272,7 @@
CloogInfo *C;
LoopInfo *LI;
TargetData *TD;
+ RegionInfo *RI;
std::vector<std::string> parallelLoops;
@@ -1279,17 +1281,6 @@
CodeGeneration() : ScopPass(ID) {}
- void createSeSeEdges(Region *R) {
- BasicBlock *newEntry = createSingleEntryEdge(R, this);
-
- for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI)
- if ((*SI)->getBasicBlock() == R->getEntry())
- (*SI)->setBasicBlock(newEntry);
-
- createSingleExitEdge(R, this);
- }
-
-
// Adding prototypes required if OpenMP is enabled.
void addOpenMPDefinitions(IRBuilder<> &Builder)
{
@@ -1342,10 +1333,90 @@
}
}
+ // Split the entry edge of the region and generate a new basic block on this
+ // edge. This function also updates ScopInfo and RegionInfo.
+ //
+ // @param region The region where the entry edge will be splitted.
+ BasicBlock *splitEdgeAdvanced(Region *region) {
+ BasicBlock *newBlock;
+ BasicBlock *splitBlock;
+
+ newBlock = SplitEdge(region->getEnteringBlock(), region->getEntry(), this);
+
+ if (DT->dominates(region->getEntry(), newBlock)) {
+ // Update ScopInfo.
+ for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI)
+ if ((*SI)->getBasicBlock() == newBlock) {
+ (*SI)->setBasicBlock(newBlock);
+ break;
+ }
+
+ // Update RegionInfo.
+ splitBlock = region->getEntry();
+ region->replaceEntry(newBlock);
+ } else {
+ RI->setRegionFor(newBlock, region->getParent());
+ splitBlock = newBlock;
+ }
+
+ return splitBlock;
+ }
+
+ // Create a split block that branches either to the old code or to a new basic
+ // block where the new code can be inserted.
+ //
+ // @param builder A builder that will be set to point to a basic block, where
+ // the new code can be generated.
+ // @return The split basic block.
+ BasicBlock *addSplitAndStartBlock(IRBuilder<> *builder) {
+ BasicBlock *splitBlock = splitEdgeAdvanced(region);
+
+ splitBlock->setName("polly.enterScop");
+
+ Function *function = splitBlock->getParent();
+ BasicBlock *startBlock = BasicBlock::Create(function->getContext(),
+ "polly.start", function);
+ splitBlock->getTerminator()->eraseFromParent();
+ builder->SetInsertPoint(splitBlock);
+ builder->CreateCondBr(builder->getTrue(), startBlock, region->getEntry());
+ DT->addNewBlock(startBlock, splitBlock);
+
+ // Start code generation here.
+ builder->SetInsertPoint(startBlock);
+ return splitBlock;
+ }
+
+ // Merge the control flow of the newly generated code with the existing code.
+ //
+ // @param splitBlock The basic block where the control flow was split between
+ // old and new version of the Scop.
+ // @param builder An IRBuilder that points to the last instruction of the
+ // newly generated code.
+ void mergeControlFlow(BasicBlock *splitBlock, IRBuilder<> *builder) {
+ BasicBlock *mergeBlock;
+ Region *R = region;
+
+ if (R->getExit()->getSinglePredecessor())
+ // No splitEdge required. A block with a single predecessor cannot have
+ // PHI nodes that would complicate life.
+ mergeBlock = R->getExit();
+ else {
+ mergeBlock = SplitEdge(R->getExitingBlock(), R->getExit(), this);
+ // SplitEdge will never split R->getExit(), as R->getExit() has more than
+ // one predecessor. Hence, mergeBlock is always a newly generated block.
+ mergeBlock->setName("polly.finalMerge");
+ R->replaceExit(mergeBlock);
+ }
+
+ builder->CreateBr(mergeBlock);
+
+ if (DT->dominates(splitBlock, mergeBlock))
+ DT->changeImmediateDominator(mergeBlock, splitBlock);
+ }
+
bool runOnScop(Scop &scop) {
S = &scop;
region = &S->getRegion();
- Region *R = region;
DT = &getAnalysis<DominatorTree>();
Dependences *DP = &getAnalysis<Dependences>();
SE = &getAnalysis<ScalarEvolution>();
@@ -1353,91 +1424,66 @@
C = &getAnalysis<CloogInfo>();
SD = &getAnalysis<ScopDetection>();
TD = &getAnalysis<TargetData>();
-
- Function *F = R->getEntry()->getParent();
+ RI = &getAnalysis<RegionInfo>();
parallelLoops.clear();
+ Function *F = region->getEntry()->getParent();
if (CodegenOnly != "" && CodegenOnly != F->getNameStr()) {
errs() << "Codegenerating only function '" << CodegenOnly
<< "' skipping '" << F->getNameStr() << "' \n";
return false;
}
- assert(R->isSimple() && "Only simple regions supported");
-
- createSeSeEdges(R);
+ assert(region->isSimple() && "Only simple regions are supported");
- // Create a basic block in which to start code generation.
- BasicBlock *PollyBB = BasicBlock::Create(F->getContext(), "pollyBB", F);
- IRBuilder<> Builder(PollyBB);
- DT->addNewBlock(PollyBB, R->getEntry());
-
- const clast_root *clast = (const clast_root *) C->getClast();
+ // In the CFG and we generate next to original code of the Scop the
+ // optimized version. Both the new and the original version of the code
+ // remain in the CFG. A branch statement decides which version is executed.
+ // At the moment, we always execute the newly generated version (the old one
+ // is dead code eliminated by the cleanup passes). Later we may decide to
+ // execute the new version only under certain conditions. This will be the
+ // case if we support constructs for which we cannot prove all assumptions
+ // at compile time.
+ //
+ // Before transformation:
+ //
+ // bb0
+ // |
+ // orig_scop
+ // |
+ // bb1
+ //
+ // After transformation:
+ // bb0
+ // |
+ // polly.splitBlock
+ // / \
+ // | startBlock
+ // | |
+ // orig_scop new_scop
+ // \ /
+ // \ /
+ // bb1 (joinBlock)
+ IRBuilder<> builder(region->getEntry());
- ClastStmtCodeGen CodeGen(S, *SE, DT, SD, DP, TD, Builder);
+ // The builder will be set to startBlock.
+ BasicBlock *splitBlock = addSplitAndStartBlock(&builder);
if (OpenMP)
- addOpenMPDefinitions(Builder);
+ addOpenMPDefinitions(builder);
- CodeGen.codegen(clast);
+ ClastStmtCodeGen CodeGen(S, *SE, DT, SD, DP, TD, builder);
+ CodeGen.codegen((const clast_root *) C->getClast());
- // Save the parallel loops generated.
parallelLoops.insert(parallelLoops.begin(),
CodeGen.getParallelLoops().begin(),
CodeGen.getParallelLoops().end());
- BasicBlock *AfterScop = *pred_begin(R->getExit());
- Builder.CreateBr(AfterScop);
-
- BasicBlock *successorBlock = *succ_begin(R->getEntry());
-
- // Update old PHI nodes to pass LLVM verification.
- std::vector<PHINode*> PHINodes;
- for (BasicBlock::iterator SI = successorBlock->begin(),
- SE = successorBlock->getFirstNonPHI(); SI != SE; ++SI) {
- PHINode *PN = static_cast<PHINode*>(&*SI);
- PHINodes.push_back(PN);
- }
-
- for (std::vector<PHINode*>::iterator PI = PHINodes.begin(),
- PE = PHINodes.end(); PI != PE; ++PI)
- (*PI)->removeIncomingValue(R->getEntry());
-
- DT->changeImmediateDominator(AfterScop, Builder.GetInsertBlock());
-
- BasicBlock *OldRegionEntry = *succ_begin(R->getEntry());
-
- // Enable the new polly code.
- R->getEntry()->getTerminator()->setSuccessor(0, PollyBB);
-
- // Remove old Scop nodes from dominator tree.
- std::vector<DomTreeNode*> ToVisit;
- std::vector<DomTreeNode*> Visited;
- ToVisit.push_back(DT->getNode(OldRegionEntry));
-
- while (!ToVisit.empty()) {
- DomTreeNode *Node = ToVisit.back();
-
- ToVisit.pop_back();
-
- if (AfterScop == Node->getBlock())
- continue;
-
- Visited.push_back(Node);
-
- std::vector<DomTreeNode*> Children = Node->getChildren();
- ToVisit.insert(ToVisit.end(), Children.begin(), Children.end());
- }
-
- for (std::vector<DomTreeNode*>::reverse_iterator I = Visited.rbegin(),
- E = Visited.rend(); I != E; ++I)
- DT->eraseNode((*I)->getBlock());
-
- R->getParent()->removeSubRegion(R);
+ mergeControlFlow(splitBlock, &builder);
- // And forget the Scop if we remove the region.
- SD->forgetScop(*R);
+ // Forget the Scop.
+ SD->forgetScop(*region);
return false;
}
Modified: polly/trunk/lib/Support/ScopHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/ScopHelper.cpp?rev=131352&r1=131351&r2=131352&view=diff
==============================================================================
--- polly/trunk/lib/Support/ScopHelper.cpp (original)
+++ polly/trunk/lib/Support/ScopHelper.cpp Sat May 14 14:01:49 2011
@@ -223,39 +223,6 @@
return false;
}
-// Helper function for LLVM-IR about Scop
-BasicBlock *polly::createSingleEntryEdge(Region *R, Pass *P) {
- BasicBlock *BB = R->getEntry();
-
- BasicBlock::iterator SplitIt = BB->begin();
-
- while (isa<PHINode>(SplitIt))
- ++SplitIt;
-
- BasicBlock *newBB = SplitBlock(BB, SplitIt, P);
-
- for (BasicBlock::iterator PI = BB->begin(); isa<PHINode>(PI); ++PI) {
- PHINode *PN = cast<PHINode>(PI);
- PHINode *NPN =
- PHINode::Create(PN->getType(), 2, PN->getName()+".ph", newBB->begin());
-
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) {
- if (R->contains(*PI)) {
- Value *V = PN->removeIncomingValue(*PI, false);
- NPN->addIncoming(V, *PI);
- }
- }
- PN->replaceAllUsesWith(NPN);
- NPN->addIncoming(PN,BB);
- }
-
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI)
- if (R->contains(*PI))
- (*PI)->getTerminator()->replaceUsesOfWith(BB, newBB);
-
- return newBB;
-}
-
BasicBlock *polly::createSingleExitEdge(Region *R, Pass *P) {
BasicBlock *BB = R->getExit();
Added: polly/trunk/test/CodeGen/split_edges.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/CodeGen/split_edges.ll?rev=131352&view=auto
==============================================================================
--- polly/trunk/test/CodeGen/split_edges.ll (added)
+++ polly/trunk/test/CodeGen/split_edges.ll Sat May 14 14:01:49 2011
@@ -0,0 +1,39 @@
+; RUN: opt %loadPolly -polly-codegen -verify-region-info -verify-dom-info -S %s | FileCheck %s
+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-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+define void @loop_with_condition() nounwind {
+bb0:
+ call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ br label %bb1
+
+bb1:
+ br i1 true, label %bb2, label %bb3
+
+bb2:
+ %ind1 = phi i32 [0, %bb1], [ %inc1, %bb2]
+ %inc1 = add i32 %ind1, 1
+ %cond1 = icmp eq i32 %ind1, 32
+ br i1 %cond1, label %bb4, label %bb2
+
+bb3:
+ %ind2 = phi i32 [0, %bb1], [ %inc2, %bb3]
+ %inc2 = add i32 %ind2, 1
+ br i1 true, label %bb4, label %bb3
+
+bb4:
+ br label %bb5
+
+bb5:
+ call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ ret void
+
+}
+
+declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
+
+
+; CHECK: polly.enterScop
+; CHECK: polly.finalMerge
+; CHECK: polly.enterScop
+; CHECK: polly.finalMerge
Added: polly/trunk/test/CodeGen/split_edges_2.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/CodeGen/split_edges_2.ll?rev=131352&view=auto
==============================================================================
--- polly/trunk/test/CodeGen/split_edges_2.ll (added)
+++ polly/trunk/test/CodeGen/split_edges_2.ll Sat May 14 14:01:49 2011
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-codegen -verify-region-info -verify-dom-info -S %s | FileCheck %s
+
+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-n8:16:32:64"
+target triple = "x86_64-pc-linux-gnu"
+
+define void @loop_with_condition() nounwind {
+bb0:
+ call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ br label %bb1
+
+bb1:
+ br label %bb2
+
+bb2:
+ %ind1 = phi i32 [0, %bb1], [ %inc1, %bb2]
+ %inc1 = add i32 %ind1, 1
+ %cond1 = icmp eq i32 %ind1, 32
+ br i1 %cond1, label %bb4, label %bb2
+
+bb4:
+ br label %bb5
+
+bb5:
+ call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ ret void
+
+}
+
+declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
+
+; CHECK: polly.enterScop
+; CHECK-NOT: polly.finalMerge
+
+
+
More information about the llvm-commits
mailing list