28#include "llvm/ADT/APInt.h"
29#include "llvm/ADT/PostOrderIterator.h"
30#include "llvm/ADT/SetVector.h"
31#include "llvm/ADT/Statistic.h"
32#include "llvm/Analysis/AssumptionCache.h"
33#include "llvm/Analysis/LoopInfo.h"
34#include "llvm/Analysis/RegionInfo.h"
35#include "llvm/Analysis/ScalarEvolution.h"
36#include "llvm/Analysis/ScalarEvolutionExpressions.h"
37#include "llvm/Analysis/TargetLibraryInfo.h"
38#include "llvm/IR/BasicBlock.h"
39#include "llvm/IR/Constant.h"
40#include "llvm/IR/Constants.h"
41#include "llvm/IR/DataLayout.h"
42#include "llvm/IR/DerivedTypes.h"
43#include "llvm/IR/Dominators.h"
44#include "llvm/IR/Function.h"
45#include "llvm/IR/InstrTypes.h"
46#include "llvm/IR/Instruction.h"
47#include "llvm/IR/Instructions.h"
48#include "llvm/IR/Module.h"
49#include "llvm/IR/Type.h"
50#include "llvm/IR/Value.h"
51#include "llvm/Support/Casting.h"
52#include "llvm/Support/CommandLine.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/TargetParser/Triple.h"
55#include "llvm/Transforms/Utils/BasicBlockUtils.h"
80#define DEBUG_TYPE "polly-codegen"
82STATISTIC(VersionedScops,
"Number of SCoPs that required versioning.");
84STATISTIC(SequentialLoops,
"Number of generated sequential for-loops");
85STATISTIC(ParallelLoops,
"Number of generated parallel for-loops");
86STATISTIC(IfConditions,
"Number of generated if-conditions");
92 "polly-codegen-emit-rtc-print",
93 cl::desc(
"Emit code that prints the runtime check result dynamically."),
101 "polly-codegen-generate-expressions",
102 cl::desc(
"Generate AST expressions for unmodified and modified accesses"),
106 "polly-target-first-level-cache-line-size",
107 cl::desc(
"The size of the first level cache line size specified in bytes."),
111 "polly-omp-backend", cl::desc(
"Choose the OpenMP library to use:"),
117 ICmpInst::Predicate &Predicate) {
121 "conditional expression is not an atomic upper bound");
127 Predicate = ICmpInst::ICMP_SLE;
130 Predicate = ICmpInst::ICMP_SLT;
133 llvm_unreachable(
"Unexpected comparison type in loop condition");
139 "conditional expression is not an atomic upper bound");
144 "Could not get the iterator");
146 isl::id IteratorID = Iterator.get_id();
149 "conditional expression is not an atomic upper bound");
151 return Cond.get_op_arg(1);
182 CmpInst::Predicate Predicate;
188 if (NumberIterations < 0)
190 if (Predicate == CmpInst::ICMP_SLT)
191 return NumberIterations;
193 return NumberIterations + 1;
197 Loop *UserScope,
const ValueMapT &GlobalMap,
198 SetVector<Value *> &Values,
199 SetVector<const SCEV *> &SCEVs) {
205 if (isa<GlobalValue>(SrcVal))
206 Values.insert(SrcVal);
221 if (
Value *NewVal = GlobalMap.lookup(SrcVal))
222 Values.insert(NewVal);
226 Loop *UserScope,
const ValueMapT &GlobalMap,
227 SetVector<Value *> &Values,
228 SetVector<const SCEV *> &SCEVs) {
229 for (Use &U : Inst->operands())
235 SetVector<const SCEV *> &SCEVs) {
240 Loop *Scope = BB ? LI->getLoopFor(BB) :
nullptr;
245 for (BasicBlock *BB : Stmt->
getRegion()->blocks()) {
246 Loop *Scope = LI->getLoopFor(BB);
247 for (Instruction &Inst : *BB)
254 bool CreateScalarRefs) {
260 for (
auto &Access : *Stmt) {
261 if (References.ParamSpace) {
262 isl::space ParamSpace = Access->getLatestAccessRelation().get_space();
263 (*References.ParamSpace) =
264 References.ParamSpace->align_params(ParamSpace);
267 if (Access->isLatestArrayKind()) {
268 auto *BasePtr = Access->getLatestScopArrayInfo()->getBasePtr();
269 if (Instruction *OpInst = dyn_cast<Instruction>(BasePtr))
273 References.Values.insert(BasePtr);
277 if (CreateScalarRefs)
278 References.Values.insert(References.BlockGen.getOrCreateAlloca(*Access));
294 isl::id Id = Set.get_tuple_id();
295 auto *Stmt =
static_cast<ScopStmt *
>(Id.get_user());
325 SetVector<Value *> &Values,
326 SetVector<const Loop *> &Loops) {
327 SetVector<const SCEV *> SCEVs;
331 Values.insert_range(llvm::make_second_range(
IDToValue));
335 Values.insert(cast<SCEVUnknown>(I.second)->getValue());
340 for (
const SCEV *Expr : SCEVs) {
345 Values.remove_if([](
const Value *V) {
return isa<GlobalValue>(V); });
358 Loops.remove_if([
this](
const Loop *L) {
359 return S.contains(L) || L->contains(
S.getEntry());
368 SetVector<Value *> ReplacedValues;
369 for (
Value *V : Values) {
372 Values = ReplacedValues;
402 AncestorLoopAttr =
Annotator.getStagingAttrEnv();
404 Annotator.getStagingAttrEnv() = ChildLoopAttr;
411 "Nest must not overwrite loop attr environment");
412 Annotator.getStagingAttrEnv() = AncestorLoopAttr;
433 auto Id = BodyMark.
id();
434 if (strcmp(Id.get_name().c_str(),
"Loop Vectorizer Disabled") == 0)
455 auto *Stmt =
static_cast<ScopStmt *
>(StmtSet.get_tuple_id().get_user());
456 for (Instruction *Inst : Stmt->getInstructions()) {
457 if (Inst->getType()->isFloatingPointTy() ||
458 (Inst->getNumOperands() > 0 &&
459 Inst->getOperand(0)->getType()->isFloatingPointTy()))
472 if (V->getType() == Ty)
474 return Builder.CreateSExtOrTrunc(V, Ty);
481 if (V->getType()->getIntegerBitWidth() <= IntTy->getBitWidth())
483 if (
auto *CI = dyn_cast<ConstantInt>(V))
484 return CI->getValue().isSignedIntN(IntTy->getBitWidth());
490 Value *ValueLB, *ValueUB, *ValueInc;
492 BasicBlock *ExitBlock;
494 CmpInst::Predicate Predicate;
509 isl::id IteratorID = Iterator.get_id();
517 MaxType =
ExprBuilder.getWidestType(MaxType, ValueLB->getType());
518 MaxType =
ExprBuilder.getWidestType(MaxType, ValueUB->getType());
519 MaxType =
ExprBuilder.getWidestType(MaxType, ValueInc->getType());
528 IntegerType *IntPtrTy =
Builder.getIntPtrTy(
DL);
529 if (MaxType->getIntegerBitWidth() > IntPtrTy->getBitWidth() &&
541 bool UseGuardBB = !
GenSE->isKnownPredicate(Predicate,
GenSE->getSCEV(ValueLB),
542 GenSE->getSCEV(ValueUB));
557 ExitBlock, Predicate, &
Annotator, MarkParallel, UseGuardBB,
558 LoopVectorizerDisabled, SkipVectorizeEnableMetadata);
567 Builder.SetInsertPoint(ExitBlock, ExitBlock->begin());
576 Value *ValueLB, *ValueUB, *ValueInc;
579 CmpInst::Predicate Predicate;
586 ParBB->setName(
"polly.parallel.for");
587 Builder.SetInsertPoint(ParBB, ParBB->begin());
603 if (Predicate == CmpInst::ICMP_SLT)
605 ValueUB,
Builder.CreateSExt(
Builder.getTrue(), ValueUB->getType()));
608 MaxType =
ExprBuilder.getWidestType(MaxType, ValueLB->getType());
609 MaxType =
ExprBuilder.getWidestType(MaxType, ValueUB->getType());
610 MaxType =
ExprBuilder.getWidestType(MaxType, ValueInc->getType());
618 IntegerType *IntPtrTy =
Builder.getIntPtrTy(
DL);
619 if (MaxType->getIntegerBitWidth() > IntPtrTy->getBitWidth() &&
629 BasicBlock::iterator LoopBody;
631 SetVector<Value *> SubtreeValues;
632 SetVector<const Loop *> Loops;
640 for (
const Loop *L : Loops) {
642 SubtreeValues.insert(LoopInductionVar);
647 std::unique_ptr<ParallelLoopGenerator> ParallelLoopGenPtr;
658 IV = ParallelLoopGenPtr->createParallelLoop(
659 ValueLB, ValueUB, ValueInc, SubtreeValues, NewValues, &LoopBody);
660 BasicBlock::iterator AfterLoop =
Builder.GetInsertPoint();
663 Function *SubFn = LoopBody->getFunction();
669 Function *CallerFn =
Builder.GetInsertBlock()->getParent();
670 DominatorTree *CallerDT =
GenDT;
671 LoopInfo *CallerLI =
GenLI;
672 ScalarEvolution *CallerSE =
GenSE;
675 MapVector<const Loop *, const SCEV *> OutsideLoopIterationsCopy =
680 DominatorTree *SubDT = ParallelLoopGenPtr->getCalleeDominatorTree();
681 LoopInfo *SubLI = ParallelLoopGenPtr->getCalleeLoopInfo();
690 TargetLibraryInfoImpl BaselineInfoImpl(SubFn->getParent()->getTargetTriple());
691 TargetLibraryInfo CalleeTLI(BaselineInfoImpl, SubFn);
692 AssumptionCache CalleeAC(*SubFn);
693 std::unique_ptr<ScalarEvolution> SubSE = std::make_unique<ScalarEvolution>(
694 *SubFn, CalleeTLI, CalleeAC, *SubDT, *SubLI);
703 Builder.SetInsertPoint(LoopBody);
709 P.second = NewValues.lookup(P.second);
717 for (
auto &[NewVal, NewNewVal] : NewValues) {
718 if (Instruction *NewValInst = dyn_cast<Instruction>((
Value *)NewVal)) {
719 if (
S.contains(NewValInst))
721 assert(NewValInst->getFunction() == &
S.getFunction());
728 for (
auto &[OldVal, NewVal] :
IDToValue) {
729 NewVal = NewValues.lookup(NewVal);
740 if (
auto *U = dyn_cast<SCEVUnknown>(
S)) {
741 Value *NewVal = NewValues.lookup(U->getValue());
742 assert(NewVal &&
"must have a new value");
749 for (
auto &[OldVal, SubVal] :
ValueMap) {
750 Instruction *SubInst = dyn_cast<Instruction>((
Value *)SubVal);
751 assert(SubInst->getFunction() == SubFn &&
752 "Instructions from outside the subfn cannot be accessed within the "
756 Instruction *SubInst = dyn_cast<Instruction>((
Value *)SubVal);
757 assert(SubInst->getFunction() == SubFn &&
758 "Instructions from outside the subfn cannot be accessed within the "
764 for (
auto P : NewValues)
765 NewValuesReverse[P.second] = P.first;
767 Annotator.addAlternativeAliasBases(NewValuesReverse);
778 ValueMap = std::move(CallerGlobals);
780 ExprBuilder.switchGeneratedFunc(CallerFn, CallerDT, CallerLI, CallerSE);
781 RegionGen.switchGeneratedFunc(CallerFn, CallerDT, CallerLI, CallerSE);
782 BlockGen.switchGeneratedFunc(CallerFn, CallerDT, CallerLI, CallerSE);
783 Builder.SetInsertPoint(AfterLoop);
805 Function *F =
Builder.GetInsertBlock()->getParent();
806 LLVMContext &Context = F->getContext();
808 BasicBlock *CondBB = SplitBlock(
Builder.GetInsertBlock(),
810 CondBB->setName(
"polly.cond");
811 BasicBlock *MergeBB = SplitBlock(CondBB, CondBB->begin(),
GenDT,
GenLI);
812 MergeBB->setName(
"polly.merge");
813 BasicBlock *ThenBB = BasicBlock::Create(Context,
"polly.then", F);
814 BasicBlock *ElseBB = BasicBlock::Create(Context,
"polly.else", F);
816 GenDT->addNewBlock(ThenBB, CondBB);
817 GenDT->addNewBlock(ElseBB, CondBB);
818 GenDT->changeImmediateDominator(MergeBB, CondBB);
820 Loop *L =
GenLI->getLoopFor(CondBB);
822 L->addBasicBlockToLoop(ThenBB, *
GenLI);
823 L->addBasicBlockToLoop(ElseBB, *
GenLI);
826 CondBB->getTerminator()->eraseFromParent();
828 Builder.SetInsertPoint(CondBB);
830 Builder.CreateCondBr(Predicate, ThenBB, ElseBB);
831 Builder.SetInsertPoint(ThenBB);
833 Builder.SetInsertPoint(ElseBB);
835 Builder.SetInsertPoint(ThenBB, ThenBB->begin());
839 Builder.SetInsertPoint(ElseBB, ElseBB->begin());
844 Builder.SetInsertPoint(MergeBB, MergeBB->begin());
858 assert(!Build.
is_null() &&
"Could not obtain isl_ast_build from user node");
861 for (
auto *MA : *Stmt) {
862 if (!MA->hasNewAccessRelation()) {
866 if (MA->getLatestScopArrayInfo()->getBasePtrOriginSAI())
870 dyn_cast<Instruction>(MA->getLatestScopArrayInfo()->getBasePtr());
878 "Only affine memory accesses can be code generated");
894 auto *DefinedBehavior =
900 "Access relation not defined on full schedule domain");
902 "Access relation not defined on full domain");
917 NewAccesses = NewAccesses.
set(MA->getId(), AccessExpr);
926 "Expression of type 'op' expected");
928 "Operation of type 'call' expected");
944 std::vector<LoopToScevMapT> &VLTS, std::vector<Value *> &IVS,
949 for (
Value *IV : IVS) {
963 auto ReadAccess = Stmt->
begin();
964 auto WriteAccess = ReadAccess++;
965 assert((*ReadAccess)->isRead() && (*WriteAccess)->isMustWrite());
966 assert((*ReadAccess)->getElementType() == (*WriteAccess)->getElementType() &&
967 "Accesses use the same data type");
968 assert((*ReadAccess)->isArrayKind() && (*WriteAccess)->isArrayKind());
970 isl_id_to_ast_expr_get(NewAccesses, (*ReadAccess)->getId().release());
973 isl_id_to_ast_expr_get(NewAccesses, (*WriteAccess)->getId().release());
974 auto *StoreAddr =
ExprBuilder.createAccessAddress(AccessExpr).first;
975 Builder.CreateStore(LoadValue, StoreAddr);
980 "trying to materialize loop induction variable twice");
981 const SCEV *OuterLIV =
SE.getAddRecExpr(
SE.getUnknown(
Builder.getInt64(0)),
1010 BlockGen.copyStmt(*Stmt, LTS, NewAccesses);
1012 RegionGen.copyStmt(*Stmt, LTS, NewAccesses);
1015 isl_id_to_ast_expr_free(NewAccesses);
1023 for (
int i = 0; i < isl_ast_node_list_n_ast_node(List); ++i)
1024 create(isl_ast_node_list_get_ast_node(List, i));
1027 isl_ast_node_list_free(List);
1035 SmallVector<llvm::Value *, 8> Values;
1038 auto Params =
S.getParamSpace();
1057 llvm_unreachable(
"code generation error");
1075 llvm_unreachable(
"Unknown isl_ast_node type");
1088 SetVector<Value *> Values;
1090 for (
auto *Val : Values) {
1093 if (
auto *Inst = dyn_cast<Instruction>(Val)) {
1094 if (
S.contains(Inst)) {
1102 auto Address = MemInst ? MemInst.getPointerOperand() :
nullptr;
1103 if (Address &&
SE.getUnknown(UndefValue::get(Address->getType())) ==
1104 SE.getPointerBase(
SE.getSCEV(Address))) {
1105 }
else if (
S.getStmtFor(Inst)) {
1108 auto *
Domain =
S.getDomainConditions(Inst->getParent()).release();
1114 V = UndefValue::get(ParamSCEV->getType());
1120 if (
auto *IAClass =
S.lookupInvariantEquivClass(Val)) {
1124 if (IAClass->InvariantAccesses.empty())
1125 V = UndefValue::get(ParamSCEV->getType());
1154 for (
const SCEV *Param :
S.parameters()) {
1155 isl_id *Id =
S.getIdForParam(Param).release();
1164 Instruction *AccInst) {
1174 Type *Ty = AccInst->getType();
1176 auto *Ptr = AddressValue;
1177 auto Name = Ptr->getName();
1178 PreloadVal =
Builder.CreateLoad(Ty, Ptr, Name +
".load");
1179 if (LoadInst *PreloadInst = dyn_cast<LoadInst>(PreloadVal))
1180 PreloadInst->setAlignment(cast<LoadInst>(AccInst)->getAlign());
1195 bool AlwaysExecuted =
Domain.is_equal(Universe);
1198 Type *AccInstTy = AccInst->getType();
1211 "polly.preload.cond.overflown");
1212 Cond =
Builder.CreateAnd(Cond, OverflowHappened,
"polly.preload.cond.result");
1215 if (!Cond->getType()->isIntegerTy(1))
1216 Cond =
Builder.CreateIsNotNull(Cond);
1218 BasicBlock *CondBB = SplitBlock(
Builder.GetInsertBlock(),
1220 CondBB->setName(
"polly.preload.cond");
1222 BasicBlock *MergeBB = SplitBlock(CondBB, CondBB->begin(),
GenDT,
GenLI);
1223 MergeBB->setName(
"polly.preload.merge");
1225 Function *F =
Builder.GetInsertBlock()->getParent();
1226 LLVMContext &Context = F->getContext();
1227 BasicBlock *ExecBB = BasicBlock::Create(Context,
"polly.preload.exec", F);
1229 GenDT->addNewBlock(ExecBB, CondBB);
1230 if (Loop *L =
GenLI->getLoopFor(CondBB))
1231 L->addBasicBlockToLoop(ExecBB, *
GenLI);
1233 auto *CondBBTerminator = CondBB->getTerminator();
1234 Builder.SetInsertPoint(CondBB, CondBBTerminator->getIterator());
1235 Builder.CreateCondBr(Cond, ExecBB, MergeBB);
1236 CondBBTerminator->eraseFromParent();
1238 Builder.SetInsertPoint(ExecBB);
1241 Builder.SetInsertPoint(ExecBB, ExecBB->getTerminator()->getIterator());
1243 Builder.SetInsertPoint(MergeBB, MergeBB->getTerminator()->getIterator());
1244 auto *MergePHI =
Builder.CreatePHI(
1245 AccInstTy, 2,
"polly.preload." + AccInst->getName() +
".merge");
1246 Value *PreloadVal = MergePHI;
1249 PreloadVal =
nullptr;
1250 PreAccInst = UndefValue::get(AccInstTy);
1253 MergePHI->addIncoming(PreAccInst, ExecBB);
1254 MergePHI->addIncoming(Constant::getNullValue(AccInstTy), CondBB);
1290 if (
auto *BaseIAClass =
S.lookupInvariantEquivClass(SAI->getBasePtr())) {
1296 isl::set BaseExecutionCtx = BaseIAClass->ExecutionContext;
1297 ExecutionCtx = ExecutionCtx.
intersect(BaseExecutionCtx);
1302 for (
unsigned i = 1, e = SAI->getNumberOfDimensions(); i < e; ++i) {
1303 const SCEV *Dim = SAI->getDimensionSize(i);
1304 SetVector<Value *> Values;
1306 for (
auto *Val : Values) {
1307 if (
auto *BaseIAClass =
S.lookupInvariantEquivClass(Val)) {
1313 isl::set BaseExecutionCtx = BaseIAClass->ExecutionContext;
1314 ExecutionCtx = ExecutionCtx.
intersect(BaseExecutionCtx);
1320 Type *AccInstTy = AccInst->getType();
1328 assert(PreloadVal->getType() == MAAccInst->getType());
1332 if (
SE.isSCEVable(AccInstTy)) {
1333 isl_id *ParamId =
S.getIdForParam(
SE.getSCEV(AccInst)).release();
1339 BasicBlock *EntryBB = &
Builder.GetInsertBlock()->getParent()->getEntryBlock();
1340 auto *
Alloca =
new AllocaInst(AccInstTy,
DL.getAllocaAddrSpace(),
1341 AccInst->getName() +
".preload.s2a",
1342 EntryBB->getFirstInsertionPt());
1345 PreloadedPointer[PreloadVal] = AccInst;
1346 Annotator.addAlternativeAliasBases(PreloadedPointer);
1348 for (
auto *DerivedSAI : SAI->getDerivedSAIs()) {
1349 Value *BasePtr = DerivedSAI->getBasePtr();
1357 assert(BasePtr->getType() == PreloadVal->getType());
1358 DerivedSAI->setBasePtr(PreloadVal);
1371 for (
auto *U : MAAccInst->users())
1372 if (Instruction *UI = dyn_cast<Instruction>(U))
1373 if (!
S.contains(UI))
1374 EscapeUsers.push_back(UI);
1376 if (EscapeUsers.empty())
1380 std::make_pair(
Alloca, std::move(EscapeUsers));
1387 for (
auto &SAI :
S.arrays()) {
1388 if (SAI->getBasePtr())
1391 assert(SAI->getNumberOfDimensions() > 0 && SAI->getDimensionSize(0) &&
1392 "The size of the outermost dimension is used to declare newly "
1393 "created arrays that require memory allocation.");
1395 Type *NewArrayType =
nullptr;
1398 uint64_t ArraySizeInt = 1;
1399 for (
int i = SAI->getNumberOfDimensions() - 1; i >= 0; i--) {
1400 auto *DimSize = SAI->getDimensionSize(i);
1401 unsigned UnsignedDimSize =
static_cast<const SCEVConstant *
>(DimSize)
1406 NewArrayType = SAI->getElementType();
1408 NewArrayType = ArrayType::get(NewArrayType, UnsignedDimSize);
1409 ArraySizeInt *= UnsignedDimSize;
1412 if (SAI->isOnHeap()) {
1413 LLVMContext &
Ctx = NewArrayType->getContext();
1416 auto IntPtrTy =
DL.getIntPtrType(
Ctx);
1419 unsigned Size = SAI->getElemSizeInBytes();
1422 BasicBlock *
StartBlock = std::get<0>(StartExitBlocks);
1425 auto *CreatedArray =
Builder.CreateMalloc(
1426 IntPtrTy, SAI->getElementType(),
1427 ConstantInt::get(Type::getInt64Ty(
Ctx), Size),
1428 ConstantInt::get(Type::getInt64Ty(
Ctx), ArraySizeInt),
nullptr,
1431 SAI->setBasePtr(CreatedArray);
1434 BasicBlock *ExitingBlock = std::get<1>(StartExitBlocks);
1435 Builder.SetInsertPoint(ExitingBlock,
1436 ExitingBlock->getTerminator()->getIterator());
1437 Builder.CreateFree(CreatedArray);
1439 auto InstIt =
Builder.GetInsertBlock()
1445 auto *CreatedArray =
new AllocaInst(NewArrayType,
DL.getAllocaAddrSpace(),
1446 SAI->getName(), InstIt);
1449 SAI->setBasePtr(CreatedArray);
1455 auto &InvariantEquivClasses =
S.getInvariantAccesses();
1456 if (InvariantEquivClasses.empty())
1459 BasicBlock *PreLoadBB = SplitBlock(
Builder.GetInsertBlock(),
1461 PreLoadBB->setName(
"polly.preload.begin");
1462 Builder.SetInsertPoint(PreLoadBB, PreLoadBB->begin());
1464 for (
auto &IAClass : InvariantEquivClasses)
1481 Loop *L =
LI.getLoopFor(
S.getEntry());
1483 while (L !=
nullptr &&
S.contains(L))
1484 L = L->getParentLoop();
1486 while (L !=
nullptr) {
1488 L = L->getParentLoop();
1507 "Insert location points after last valid instruction");
1508 BasicBlock::iterator InsertLocation =
Builder.GetInsertPoint();
1511 "polly", Expr, Expr->getType(), InsertLocation,
1535 if (!RTC->getType()->isIntegerTy(1))
1536 RTC =
Builder.CreateIsNotNull(RTC);
1537 Value *OverflowHappened =
1541 auto *F =
Builder.GetInsertBlock()->getParent();
1544 "F: " + F->getName().str() +
" R: " +
S.getRegion().getNameStr() +
1546 RTC,
" Overflow: ", OverflowHappened,
1548 " (0 failed, -1 succeeded)\n"
1549 " (if one or both are 0 falling back to original code, if both are -1 "
1550 "executing Polly code)\n");
1553 RTC =
Builder.CreateAnd(RTC, OverflowHappened,
"polly.rtc.result");
1556 if (!isa<ConstantInt>(RTC))
cl::opt< bool > PollyVectorizeMetadata
static void findReferencesInInst(Instruction *Inst, ScopStmt *UserStmt, Loop *UserScope, const ValueMapT &GlobalMap, SetVector< Value * > &Values, SetVector< const SCEV * > &SCEVs)
static void findReferencesByUse(Value *SrcVal, ScopStmt *UserStmt, Loop *UserScope, const ValueMapT &GlobalMap, SetVector< Value * > &Values, SetVector< const SCEV * > &SCEVs)
static Value * castToType(IRBuilderBase &Builder, Value *V, Type *Ty)
Sign-extend or truncate V to Ty.
static void addReferencesFromStmtSet(isl::set Set, SubtreeReferences *UserPtr)
Extract the out-of-scop values and SCEVs referenced from a set describing a ScopStmt.
static cl::opt< bool > PollyGenerateRTCPrint("polly-codegen-emit-rtc-print", cl::desc("Emit code that prints the runtime check result dynamically."), cl::Hidden, cl::cat(PollyCategory))
static void addReferencesFromStmtUnionSet(isl::union_set USet, SubtreeReferences &References)
Extract the out-of-scop values and SCEVs referenced from a union set referencing multiple ScopStmts.
static cl::opt< bool > PollyGenerateExpressions("polly-codegen-generate-expressions", cl::desc("Generate AST expressions for unmodified and modified accesses"), cl::Hidden, cl::cat(PollyCategory))
static bool fitsInTy(Value *V, IntegerType *IntTy)
Returns true when V is known to fit in IntPtrTy without data loss.
STATISTIC(VersionedScops, "Number of SCoPs that required versioning.")
static bool hasLoopCarriedDependence(isl::ast_node_for For, const Scop &S)
Returns true if the loop has a dist=1 dependence involving FP operations (array-carried RAW/WAW or sc...
static bool IsLoopVectorizerDisabled(isl::ast_node_for Node)
Restore the initial ordering of dimensions of the band node.
static void findReferencesInStmt(ScopStmt *Stmt, SetVector< Value * > &Values, ValueMapT &GlobalMap, SetVector< const SCEV * > &SCEVs)
static cl::opt< OpenMPBackend > PollyOmpBackend("polly-omp-backend", cl::desc("Choose the OpenMP library to use:"), cl::values(clEnumValN(OpenMPBackend::GNU, "GNU", "GNU OpenMP"), clEnumValN(OpenMPBackend::LLVM, "LLVM", "LLVM OpenMP")), cl::Hidden, cl::init(OpenMPBackend::GNU), cl::cat(PollyCategory))
static cl::opt< int > PollyTargetFirstLevelCacheLineSize("polly-target-first-level-cache-line-size", cl::desc("The size of the first level cache line size specified in bytes."), cl::Hidden, cl::init(64), cl::cat(PollyCategory))
OpenMPBackend
OpenMP backend options.
llvm::cl::OptionCategory PollyCategory
isl_bool isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1, __isl_keep isl_pw_aff *pa2)
__isl_export __isl_give isl_set * isl_pw_aff_domain(__isl_take isl_pw_aff *pwaff)
__isl_export __isl_give isl_ast_expr * isl_ast_node_for_get_init(__isl_keep isl_ast_node *node)
__isl_export __isl_give isl_ast_node_list * isl_ast_node_block_get_children(__isl_keep isl_ast_node *node)
__isl_null isl_ast_expr * isl_ast_expr_free(__isl_take isl_ast_expr *expr)
isl_size isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
enum isl_ast_expr_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr)
__isl_give isl_ast_expr * isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr, int pos)
__isl_export __isl_give isl_ast_node * isl_ast_node_mark_get_node(__isl_keep isl_ast_node *node)
__isl_export __isl_give isl_ast_expr * isl_ast_node_for_get_inc(__isl_keep isl_ast_node *node)
__isl_give isl_ast_node * isl_ast_node_if_get_else(__isl_keep isl_ast_node *node)
__isl_export __isl_give isl_ast_node * isl_ast_node_for_get_body(__isl_keep isl_ast_node *node)
__isl_give isl_id * isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
__isl_export __isl_give isl_ast_expr * isl_ast_node_user_get_expr(__isl_keep isl_ast_node *node)
__isl_export __isl_give isl_ast_expr * isl_ast_node_if_get_cond(__isl_keep isl_ast_node *node)
__isl_export __isl_give isl_id * isl_ast_node_mark_get_id(__isl_keep isl_ast_node *node)
__isl_export __isl_give isl_ast_expr * isl_ast_node_for_get_iterator(__isl_keep isl_ast_node *node)
__isl_null isl_ast_node * isl_ast_node_free(__isl_take isl_ast_node *node)
__isl_give isl_ast_node * isl_ast_node_if_get_then(__isl_keep isl_ast_node *node)
isl_bool isl_ast_node_if_has_else(__isl_keep isl_ast_node *node)
__isl_give isl_ast_expr * isl_ast_expr_copy(__isl_keep isl_ast_expr *expr)
static isl::ast_build from_context(isl::set set)
isl::checked::ast_expr access_from(isl::checked::multi_pw_aff mpa) const
isl::checked::union_map get_schedule() const
isl::checked::ast_expr expr_from(isl::checked::pw_aff pa) const
__isl_give isl_ast_expr * release()
__isl_keep isl_ast_expr * get() const
isl::checked::ast_node_list children() const
isl::checked::ast_node body() const
isl::checked::ast_expr init() const
isl::checked::ast_expr cond() const
isl::checked::ast_expr inc() const
isl::checked::ast_expr iterator() const
isl::checked::id id() const
__isl_keep isl_ast_node * get() const
__isl_give isl_ast_node * release()
__isl_give isl_id_to_ast_expr * release()
isl::checked::id_to_ast_expr set(isl::checked::id key, isl::checked::ast_expr val) const
std::string get_name() const
__isl_keep isl_id * get() const
isl::checked::set range() const
__isl_keep isl_pw_aff * get() const
__isl_give isl_pw_aff * copy() const &
isl::checked::pw_multi_aff gist_params(isl::checked::set set) const
isl::checked::set domain() const
isl::checked::set intersect(isl::checked::set set2) const
__isl_give isl_set * release()
__isl_keep isl_set * get() const
isl::checked::union_set domain() const
__isl_give isl_union_set * release()
isl::checked::set_list get_set_list() const
static isl::id_to_ast_expr alloc(isl::ctx ctx, int min_size)
static isl::pw_multi_aff from_set(isl::set set)
static isl::set universe(isl::space space)
static isl::val one(isl::ctx ctx)
SmallVector< Instruction *, 4 > EscapeUserVectorTy
Simple vector of instructions to store escape users.
static bool isParallel(const isl::ast_node &Node)
Is this loop a parallel loop?
static isl::pw_aff getMinimalDependenceDistance(const isl::ast_node &Node)
Get minimal dependence distance or nullptr if not available.
static bool isExecutedInParallel(const isl::ast_node &Node)
Will the loop be run as thread parallel?
static isl::union_map getSchedule(const isl::ast_node &Node)
Get the nodes schedule or a nullptr if not available.
static isl::ast_build getBuild(const isl::ast_node &Node)
Get the nodes build context or a nullptr if not available.
static bool isReductionParallel(const isl::ast_node &Node)
Is this loop a reduction parallel loop?
llvm::MapVector< isl_id *, llvm::AssertingVH< llvm::Value > > IDToValueTy
A map from isl_ids to llvm::Values.
void addParameters(__isl_take isl_set *Context)
Value * getLatestValue(Value *Original) const
Return the most up-to-date version of the llvm::Value for code generation.
void create(__isl_take isl_ast_node *Node)
RegionGenerator RegionGen
The generator used to copy a non-affine region.
ScopAnnotator & Annotator
BlockGenerator::AllocaMapTy ScalarMap
Maps used by the block and region generator to demote scalars.
SmallVector< Function *, 8 > ParallelSubfunctions
A collection of all parallel subfunctions that have been created.
IslExprBuilder::IDToValueTy IDToValue
bool preloadInvariantEquivClass(InvariantEquivClassTy &IAClass)
Preload the invariant access equivalence class IAClass.
IslExprBuilder ExprBuilder
void createForSequential(isl::ast_node_for For, bool MarkParallel)
__isl_give isl_id_to_ast_expr * createNewAccesses(ScopStmt *Stmt, __isl_keep isl_ast_node *Node)
Create new access functions for modified memory accesses.
void createForParallel(__isl_take isl_ast_node *For)
Create LLVM-IR that executes a for node thread parallel.
Value * preloadUnconditionally(isl::set AccessRange, isl::ast_build Build, Instruction *AccInst)
Preload the memory access at AccessRange with Build.
bool preloadInvariantLoads()
Preload all memory loads that are invariant.
Value * generateSCEV(const SCEV *Expr)
Generate code for a given SCEV*.
bool materializeParameters()
Materialize all parameters in the current scop.
void generateBeginScopTrace()
ValueMapT ValueMap
A set of Value -> Value remappings to apply when generating new code.
Value * preloadInvariantLoad(const MemoryAccess &MA, isl::set Domain)
Preload the memory load access MA.
bool materializeValue(__isl_take isl_id *Id)
Materialize code for Id if it was not done before.
SmallSet< std::pair< const SCEV *, Type * >, 16 > PreloadedPtrs
Set to remember materialized invariant loads.
Value * materializeNonScopLoopInductionVariable(const Loop *L)
Materialize a canonical loop induction variable for L, which is a loop that is not present in the Sco...
virtual void createBlock(__isl_take isl_ast_node *Block)
virtual void createUser(__isl_take isl_ast_node *User)
void createSubstitutionsVector(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt, std::vector< LoopToScevMapT > &VLTS, std::vector< Value * > &IVS, __isl_take isl_id *IteratorID)
DominatorTree * GenDT
Relates to the region where the code is emitted into.
virtual void createFor(__isl_take isl_ast_node *For)
virtual void createMark(__isl_take isl_ast_node *Marker)
Generate code for a marker now.
void allocateNewArrays(BBPair StartExitBlocks)
Allocate memory for all new arrays created by Polly.
virtual isl::union_map getScheduleForAstNode(const isl::ast_node &Node)
Get the schedule for a given AST node.
void getReferencesInSubtree(const isl::ast_node &For, SetVector< Value * > &Values, SetVector< const Loop * > &Loops)
Compute the values and loops referenced in this subtree.
void generateCopyStmt(ScopStmt *Stmt, __isl_keep isl_id_to_ast_expr *NewAccesses)
Create code for a copy statement.
virtual void createIf(__isl_take isl_ast_node *If)
void createSubstitutions(__isl_take isl_ast_expr *Expr, ScopStmt *Stmt, LoopToScevMapT <S)
Generate LLVM-IR that computes the values of the original induction variables in function of the newl...
isl::ast_expr getUpperBound(isl::ast_node_for For, CmpInst::Predicate &Predicate)
BlockGenerator::EscapeUsersAllocaMapTy EscapeMap
See BlockGenerator::EscapeMap.
BlockGenerator BlockGen
The generator used to copy a basic block.
BlockGenerator & getBlockGenerator()
Get the associated block generator.
int getNumberOfIterations(isl::ast_node_for For)
Return non-negative number of iterations in case of the following form of a loop and -1 otherwise.
Value * createRTC(isl_ast_expr *Condition)
Generate code that evaluates Condition at run-time.
IslExprBuilder & getExprBuilder()
MapVector< const Loop *, const SCEV * > OutsideLoopIterations
The current iteration of out-of-scop loops.
static MemAccInst dyn_cast(llvm::Value &V)
Represent memory accesses in statements.
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
bool isRead() const
Is this a read memory access?
isl::map getAddressFunction() const
Get an isl map describing the memory address accessed.
const ScopArrayInfo * getScopArrayInfo() const
Legacy name of getOriginalScopArrayInfo().
Value * getOriginalBaseAddr() const
Get the original base address of this access (e.g.
bool isArrayKind() const
Old name of isOriginalArrayKind.
This ParallelLoopGenerator subclass handles the generation of parallelized code, utilizing the GNU Op...
This ParallelLoopGenerator subclass handles the generation of parallelized code, utilizing the LLVM O...
const std::vector< Instruction * > & getInstructions() const
bool isBlockStmt() const
Return true if this statement represents a single basic block.
Region * getRegion() const
Get the region represented by this ScopStmt (if any).
BasicBlock * getBasicBlock() const
Get the BasicBlock represented by this ScopStmt (if any).
bool isCopyStmt() const
Return true if this is a copy statement.
bool isRegionStmt() const
Return true if this statement represents a whole region.
Loop * getLoopForDimension(unsigned Dimension) const
Get the loop for a dimension.
isl::set getDomain() const
Get the iteration domain of this ScopStmt.
void setAstBuild(isl::ast_build B)
Set the isl AST build.
ScalarEvolution * getSE() const
Return the scalar evolution.
isl::set getBestKnownDefinedBehaviorContext() const
Return the define behavior context, or if not available, its approximation from all other contexts.
isl::ctx getIslCtx() const
Get the isl context of this static control part.
LoopInfo * getLI() const
Return the LoopInfo used for this Scop.
bool contains(const Loop *L) const
Check if L is contained in the SCoP.
const Region & getRegion() const
Get the maximum region of this static control part.
isl::set getContext() const
Get the constraint on parameter of this Scop.
Determine the nature of a value's use within a statement.
const SCEV * getScevExpr() const
Return the ScalarEvolution representation of Val.
static VirtualUse create(Scop *S, const Use &U, LoopInfo *LI, bool Virtual)
Get a VirtualUse for an llvm::Use.
UseKind getKind() const
Return the type of use.
__isl_export __isl_keep const char * isl_id_get_name(__isl_keep isl_id *id)
__isl_null isl_id * isl_id_free(__isl_take isl_id *id)
void * isl_id_get_user(__isl_keep isl_id *id)
enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node)
__isl_export __isl_give isl_set * isl_map_domain(__isl_take isl_map *bmap)
boolean manage(isl_bool val)
aff manage_copy(__isl_keep isl_aff *ptr)
std::forward_list< MemoryAccess * > MemoryAccessList
Ordered list type to hold accesses.
void findValues(const llvm::SCEV *Expr, llvm::ScalarEvolution &SE, llvm::SetVector< llvm::Value * > &Values)
Find the values referenced by SCEVUnknowns in a given SCEV expression.
void findLoops(const llvm::SCEV *Expr, llvm::SetVector< const llvm::Loop * > &Loops)
Find the loops referenced from a SCEV expression.
llvm::Value * expandCodeFor(Scop &S, llvm::ScalarEvolution &SE, llvm::Function *GenFn, llvm::ScalarEvolution &GenSE, const llvm::DataLayout &DL, const char *Name, const llvm::SCEV *E, llvm::Type *Ty, llvm::BasicBlock::iterator IP, ValueMapT *VMap, LoopToScevMapT *LoopMap, llvm::BasicBlock *RTCBB)
Wrapper for SCEVExpander extended to all Polly features.
@ Value
MemoryKind::Value: Models an llvm::Value.
void addReferencesFromStmt(ScopStmt *Stmt, void *UserPtr, bool CreateScalarRefs=true)
Extract the out-of-scop values and SCEVs referenced from a ScopStmt.
BandAttr * getLoopAttr(const isl::id &Id)
Return the BandAttr of a loop's isl::id.
Value * createLoop(Value *LowerBound, Value *UpperBound, Value *Stride, PollyIRBuilder &Builder, LoopInfo &LI, DominatorTree &DT, BasicBlock *&ExitBlock, ICmpInst::Predicate Predicate, ScopAnnotator *Annotator=nullptr, bool Parallel=false, bool UseGuard=true, bool LoopVectDisabled=false, bool SkipVectorizeEnableMetadata=false)
Create a scalar do/for-style loop.
llvm::iota_range< unsigned > rangeIslSize(unsigned Begin, isl::size End)
Check that End is valid and return an iterator from Begin to End.
llvm::DenseMap< const llvm::Loop *, llvm::SCEVUse > LoopToScevMapT
Same as llvm/Analysis/ScalarEvolutionExpressions.h.
llvm::DenseMap< llvm::AssertingVH< llvm::Value >, llvm::AssertingVH< llvm::Value > > ValueMapT
Type to remap values.
std::pair< llvm::BasicBlock *, llvm::BasicBlock * > BBPair
Type to hold region delimiters (entry & exit block).
__isl_export __isl_give isl_set * isl_set_intersect_params(__isl_take isl_set *set, __isl_take isl_set *params)
__isl_null isl_set * isl_set_free(__isl_take isl_set *set)
__isl_export isl_bool isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
__isl_give isl_set * isl_set_copy(__isl_keep isl_set *set)
isl_bool isl_set_involves_dims(__isl_keep isl_set *set, enum isl_dim_type type, unsigned first, unsigned n)
isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
__isl_give isl_id * isl_set_get_dim_id(__isl_keep isl_set *set, enum isl_dim_type type, unsigned pos)
__isl_export isl_bool isl_set_is_empty(__isl_keep isl_set *set)
Represent the attributes of a loop.
Type for equivalent invariant accesses and their domain context.
MemoryAccessList InvariantAccesses
Memory accesses now treated invariant.
Type * AccessType
The type of the invariant access.
isl::set ExecutionContext
The execution context under which the memory location is accessed.
const SCEV * IdentifyingPointer
The pointer that identifies this equivalence class.
static void createCPUPrinter(PollyIRBuilder &Builder, Args... args)
Print a set of LLVM-IR Values or StringRefs via printf.
static llvm::Value * getPrintableString(PollyIRBuilder &Builder, llvm::StringRef Str)
Generate a constant string into the builder's llvm::Module which can be passed to createCPUPrinter().
static TupleKindPtr Domain("Domain")
__isl_give isl_set * isl_set_from_union_set(__isl_take isl_union_set *uset)