16#include "llvm/Transforms/Utils/BasicBlockUtils.h"
28static cl::opt<OverflowTrackingChoice>
OTMode(
29 "polly-overflow-tracking",
30 cl::desc(
"Define where potential integer overflows in generated "
31 "expressions should be tracked."),
32 cl::values(clEnumValN(
OT_NEVER,
"never",
"Never track the overflow bit."),
34 "Track the overflow bit if requested."),
36 "Always track the overflow bit.")),
41 const DataLayout &DL, ScalarEvolution &SE,
42 DominatorTree &DT, LoopInfo &LI,
43 BasicBlock *StartBlock)
44 :
S(
S), Builder(Builder), IDToValue(IDToValue), GlobalMap(GlobalMap),
45 DL(DL), SE(SE), StartBlock(StartBlock), GenDT(&DT), GenLI(&LI),
51 llvm::DominatorTree *GenDT,
52 llvm::LoopInfo *GenLI,
53 llvm::ScalarEvolution *GenSE) {
56 GenFn ==
GenLI->getTopLevelLoops().front()->getHeader()->getParent());
95 auto BitWidth = APValue.getBitWidth();
96 return BitWidth >= 64;
103 for (
int i = 0; i < NumArgs; i++) {
113 Value *RHS,
const Twine &Name) {
117 case Instruction::Add:
118 return Builder.CreateNSWAdd(LHS, RHS, Name);
119 case Instruction::Sub:
120 return Builder.CreateNSWSub(LHS, RHS, Name);
121 case Instruction::Mul:
122 return Builder.CreateNSWMul(LHS, RHS, Name);
124 llvm_unreachable(
"Unknown binary operator!");
131 case Instruction::Add:
132 F = Intrinsic::getDeclaration(
M, Intrinsic::sadd_with_overflow,
135 case Instruction::Sub:
136 F = Intrinsic::getDeclaration(
M, Intrinsic::ssub_with_overflow,
139 case Instruction::Mul:
140 F = Intrinsic::getDeclaration(
M, Intrinsic::smul_with_overflow,
144 llvm_unreachable(
"No overflow intrinsic for binary operator found!");
147 auto *ResultStruct =
Builder.CreateCall(F, {LHS, RHS}, Name);
148 assert(ResultStruct->getType()->isStructTy());
151 Builder.CreateExtractValue(ResultStruct, 1, Name +
".obit");
162 return Builder.CreateExtractValue(ResultStruct, 0, Name +
".res");
166 return createBinOp(Instruction::Add, LHS, RHS, Name);
170 return createBinOp(Instruction::Sub, LHS, RHS, Name);
174 return createBinOp(Instruction::Mul, LHS, RHS, Name);
178 assert(isa<IntegerType>(T1) && isa<IntegerType>(T2));
180 if (T1->getPrimitiveSizeInBits() < T2->getPrimitiveSizeInBits())
188 "Unsupported unary operation");
192 assert(MaxType->isIntegerTy() &&
193 "Unary expressions can only be created for integer types");
198 if (MaxType != V->getType())
199 V =
Builder.CreateSExt(V, MaxType);
202 return createSub(ConstantInt::getNullValue(MaxType), V);
207 "isl ast expression not of type isl_ast_op");
209 "We need at least two operands in an n-ary operation");
211 CmpInst::Predicate Pred;
214 llvm_unreachable(
"This is not a an n-ary isl ast expression");
216 Pred = CmpInst::ICMP_SGT;
219 Pred = CmpInst::ICMP_SLT;
229 if (Ty != OpV->getType())
230 OpV =
Builder.CreateSExt(OpV, Ty);
232 if (Ty != V->getType())
236 V =
Builder.CreateSelect(Cmp, V, OpV);
247std::pair<Value *, Type *>
250 "isl ast expression not of type isl_ast_op");
252 "not an access isl ast expression");
254 "We need at least two operands to create a member access.");
256 Value *Base, *IndexOp, *Access;
270 SAI = (*IDToSAI)[BaseId];
277 assert(SAI &&
"No ScopArrayInfo found for this isl_id.");
281 if (
auto NewBase =
GlobalMap.lookup(Base))
284 assert(Base->getType()->isPointerTy() &&
"Access base should be a pointer");
285 StringRef BaseName = Base->getName();
297 assert(NextIndex->getType()->isIntegerTy() &&
298 "Access index should be an integer");
306 Type *Ty =
getWidestType(NextIndex->getType(), IndexOp->getType());
308 if (Ty != NextIndex->getType())
309 NextIndex =
Builder.CreateIntCast(NextIndex, Ty,
true);
310 if (Ty != IndexOp->getType())
311 IndexOp =
Builder.CreateIntCast(IndexOp, Ty,
true);
313 IndexOp =
createAdd(IndexOp, NextIndex,
"polly.access.add." + BaseName);
330 Type *Ty =
getWidestType(DimSize->getType(), IndexOp->getType());
332 if (Ty != IndexOp->getType())
333 IndexOp =
Builder.CreateSExtOrTrunc(IndexOp, Ty,
334 "polly.access.sext." + BaseName);
335 if (Ty != DimSize->getType())
336 DimSize =
Builder.CreateSExtOrTrunc(DimSize, Ty,
337 "polly.access.sext." + BaseName);
338 IndexOp =
createMul(IndexOp, DimSize,
"polly.access.mul." + BaseName);
342 "polly.access." + BaseName);
352 assert(Info.first &&
"Could not create op access address");
353 return Builder.CreateLoad(Info.second, Info.first,
354 Info.first->getName() +
".load");
363 "isl ast expression not of type isl_ast_op");
365 "not a binary isl ast expression");
372 Type *LHSType = LHS->getType();
373 Type *RHSType = RHS->getType();
398 llvm_unreachable(
"This is no binary isl ast expression");
401 if (MaxType != RHS->getType())
402 RHS =
Builder.CreateSExt(RHS, MaxType);
404 if (MaxType != LHS->getType())
405 LHS =
Builder.CreateSExt(LHS, MaxType);
409 llvm_unreachable(
"This is no binary isl ast expression");
420 Res =
Builder.CreateSDiv(LHS, RHS,
"pexp.div",
true);
423 Res =
Builder.CreateUDiv(LHS, RHS,
"pexp.p_div_q");
426 if (
auto *Const = dyn_cast<ConstantInt>(RHS)) {
427 auto &Val = Const->getValue();
428 if (Val.isPowerOf2() && Val.isNonNegative()) {
429 Res =
Builder.CreateAShr(LHS, Val.ceilLogBase2(),
"polly.fdiv_q.shr");
437 Value *One = ConstantInt::get(MaxType, 1);
438 Value *Zero = ConstantInt::get(MaxType, 0);
441 Value *isNegative =
Builder.CreateICmpSLT(LHS, Zero,
"pexp.fdiv_q.2");
443 Builder.CreateSelect(isNegative, Sum2, LHS,
"pexp.fdiv_q.3");
444 Res =
Builder.CreateSDiv(Dividend, RHS,
"pexp.fdiv_q.4");
448 Res =
Builder.CreateURem(LHS, RHS,
"pexp.pdiv_r");
452 Res =
Builder.CreateSRem(LHS, RHS,
"pexp.zdiv_r");
466 "Unsupported unary isl ast expression");
467 Value *LHS, *RHS, *Cond;
471 if (!Cond->getType()->isIntegerTy(1))
472 Cond =
Builder.CreateIsNotNull(Cond);
480 if (MaxType != RHS->getType())
481 RHS =
Builder.CreateSExt(RHS, MaxType);
483 if (MaxType != LHS->getType())
484 LHS =
Builder.CreateSExt(LHS, MaxType);
488 return Builder.CreateSelect(Cond, LHS, RHS);
493 "Expected an isl_ast_expr_op expression");
499 bool HasNonAddressOfOperand =
508 auto *LHSTy = LHS->getType();
509 auto *RHSTy = RHS->getType();
510 bool IsPtrType = LHSTy->isPointerTy() || RHSTy->isPointerTy();
511 bool UseUnsignedCmp = IsPtrType && !HasNonAddressOfOperand;
513 auto *PtrAsIntTy =
Builder.getIntNTy(
DL.getPointerSizeInBits());
514 if (LHSTy->isPointerTy())
515 LHS =
Builder.CreatePtrToInt(LHS, PtrAsIntTy);
516 if (RHSTy->isPointerTy())
517 RHS =
Builder.CreatePtrToInt(RHS, PtrAsIntTy);
519 if (LHS->getType() != RHS->getType()) {
520 Type *MaxType = LHS->getType();
523 if (MaxType != RHS->getType())
524 RHS =
Builder.CreateSExt(RHS, MaxType);
526 if (MaxType != LHS->getType())
527 LHS =
Builder.CreateSExt(LHS, MaxType);
532 "Unsupported ICmp isl ast expression");
534 "Isl ast op type interface changed");
536 CmpInst::Predicate Predicates[5][2] = {
537 {CmpInst::ICMP_EQ, CmpInst::ICMP_EQ},
538 {CmpInst::ICMP_SLE, CmpInst::ICMP_ULE},
539 {CmpInst::ICMP_SLT, CmpInst::ICMP_ULT},
540 {CmpInst::ICMP_SGE, CmpInst::ICMP_UGE},
541 {CmpInst::ICMP_SGT, CmpInst::ICMP_UGT},
553 "Expected an isl_ast_expr_op expression");
561 "Unsupported isl_ast_op_type");
578 if (!LHS->getType()->isIntegerTy(1))
579 LHS =
Builder.CreateIsNotNull(LHS);
580 if (!RHS->getType()->isIntegerTy(1))
581 RHS =
Builder.CreateIsNotNull(RHS);
585 llvm_unreachable(
"Unsupported boolean expression");
601 "Expected an isl_ast_expr_op expression");
607 LLVMContext &Context = F->getContext();
612 "Unsupported isl_ast_op_type");
614 auto InsertBB =
Builder.GetInsertBlock();
615 auto InsertPoint =
Builder.GetInsertPoint();
616 auto NextBB = SplitBlock(InsertBB, &*InsertPoint,
GenDT,
GenLI);
617 BasicBlock *CondBB = BasicBlock::Create(Context,
"polly.cond", F);
618 GenLI->changeLoopFor(CondBB,
GenLI->getLoopFor(InsertBB));
619 GenDT->addNewBlock(CondBB, InsertBB);
621 InsertBB->getTerminator()->eraseFromParent();
622 Builder.SetInsertPoint(InsertBB);
623 auto BR =
Builder.CreateCondBr(
Builder.getTrue(), NextBB, CondBB);
625 Builder.SetInsertPoint(CondBB);
628 Builder.SetInsertPoint(InsertBB->getTerminator());
631 if (!LHS->getType()->isIntegerTy(1))
632 LHS =
Builder.CreateIsNotNull(LHS);
633 auto LeftBB =
Builder.GetInsertBlock();
636 BR->setCondition(
Builder.CreateNeg(LHS));
638 BR->setCondition(LHS);
640 Builder.SetInsertPoint(CondBB->getTerminator());
642 if (!RHS->getType()->isIntegerTy(1))
643 RHS =
Builder.CreateIsNotNull(RHS);
644 auto RightBB =
Builder.GetInsertBlock();
646 Builder.SetInsertPoint(NextBB->getTerminator());
651 PHI->addIncoming(RHS, RightBB);
659 "Expression not of type isl_ast_expr_op");
665 llvm_unreachable(
"Unsupported isl ast expression");
700 llvm_unreachable(
"Unsupported isl_ast_expr_op kind.");
705 "Expected an isl_ast_expr_op expression.");
710 "Expected address of operator to be an isl_ast_expr_op expression.");
712 "Expected address of operator to be an access expression.");
723 "Expression not of type isl_ast_expr_ident");
734 V = UndefValue::get(
getType(Expr));
736 if (V->getType()->isPointerTy())
737 V =
Builder.CreatePtrToInt(V,
Builder.getIntNTy(
DL.getPointerSizeInBits()));
739 assert(V &&
"Unknown parameter id found");
752 return IntegerType::get(
Builder.getContext(), 64);
757 "Expression not of type isl_ast_expr_int");
766 auto BitWidth = APValue.getBitWidth();
770 T =
Builder.getIntNTy(BitWidth);
772 APValue = APValue.sext(T->getBitWidth());
773 V = ConstantInt::get(T, APValue);
782 llvm_unreachable(
"Code generation error");
791 llvm_unreachable(
"Unexpected enum value");
polly dump Polly Dump Function
polly dump Polly Dump Module
OverflowTrackingChoice
Different overflow tracking modes.
@ OT_ALWAYS
Always track potential overflows.
@ OT_NEVER
Never tack potential overflows.
@ OT_REQUEST
Track potential overflows if requested.
static cl::opt< OverflowTrackingChoice > OTMode("polly-overflow-tracking", cl::desc("Define where potential integer overflows in generated " "expressions should be tracked."), cl::values(clEnumValN(OT_NEVER, "never", "Never track the overflow bit."), clEnumValN(OT_REQUEST, "request", "Track the overflow bit if requested."), clEnumValN(OT_ALWAYS, "always", "Always track the overflow bit.")), cl::Hidden, cl::init(OT_REQUEST), cl::cat(PollyCategory))
llvm::cl::OptionCategory PollyCategory
static RegisterPass< ScopPrinterWrapperPass > M("dot-scops", "Polly - Print Scops of function")
__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_give isl_id * isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
__isl_give isl_val * isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
#define isl_ast_op_fdiv_q
#define isl_ast_op_member
#define isl_ast_op_pdiv_r
#define isl_ast_op_zdiv_r
#define isl_ast_op_or_else
#define isl_ast_op_access
#define isl_ast_op_select
#define isl_ast_op_pdiv_q
#define isl_ast_op_and_then
#define isl_ast_op_address_of
isl::ast_expr get_op_arg(int pos) const
__isl_keep isl_ast_expr * get() const
llvm::BasicBlock * StartBlock
bool hasLargeInts(isl::ast_expr Expr)
Check if an Expr contains integer constants larger than 64 bit.
llvm::Value * createAdd(llvm::Value *LHS, llvm::Value *RHS, const llvm::Twine &Name="")
Create an addition and track overflows if requested.
llvm::Value * createOpBoolean(__isl_take isl_ast_expr *Expr)
llvm::Value * createOpICmp(__isl_take isl_ast_expr *Expr)
llvm::Value * createBinOp(llvm::BinaryOperator::BinaryOps Opc, llvm::Value *LHS, llvm::Value *RHS, const llvm::Twine &Name)
Create a binary operation Opc and track overflows if requested.
llvm::ScalarEvolution * GenSE
IDToScopArrayInfoTy * IDToSAI
A map from isl_ids to ScopArrayInfo objects.
llvm::Value * createOpAccess(__isl_take isl_ast_expr *Expr)
void setTrackOverflow(bool Enable)
Change if runtime overflows are tracked or not.
IslExprBuilder(Scop &S, PollyIRBuilder &Builder, IDToValueTy &IDToValue, ValueMapT &GlobalMap, const llvm::DataLayout &DL, llvm::ScalarEvolution &SE, llvm::DominatorTree &DT, llvm::LoopInfo &LI, llvm::BasicBlock *StartBlock)
Construct an IslExprBuilder.
llvm::Value * getOverflowState() const
Return the current overflow status or nullptr if it is not tracked.
const llvm::DataLayout & DL
llvm::DominatorTree * GenDT
Relates to the region where the code is emitted into.
llvm::MapVector< isl_id *, llvm::AssertingVH< llvm::Value > > IDToValueTy
A map from isl_ids to llvm::Values.
llvm::Value * create(__isl_take isl_ast_expr *Expr)
Create LLVM-IR for an isl_ast_expr[ession].
llvm::Type * getWidestType(llvm::Type *T1, llvm::Type *T2)
Return the largest of two types.
std::pair< llvm::Value *, llvm::Type * > createAccessAddress(__isl_take isl_ast_expr *Expr)
Create LLVM-IR that computes the memory location of an access expression.
llvm::Value * createOpAddressOf(__isl_take isl_ast_expr *Expr)
llvm::Value * createMul(llvm::Value *LHS, llvm::Value *RHS, const llvm::Twine &Name="")
Create a multiplication and track overflows if requested.
llvm::Value * OverflowState
Flag that will be set if an overflow occurred at runtime.
llvm::Value * createOpNAry(__isl_take isl_ast_expr *Expr)
llvm::IntegerType * getType(__isl_keep isl_ast_expr *Expr)
Return the type with which this expression should be computed.
llvm::Value * createOpBooleanConditional(__isl_take isl_ast_expr *Expr)
llvm::ScalarEvolution & SE
llvm::Value * createOpSelect(__isl_take isl_ast_expr *Expr)
void switchGeneratedFunc(llvm::Function *GenFn, llvm::DominatorTree *GenDT, llvm::LoopInfo *GenLI, llvm::ScalarEvolution *GenSE)
Change the function that code is emitted into.
llvm::Value * createOp(__isl_take isl_ast_expr *Expr)
llvm::Value * createOpUnary(__isl_take isl_ast_expr *Expr)
llvm::Value * createInt(__isl_take isl_ast_expr *Expr)
llvm::Value * createId(__isl_take isl_ast_expr *Expr)
llvm::Value * createSub(llvm::Value *LHS, llvm::Value *RHS, const llvm::Twine &Name="")
Create a subtraction and track overflows if requested.
llvm::Value * createOpBin(__isl_take isl_ast_expr *Expr)
A class to store information about arrays in the SCoP.
const SCEV * getDimensionSize(unsigned Dim) const
Return the size of dimension dim as SCEV*.
static const ScopArrayInfo * getFromId(isl::id Id)
Access the ScopArrayInfo associated with an isl Id.
Value * getBasePtr() const
Return the base pointer.
Type * getElementType() const
Get the canonical element type of this array.
__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)
enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
boolean manage(isl_bool val)
This file contains the declaration of the PolyhedralInfo class, which will provide an interface to ex...
@ Value
MemoryKind::Value: Models an llvm::Value.
@ PHI
MemoryKind::PHI: Models PHI nodes within the SCoP.
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::Instruction *IP, ValueMapT *VMap, LoopToScevMapT *LoopMap, llvm::BasicBlock *RTCBB)
Wrapper for SCEVExpander extended to all Polly features.
llvm::IRBuilder< llvm::ConstantFolder, IRInserter > PollyIRBuilder
llvm::DenseMap< llvm::AssertingVH< llvm::Value >, llvm::AssertingVH< llvm::Value > > ValueMapT
Type to remap values.
llvm::APInt APIntFromVal(__isl_take isl_val *Val)
Translate isl_val to llvm::APInt.
static void createCPUPrinter(PollyIRBuilder &Builder, Args... args)
Print a set of LLVM-IR Values or StringRefs via printf.