[llvm-commits] [polly] r153325 - in /polly/trunk: include/polly/LoopGenerators.h lib/CMakeLists.txt lib/CodeGeneration.cpp lib/LoopGenerators.cpp
Tobias Grosser
grosser at fim.uni-passau.de
Fri Mar 23 03:35:19 PDT 2012
Author: grosser
Date: Fri Mar 23 05:35:18 2012
New Revision: 153325
URL: http://llvm.org/viewvc/llvm-project?rev=153325&view=rev
Log:
CodeGen: Extract the LLVM-IR generaction of scalar and OpenMP loops.
We create a new file LoopGenerators that provides utility classes for the
generation of OpenMP parallel and scalar loops. This means we move a lot
of the OpenMP generation out of the Polly specific code generator.
Added:
polly/trunk/include/polly/LoopGenerators.h
polly/trunk/lib/LoopGenerators.cpp
Modified:
polly/trunk/lib/CMakeLists.txt
polly/trunk/lib/CodeGeneration.cpp
Added: polly/trunk/include/polly/LoopGenerators.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/LoopGenerators.h?rev=153325&view=auto
==============================================================================
--- polly/trunk/include/polly/LoopGenerators.h (added)
+++ polly/trunk/include/polly/LoopGenerators.h Fri Mar 23 05:35:18 2012
@@ -0,0 +1,108 @@
+//===- LoopGenerators.h - IR helper to create loops -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions to create scalar and OpenMP parallel loops
+// as LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Support/IRBuilder.h"
+#include "llvm/ADT/SetVector.h"
+
+#include <map>
+
+namespace llvm {
+ class Value;
+ class Pass;
+ class BasicBlock;
+}
+
+using namespace llvm;
+
+/// @brief Create a scalar loop.
+///
+/// @param LowerBound The starting value of the induction variable.
+/// @param UpperBound The upper bound of the induction variable.
+/// @param Stride The value by which the induction variable is incremented.
+///
+/// @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.
+Value *createLoop(Value *LowerBound, Value *UpperBound, Value *Stride,
+ IRBuilder<> *Builder, Pass *P, BasicBlock **AfterBlock);
+
+class OMPGenerator {
+public:
+ typedef std::map<Value*, Value*> ValueToValueMapTy;
+
+ OMPGenerator(IRBuilder<> &Builder, Pass *P): Builder(Builder), P(P) {}
+
+ /// @brief Create an OpenMP parallel loop.
+ ///
+ ///
+ /// @param LowerBound The starting value of the induction variable.
+ /// @param UpperBound The upper bound of the induction variable.
+ /// @param Stride The value by which the induction variable is
+ /// incremented.
+ ///
+ /// @param UsedValues A set of LLVM-IR Values that should be available to
+ /// the new loop body.
+ /// @param VMap This map is filled by createParallelLoop(). It
+ /// maps the values in UsedValues to Values through which
+ /// their content is available within the loop body.
+ /// @param LoopBody A pointer to an iterator that is set to point to the
+ /// body of the created loop. It should be used to insert
+ /// instructions that form the actual loop body.
+ ///
+ /// @return Value* The newly created induction variable for this loop.
+ Value *createParallelLoop(Value *LowerBound, Value *UpperBound, Value *Stride,
+ SetVector<Value*> &UsedValues,
+ ValueToValueMapTy &VMap,
+ BasicBlock::iterator *LoopBody);
+
+private:
+ IRBuilder<> &Builder;
+ Pass *P;
+
+ IntegerType *getIntPtrTy();
+ Module *getModule();
+
+ void createCallParallelLoopStart(Value *SubFunction, Value *SubfunctionParam,
+ Value *NumberOfThreads, Value *LowerBound,
+ Value *UpperBound, Value *Stride);
+ Value *createCallLoopNext(Value *LowerBoundPtr, Value *UpperBoundPtr);
+ void createCallParallelEnd();
+ void createCallLoopEndNowait();
+
+ Value *loadValuesIntoStruct(SetVector<Value*> &Values);
+ void extractValuesFromStruct(SetVector<Value*> OldValues,
+ Value *Struct, ValueToValueMapTy &Map);
+
+ /// @brief Create the OpenMP subfunction.
+ ///
+ /// @param Stride The value by which the induction variable is
+ /// incremented.
+ /// @param Struct The structure that is used to make Values available to
+ /// the loop body.
+ /// @param UsedValues A set of LLVM-IR Values that should be available to
+ /// the new loop body.
+ /// @param VMap This map that is filled by createSubfunction(). It
+ /// maps the values in UsedValues to Values through which
+ /// their content is available within the loop body.
+ /// @param SubFunction The newly created SubFunction is returned here.
+ ///
+ /// @return Value* The newly created induction variable.
+ Value *createSubfunction(Value *Stride, Value *Struct,
+ SetVector<Value*> UsedValues,
+ ValueToValueMapTy &VMap,
+ Function **SubFunction);
+
+ /// @brief Create the definition of the OpenMP subfunction.
+ Function *createSubfunctionDefinition();
+};
+
Modified: polly/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CMakeLists.txt?rev=153325&r1=153324&r2=153325&view=diff
==============================================================================
--- polly/trunk/lib/CMakeLists.txt (original)
+++ polly/trunk/lib/CMakeLists.txt Fri Mar 23 05:35:18 2012
@@ -25,6 +25,7 @@
IndependentBlocks.cpp
IndVarSimplify.cpp
MayAliasSet.cpp
+ LoopGenerators.cpp
Pocc.cpp
RegionSimplify.cpp
RegisterPasses.cpp
Modified: polly/trunk/lib/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGeneration.cpp?rev=153325&r1=153324&r2=153325&view=diff
==============================================================================
--- polly/trunk/lib/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGeneration.cpp Fri Mar 23 05:35:18 2012
@@ -29,6 +29,7 @@
#include "polly/ScopInfo.h"
#include "polly/TempScopInfo.h"
#include "polly/Support/GICHelper.h"
+#include "polly/LoopGenerators.h"
#include "llvm/Module.h"
#include "llvm/ADT/SetVector.h"
@@ -86,70 +87,6 @@
typedef DenseMap<const char*, Value*> CharMapT;
typedef std::vector<ValueMapT> VectorValueMapT;
-// Create a new loop.
-//
-// @param Builder The builder used to create the loop. It also defines the
-// place where to create the loop.
-// @param UB The upper bound of the loop iv.
-// @param Stride The number by which the loop iv is incremented after every
-// iteration.
-static Value *createLoop(IRBuilder<> *Builder, Value *LB, Value *UB,
- APInt Stride, Pass *P, BasicBlock **AfterBlock) {
- 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.");
-
- 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);
-
- // IV increment.
- Value *StrideValue = ConstantInt::get(LoopIVType,
- Stride.zext(LoopIVType->getBitWidth()));
- Value *IncrementedIV = Builder->CreateAdd(IV, StrideValue,
- "polly.next_loopiv");
-
- // Exit condition.
- Value *CMP;
- if (AtLeastOnce) { // At least on iteration.
- UB = Builder->CreateAdd(UB, Builder->getInt64(1));
- CMP = Builder->CreateICmpNE(IV, UB);
- } else { // Maybe not executed at all.
- CMP = Builder->CreateICmpSLE(IV, UB);
- }
-
- Builder->CreateCondBr(CMP, BodyBB, AfterBB);
- DT.addNewBlock(BodyBB, HeaderBB);
-
- Builder->SetInsertPoint(BodyBB);
- Builder->CreateBr(HeaderBB);
- IV->addIncoming(IncrementedIV, BodyBB);
- DT.changeImmediateDominator(AfterBB, HeaderBB);
-
- Builder->SetInsertPoint(BodyBB->begin());
- *AfterBlock = AfterBB;
-
- return IV;
-}
-
class IslGenerator;
class IslGenerator {
@@ -1036,6 +973,10 @@
}
class ClastStmtCodeGen {
+public:
+ const std::vector<std::string> &getParallelLoops();
+
+private:
// The Scop we code generate.
Scop *S;
Pass *P;
@@ -1066,11 +1007,6 @@
std::vector<std::string> parallelLoops;
-public:
-
- const std::vector<std::string> &getParallelLoops();
-
- protected:
void codegen(const clast_assignment *a);
void codegen(const clast_assignment *a, ScopStmt *Statement,
@@ -1087,36 +1023,16 @@
void codegen(const clast_block *b);
/// @brief Create a classical sequential loop.
- void codegenForSequential(const clast_for *f, Value *LowerBound = 0,
- Value *UpperBound = 0);
-
- /// @brief Add a new definition of an openmp subfunction.
- Function *addOpenMPSubfunction(Module *M);
-
- /// @brief Add values to the OpenMP structure.
- ///
- /// Create the subfunction structure and add the values from the list.
- Value *addValuesToOpenMPStruct(SetVector<Value*> OMPDataVals,
- Function *SubFunction);
+ void codegenForSequential(const clast_for *f);
/// @brief Create OpenMP structure values.
///
- /// Create a list of values that has to be stored into the subfuncition
+ /// Create a list of values that has to be stored into the OpenMP subfuncition
/// structure.
- SetVector<Value*> createOpenMPStructValues();
+ SetVector<Value*> getOMPValues();
- /// @brief Extract the values from the subfunction parameter.
- ///
- /// Extract the values from the subfunction parameter and update the clast
- /// variables to point to the new values.
- void extractValuesFromOpenMPStruct(CharMapT *clastVarsOMP,
- SetVector<Value*> OMPDataVals,
- Value *userContext);
-
- /// @brief Add body to the subfunction.
- void addOpenMPSubfunctionBody(Function *FN, const clast_for *f,
- Value *structData,
- SetVector<Value*> OMPDataVals);
+ void updateWithValueMap(OMPGenerator::ValueToValueMapTy &VMap,
+ CharMapT &ClastVarsNew);
/// @brief Create an OpenMP parallel for loop.
///
@@ -1232,24 +1148,16 @@
codegen(b->body);
}
-void ClastStmtCodeGen::codegenForSequential(const clast_for *f,
- Value *LowerBound,
- Value *UpperBound) {
+void ClastStmtCodeGen::codegenForSequential(const clast_for *f) {
+ Value *LowerBound, *UpperBound, *IV, *Stride;
BasicBlock *AfterBB;
Type *IntPtrTy = getIntPtrTy();
- APInt Stride = APInt_from_MPZ(f->stride);
-
- // The value of lowerbound and upperbound will be supplied, if this
- // function is called while generating OpenMP code. Otherwise get
- // the values.
- assert(!!LowerBound == !!UpperBound && "Either give both bounds or none");
- if (LowerBound == 0) {
- LowerBound = ExpGen.codegen(f->LB, IntPtrTy);
- UpperBound = ExpGen.codegen(f->UB, IntPtrTy);
- }
+ LowerBound = ExpGen.codegen(f->LB, IntPtrTy);
+ UpperBound = ExpGen.codegen(f->UB, IntPtrTy);
+ Stride = Builder.getInt(APInt_from_MPZ(f->stride));
- Value *IV = createLoop(&Builder, LowerBound, UpperBound, Stride, P, &AfterBB);
+ IV = createLoop(LowerBound, UpperBound, Stride, &Builder, P, &AfterBB);
// Add loop iv to symbols.
(*ClastVars)[f->iterator] = IV;
@@ -1262,193 +1170,87 @@
Builder.SetInsertPoint(AfterBB->begin());
}
-Function *ClastStmtCodeGen::addOpenMPSubfunction(Module *M) {
- Function *F = Builder.GetInsertBlock()->getParent();
- std::vector<Type*> Arguments(1, Builder.getInt8PtrTy());
- FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
- Function *FN = Function::Create(FT, Function::InternalLinkage,
- F->getName() + ".omp_subfn", M);
- // Do not run any polly pass on the new function.
- P->getAnalysis<ScopDetection>().markFunctionAsInvalid(FN);
-
- Function::arg_iterator AI = FN->arg_begin();
- AI->setName("omp.userContext");
-
- return FN;
-}
-
-Value *ClastStmtCodeGen::addValuesToOpenMPStruct(SetVector<Value*> OMPDataVals,
- Function *SubFunction) {
- std::vector<Type*> structMembers;
-
- // Create the structure.
- for (unsigned i = 0; i < OMPDataVals.size(); i++)
- structMembers.push_back(OMPDataVals[i]->getType());
+SetVector<Value*> ClastStmtCodeGen::getOMPValues() {
+ SetVector<Value*> Values;
- StructType *structTy = StructType::get(Builder.getContext(),
- structMembers);
- // Store the values into the structure.
- Value *structData = Builder.CreateAlloca(structTy, 0, "omp.userContext");
- for (unsigned i = 0; i < OMPDataVals.size(); i++) {
- Value *storeAddr = Builder.CreateStructGEP(structData, i);
- Builder.CreateStore(OMPDataVals[i], storeAddr);
- }
-
- return structData;
-}
-
-SetVector<Value*> ClastStmtCodeGen::createOpenMPStructValues() {
- SetVector<Value*> OMPDataVals;
-
- // Push the clast variables available in the clastVars.
+ // The clast variables
for (CharMapT::iterator I = ClastVars->begin(), E = ClastVars->end();
I != E; I++)
- OMPDataVals.insert(I->second);
+ Values.insert(I->second);
- // Push the base addresses of memory references.
+ // The memory reference base addresses
for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
ScopStmt *Stmt = *SI;
for (SmallVector<MemoryAccess*, 8>::iterator I = Stmt->memacc_begin(),
E = Stmt->memacc_end(); I != E; ++I) {
Value *BaseAddr = const_cast<Value*>((*I)->getBaseAddr());
- OMPDataVals.insert((BaseAddr));
+ Values.insert((BaseAddr));
}
}
- return OMPDataVals;
+ return Values;
}
-void ClastStmtCodeGen::extractValuesFromOpenMPStruct(CharMapT *clastVarsOMP,
- SetVector<Value*> OMPDataVals, Value *userContext) {
- // Extract the clast variables.
- unsigned i = 0;
+void ClastStmtCodeGen::updateWithValueMap(OMPGenerator::ValueToValueMapTy &VMap,
+ CharMapT &ClastVarsNew) {
+ std::set<Value*> Inserted;
+
for (CharMapT::iterator I = ClastVars->begin(), E = ClastVars->end();
I != E; I++) {
- Value *loadAddr = Builder.CreateStructGEP(userContext, i);
- (*clastVarsOMP)[I->first] = Builder.CreateLoad(loadAddr);
- i++;
+ ClastVarsNew[I->first] = VMap[I->second];
+ Inserted.insert(I->second);
}
- // Extract the base addresses of memory references.
- for (unsigned j = i; j < OMPDataVals.size(); j++) {
- Value *loadAddr = Builder.CreateStructGEP(userContext, j);
- Value *baseAddr = OMPDataVals[j];
- ValueMap[baseAddr] = Builder.CreateLoad(loadAddr);
+ for (std::map<Value*, Value*>::iterator I = VMap.begin(), E = VMap.end();
+ I != E; ++I) {
+ if (Inserted.count(I->first))
+ continue;
+
+ ValueMap[I->first] = I->second;
}
}
-void ClastStmtCodeGen::addOpenMPSubfunctionBody(Function *FN,
- const clast_for *f,
- Value *StructData,
- SetVector<Value*> OMPDataVals) {
- Type *IntPtrTy = getIntPtrTy();
- Module *M = Builder.GetInsertBlock()->getParent()->getParent();
- LLVMContext &Context = FN->getContext();
-
- // Store the previous basic block.
- BasicBlock::iterator PrevInsertPoint = Builder.GetInsertPoint();
- BasicBlock *PrevBB = Builder.GetInsertBlock();
-
- // Create basic blocks.
- BasicBlock *HeaderBB = BasicBlock::Create(Context, "omp.setup", FN);
- BasicBlock *ExitBB = BasicBlock::Create(Context, "omp.exit", FN);
- BasicBlock *CheckNextBB = BasicBlock::Create(Context, "omp.checkNext", FN);
- BasicBlock *LoadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds",
- FN);
-
- DominatorTree &DT = P->getAnalysis<DominatorTree>();
- DT.addNewBlock(HeaderBB, PrevBB);
- DT.addNewBlock(ExitBB, HeaderBB);
- DT.addNewBlock(CheckNextBB, HeaderBB);
- DT.addNewBlock(LoadIVBoundsBB, HeaderBB);
-
- // Fill up basic block HeaderBB.
- Builder.SetInsertPoint(HeaderBB);
- Value *LowerBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.lowerBoundPtr");
- Value *UpperBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.upperBoundPtr");
- Value *UserContext = Builder.CreateBitCast(FN->arg_begin(),
- StructData->getType(),
- "omp.userContext");
-
- CharMapT ClastVarsOMP;
- extractValuesFromOpenMPStruct(&ClastVarsOMP, OMPDataVals, UserContext);
-
- Builder.CreateBr(CheckNextBB);
-
- // Add code to check if another set of iterations will be executed.
- Builder.SetInsertPoint(CheckNextBB);
- Function *RuntimeNextFunction = M->getFunction("GOMP_loop_runtime_next");
- Value *Ret1 = Builder.CreateCall2(RuntimeNextFunction,
- LowerBoundPtr, UpperBoundPtr);
- Value *HasNextSchedule = Builder.CreateTrunc(Ret1, Builder.getInt1Ty(),
- "omp.hasNextScheduleBlock");
- Builder.CreateCondBr(HasNextSchedule, LoadIVBoundsBB, ExitBB);
-
- // Add code to to load the iv bounds for this set of iterations.
- Builder.SetInsertPoint(LoadIVBoundsBB);
- Value *LowerBound = Builder.CreateLoad(LowerBoundPtr, "omp.lowerBound");
- Value *UpperBound = Builder.CreateLoad(UpperBoundPtr, "omp.upperBound");
-
- // Subtract one as the upper bound provided by openmp is a < comparison
- // whereas the codegenForSequential function creates a <= comparison.
- UpperBound = Builder.CreateSub(UpperBound, ConstantInt::get(IntPtrTy, 1),
- "omp.upperBoundAdjusted");
+void ClastStmtCodeGen::codegenForOpenMP(const clast_for *For) {
+ Value *Stride, *LowerBound, *UpperBound, *IV;
+ BasicBlock::iterator LoopBody;
+ IntegerType *IntPtrTy = getIntPtrTy();
+ SetVector<Value*> Values;
+ OMPGenerator::ValueToValueMapTy VMap;
+ OMPGenerator OMPGen(Builder, P);
+
+
+ Stride = Builder.getInt(APInt_from_MPZ(For->stride));
+ Stride = Builder.CreateSExtOrBitCast(Stride, IntPtrTy);
+ LowerBound = ExpGen.codegen(For->LB, IntPtrTy);
+ UpperBound = ExpGen.codegen(For->UB, IntPtrTy);
+
+ Values = getOMPValues();
+
+ IV = OMPGen.createParallelLoop(LowerBound, UpperBound, Stride, Values, VMap,
+ &LoopBody);
+ BasicBlock::iterator AfterLoop = Builder.GetInsertPoint();
+ Builder.SetInsertPoint(LoopBody);
// Use clastVarsOMP during code generation of the OpenMP subfunction.
+ CharMapT ClastVarsOMP;
+ updateWithValueMap(VMap, ClastVarsOMP);
CharMapT *OldClastVars = ClastVars;
ClastVars = &ClastVarsOMP;
ExpGen.setIVS(&ClastVarsOMP);
- Builder.CreateBr(CheckNextBB);
- Builder.SetInsertPoint(--Builder.GetInsertPoint());
- codegenForSequential(f, LowerBound, UpperBound);
+ // Add loop iv to symbols.
+ (*ClastVars)[For->iterator] = IV;
+
+ if (For->body)
+ codegen(For->body);
+
+ // Loop is finished, so remove its iv from the live symbols.
+ ClastVars->erase(For->iterator);
// Restore the old clastVars.
ClastVars = OldClastVars;
ExpGen.setIVS(OldClastVars);
-
- // Add code to terminate this openmp subfunction.
- Builder.SetInsertPoint(ExitBB);
- Function *EndnowaitFunction = M->getFunction("GOMP_loop_end_nowait");
- Builder.CreateCall(EndnowaitFunction);
- Builder.CreateRetVoid();
-
- // Restore the previous insert point.
- Builder.SetInsertPoint(PrevInsertPoint);
-}
-
-void ClastStmtCodeGen::codegenForOpenMP(const clast_for *For) {
- Module *M = Builder.GetInsertBlock()->getParent()->getParent();
- IntegerType *IntPtrTy = getIntPtrTy();
-
- Function *SubFunction = addOpenMPSubfunction(M);
- SetVector<Value*> OMPDataVals = createOpenMPStructValues();
- Value *StructData = addValuesToOpenMPStruct(OMPDataVals, SubFunction);
-
- addOpenMPSubfunctionBody(SubFunction, For, StructData, OMPDataVals);
-
- // Create call for GOMP_parallel_loop_runtime_start.
- Value *SubfunctionParam = Builder.CreateBitCast(StructData,
- Builder.getInt8PtrTy(),
- "omp_data");
-
- Value *NumberOfThreads = Builder.getInt32(0);
- Value *LowerBound = ExpGen.codegen(For->LB, IntPtrTy);
- Value *UpperBound = ExpGen.codegen(For->UB, IntPtrTy);
-
- // Add one as the upper bound provided by openmp is a < comparison
- // whereas the codegenForSequential function creates a <= comparison.
- UpperBound = Builder.CreateAdd(UpperBound, ConstantInt::get(IntPtrTy, 1));
- APInt APStride = APInt_from_MPZ(For->stride);
- Value *Stride = ConstantInt::get(IntPtrTy,
- APStride.zext(IntPtrTy->getBitWidth()));
-
- Value *Arguments[] = { SubFunction, SubfunctionParam, NumberOfThreads,
- LowerBound, UpperBound, Stride};
- Builder.CreateCall(M->getFunction("GOMP_parallel_loop_runtime_start"),
- Arguments);
- Builder.CreateCall(SubFunction, SubfunctionParam);
- Builder.CreateCall(M->getFunction("GOMP_parallel_end"));
+ Builder.SetInsertPoint(AfterLoop);
}
bool ClastStmtCodeGen::isInnermostLoop(const clast_for *f) {
@@ -1679,53 +1481,6 @@
CodeGeneration() : ScopPass(ID) {}
- // Add the declarations needed by the OpenMP function calls that we insert in
- // OpenMP mode.
- void addOpenMPDeclarations(Module *M)
- {
- IRBuilder<> Builder(M->getContext());
- Type *LongTy = getAnalysis<TargetData>().getIntPtrType(M->getContext());
-
- llvm::GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
-
- if (!M->getFunction("GOMP_parallel_end")) {
- FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
- Function::Create(Ty, Linkage, "GOMP_parallel_end", M);
- }
-
- if (!M->getFunction("GOMP_parallel_loop_runtime_start")) {
- Type *Params[] = {
- PointerType::getUnqual(FunctionType::get(Builder.getVoidTy(),
- Builder.getInt8PtrTy(),
- false)),
- Builder.getInt8PtrTy(),
- Builder.getInt32Ty(),
- LongTy,
- LongTy,
- LongTy,
- };
-
- FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
- Function::Create(Ty, Linkage, "GOMP_parallel_loop_runtime_start", M);
- }
-
- if (!M->getFunction("GOMP_loop_runtime_next")) {
- PointerType *LongPtrTy = PointerType::getUnqual(LongTy);
- Type *Params[] = {
- LongPtrTy,
- LongPtrTy,
- };
-
- FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false);
- Function::Create(Ty, Linkage, "GOMP_loop_runtime_next", M);
- }
-
- if (!M->getFunction("GOMP_loop_end_nowait")) {
- FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
- Function::Create(Ty, Linkage, "GOMP_loop_end_nowait", M);
- }
- }
-
// Split the entry edge of the region and generate a new basic block on this
// edge. This function also updates ScopInfo and RegionInfo.
//
@@ -1820,10 +1575,6 @@
assert(region->isSimple() && "Only simple regions are supported");
- Module *M = region->getEntry()->getParent()->getParent();
-
- if (OpenMP) addOpenMPDeclarations(M);
-
// In the CFG the optimized code of the SCoP is generated next to the
// original code. Both the new and the original version of the code remain
// in the CFG. A branch statement decides which version is executed.
Added: polly/trunk/lib/LoopGenerators.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/LoopGenerators.cpp?rev=153325&view=auto
==============================================================================
--- polly/trunk/lib/LoopGenerators.cpp (added)
+++ polly/trunk/lib/LoopGenerators.cpp Fri Mar 23 05:35:18 2012
@@ -0,0 +1,335 @@
+//===------ LoopGenerators.cpp - IR helper to create loops ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions to create scalar and OpenMP parallel loops
+// as LLVM-IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "polly/LoopGenerators.h"
+#include "polly/ScopDetection.h"
+
+#include "llvm/Module.h"
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+
+using namespace llvm;
+
+Value *createLoop(Value *LB, Value *UB, Value *Stride,
+ IRBuilder<> *Builder, Pass *P, BasicBlock **AfterBlock) {
+ 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.");
+
+ 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->CreateAdd(IV, Stride, "polly.next_loopiv");
+
+ // Exit condition.
+ Value *CMP;
+ CMP = Builder->CreateICmpSLE(IV, UB);
+
+ Builder->CreateCondBr(CMP, BodyBB, AfterBB);
+ DT.addNewBlock(BodyBB, HeaderBB);
+
+ Builder->SetInsertPoint(BodyBB);
+ Builder->CreateBr(HeaderBB);
+ IV->addIncoming(IncrementedIV, BodyBB);
+ DT.changeImmediateDominator(AfterBB, HeaderBB);
+
+ Builder->SetInsertPoint(BodyBB->begin());
+ *AfterBlock = AfterBB;
+
+ return IV;
+}
+
+void OMPGenerator::createCallParallelLoopStart(Value *SubFunction,
+ Value *SubfunctionParam,
+ Value *NumberOfThreads,
+ Value *LowerBound,
+ Value *UpperBound,
+ Value *Stride) {
+ Module *M = getModule();
+ const char *Name = "GOMP_parallel_loop_runtime_start";
+ Function *F = M->getFunction(Name);
+
+ // If F is not available, declare it.
+ if (!F) {
+ Type *LongTy = getIntPtrTy();
+ GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+
+ Type *Params[] = {
+ PointerType::getUnqual(FunctionType::get(Builder.getVoidTy(),
+ Builder.getInt8PtrTy(),
+ false)),
+ Builder.getInt8PtrTy(),
+ Builder.getInt32Ty(),
+ LongTy,
+ LongTy,
+ LongTy,
+ };
+
+ FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
+ F = Function::Create(Ty, Linkage, Name, M);
+ }
+
+ Value *Args[] = {
+ SubFunction,
+ SubfunctionParam,
+ NumberOfThreads,
+ LowerBound,
+ UpperBound,
+ Stride,
+ };
+
+ Builder.CreateCall(F, Args);
+}
+
+Value *OMPGenerator::createCallLoopNext(Value *LowerBoundPtr,
+ Value *UpperBoundPtr) {
+ Module *M = getModule();
+ const char *Name = "GOMP_loop_runtime_next";
+ Function *F = M->getFunction(Name);
+
+ // If F is not available, declare it.
+ if (!F) {
+ Type *LongPtrTy = PointerType::getUnqual(getIntPtrTy());
+ GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+
+ Type *Params[] = {
+ LongPtrTy,
+ LongPtrTy,
+ };
+
+ FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false);
+ F = Function::Create(Ty, Linkage, Name, M);
+ }
+
+ Value *Args[] = {
+ LowerBoundPtr,
+ UpperBoundPtr,
+ };
+
+ Value *Return = Builder.CreateCall(F, Args);
+ Return = Builder.CreateICmpNE(Return, Builder.CreateZExt(Builder.getFalse(),
+ Return->getType()));
+ return Return;
+}
+
+void OMPGenerator::createCallParallelEnd() {
+ const char *Name = "GOMP_parallel_end";
+ Module *M = getModule();
+ Function *F = M->getFunction(Name);
+
+ // If F is not available, declare it.
+ if (!F) {
+ GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+
+ FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
+ F = Function::Create(Ty, Linkage, Name, M);
+ }
+
+ Builder.CreateCall(F);
+}
+
+void OMPGenerator::createCallLoopEndNowait() {
+ const char *Name = "GOMP_loop_end_nowait";
+ Module *M = getModule();
+ Function *F = M->getFunction(Name);
+
+ // If F is not available, declare it.
+ if (!F) {
+ GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
+
+ FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
+ F = Function::Create(Ty, Linkage, Name, M);
+ }
+
+ Builder.CreateCall(F);
+}
+
+IntegerType *OMPGenerator::getIntPtrTy() {
+ return P->getAnalysis<TargetData>().getIntPtrType(Builder.getContext());
+}
+
+Module *OMPGenerator::getModule() {
+ return Builder.GetInsertBlock()->getParent()->getParent();
+}
+
+Function *OMPGenerator::createSubfunctionDefinition() {
+ Module *M = getModule();
+ Function *F = Builder.GetInsertBlock()->getParent();
+ std::vector<Type*> Arguments(1, Builder.getInt8PtrTy());
+ FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
+ Function *FN = Function::Create(FT, Function::InternalLinkage,
+ F->getName() + ".omp_subfn", M);
+ // Do not run any polly pass on the new function.
+ P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN);
+
+ Function::arg_iterator AI = FN->arg_begin();
+ AI->setName("omp.userContext");
+
+ return FN;
+}
+
+Value *OMPGenerator::loadValuesIntoStruct(SetVector<Value*> &Values) {
+ std::vector<Type*> Members;
+
+ for (unsigned i = 0; i < Values.size(); i++)
+ Members.push_back(Values[i]->getType());
+
+ StructType *Ty = StructType::get(Builder.getContext(), Members);
+ Value *Struct = Builder.CreateAlloca(Ty, 0, "omp.userContext");
+
+ for (unsigned i = 0; i < Values.size(); i++) {
+ Value *Address = Builder.CreateStructGEP(Struct, i);
+ Builder.CreateStore(Values[i], Address);
+ }
+
+ return Struct;
+}
+
+void OMPGenerator::extractValuesFromStruct(SetVector<Value*> OldValues,
+ Value *Struct,
+ ValueToValueMapTy &Map) {
+ for (unsigned i = 0; i < OldValues.size(); i++) {
+ Value *Address = Builder.CreateStructGEP(Struct, i);
+ Value *NewValue = Builder.CreateLoad(Address);
+ Map.insert(std::make_pair<Value*, Value*>(OldValues[i], NewValue));
+ }
+}
+
+Value *OMPGenerator::createSubfunction(Value *Stride, Value *StructData,
+ SetVector<Value*> Data,
+ ValueToValueMapTy &Map,
+ Function **SubFunction) {
+ Function *FN = createSubfunctionDefinition();
+
+ BasicBlock *PrevBB, *HeaderBB, *ExitBB, *CheckNextBB, *LoadIVBoundsBB,
+ *AfterBB;
+ Value *LowerBoundPtr, *UpperBoundPtr, *UserContext, *Ret1, *HasNextSchedule,
+ *LowerBound, *UpperBound, *IV;
+ Type *IntPtrTy = getIntPtrTy();
+ LLVMContext &Context = FN->getContext();
+
+ // Store the previous basic block.
+ PrevBB = Builder.GetInsertBlock();
+
+ // Create basic blocks.
+ HeaderBB = BasicBlock::Create(Context, "omp.setup", FN);
+ ExitBB = BasicBlock::Create(Context, "omp.exit", FN);
+ CheckNextBB = BasicBlock::Create(Context, "omp.checkNext", FN);
+ LoadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds", FN);
+
+ DominatorTree &DT = P->getAnalysis<DominatorTree>();
+ DT.addNewBlock(HeaderBB, PrevBB);
+ DT.addNewBlock(ExitBB, HeaderBB);
+ DT.addNewBlock(CheckNextBB, HeaderBB);
+ DT.addNewBlock(LoadIVBoundsBB, HeaderBB);
+
+ // Fill up basic block HeaderBB.
+ Builder.SetInsertPoint(HeaderBB);
+ LowerBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.lowerBoundPtr");
+ UpperBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.upperBoundPtr");
+ UserContext = Builder.CreateBitCast(FN->arg_begin(), StructData->getType(),
+ "omp.userContext");
+
+ extractValuesFromStruct(Data, UserContext, Map);
+ Builder.CreateBr(CheckNextBB);
+
+ // Add code to check if another set of iterations will be executed.
+ Builder.SetInsertPoint(CheckNextBB);
+ Ret1 = createCallLoopNext(LowerBoundPtr, UpperBoundPtr);
+ HasNextSchedule = Builder.CreateTrunc(Ret1, Builder.getInt1Ty(),
+ "omp.hasNextScheduleBlock");
+ Builder.CreateCondBr(HasNextSchedule, LoadIVBoundsBB, ExitBB);
+
+ // Add code to to load the iv bounds for this set of iterations.
+ Builder.SetInsertPoint(LoadIVBoundsBB);
+ LowerBound = Builder.CreateLoad(LowerBoundPtr, "omp.lowerBound");
+ UpperBound = Builder.CreateLoad(UpperBoundPtr, "omp.upperBound");
+
+ // Subtract one as the upper bound provided by openmp is a < comparison
+ // whereas the codegenForSequential function creates a <= comparison.
+ UpperBound = Builder.CreateSub(UpperBound, ConstantInt::get(IntPtrTy, 1),
+ "omp.upperBoundAdjusted");
+
+ Builder.CreateBr(CheckNextBB);
+ Builder.SetInsertPoint(--Builder.GetInsertPoint());
+ IV = createLoop(LowerBound, UpperBound, Stride, &Builder, P, &AfterBB);
+
+ BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
+ Builder.SetInsertPoint(AfterBB->begin());
+
+ // Add code to terminate this openmp subfunction.
+ Builder.SetInsertPoint(ExitBB);
+ createCallLoopEndNowait();
+ Builder.CreateRetVoid();
+
+ Builder.SetInsertPoint(LoopBody);
+ *SubFunction = FN;
+
+ return IV;
+}
+
+Value *OMPGenerator::createParallelLoop(Value *LowerBound, Value *UpperBound,
+ Value *Stride,
+ SetVector<Value*> &Values,
+ ValueToValueMapTy &Map,
+ BasicBlock::iterator *LoopBody) {
+ Value *Struct, *IV, *SubfunctionParam, *NumberOfThreads;
+ Function *SubFunction;
+
+ Struct = loadValuesIntoStruct(Values);
+
+ BasicBlock::iterator PrevInsertPoint = Builder.GetInsertPoint();
+ IV = createSubfunction(Stride, Struct, Values, Map, &SubFunction);
+ *LoopBody = Builder.GetInsertPoint();
+ Builder.SetInsertPoint(PrevInsertPoint);
+
+ // Create call for GOMP_parallel_loop_runtime_start.
+ SubfunctionParam = Builder.CreateBitCast(Struct, Builder.getInt8PtrTy(),
+ "omp_data");
+
+ NumberOfThreads = Builder.getInt32(0);
+
+ // Add one as the upper bound provided by openmp is a < comparison
+ // whereas the codegenForSequential function creates a <= comparison.
+ UpperBound = Builder.CreateAdd(UpperBound,
+ ConstantInt::get(getIntPtrTy(), 1));
+
+ createCallParallelLoopStart(SubFunction, SubfunctionParam, NumberOfThreads,
+ LowerBound, UpperBound, Stride);
+ Builder.CreateCall(SubFunction, SubfunctionParam);
+ createCallParallelEnd();
+
+ return IV;
+}
More information about the llvm-commits
mailing list