diff options
| author | Johannes Doerfert <doerfert@cs.uni-saarland.de> | 2016-05-12 15:12:43 +0000 |
|---|---|---|
| committer | Johannes Doerfert <doerfert@cs.uni-saarland.de> | 2016-05-12 15:12:43 +0000 |
| commit | 404a0f81ea47c743d75944b504bcc0a4dc81d5df (patch) | |
| tree | 7ee580a8732f39342b0a651dc3fce484691a6338 /polly/lib/CodeGen | |
| parent | 1168ca925cad2186772ff1692279846635baa1a0 (diff) | |
| download | bcm5719-llvm-404a0f81ea47c743d75944b504bcc0a4dc81d5df.tar.gz bcm5719-llvm-404a0f81ea47c743d75944b504bcc0a4dc81d5df.zip | |
Check overflows in RTCs and bail accordingly
We utilize assumptions on the input to model IR in polyhedral world.
To verify these assumptions we version the code and guard it with a
runtime-check (RTC). However, since the RTCs are themselves generated
from the polyhedral representation we generate them under the same
assumptions that they should verify. In other words, the guarantees
that we try to provide with the RTCs do not hold for the RTCs
themselves. To this end it is necessary to employ a different check
for the RTCs that will verify the assumptions did hold for them too.
Differential Revision: http://reviews.llvm.org/D20165
llvm-svn: 269299
Diffstat (limited to 'polly/lib/CodeGen')
| -rw-r--r-- | polly/lib/CodeGen/CodeGeneration.cpp | 9 | ||||
| -rw-r--r-- | polly/lib/CodeGen/IslExprBuilder.cpp | 134 | ||||
| -rw-r--r-- | polly/lib/CodeGen/IslNodeBuilder.cpp | 6 |
3 files changed, 139 insertions, 10 deletions
diff --git a/polly/lib/CodeGen/CodeGeneration.cpp b/polly/lib/CodeGen/CodeGeneration.cpp index c5c6527d911..757e24813cf 100644 --- a/polly/lib/CodeGen/CodeGeneration.cpp +++ b/polly/lib/CodeGen/CodeGeneration.cpp @@ -148,6 +148,7 @@ public: PollyIRBuilder Builder = createPollyIRBuilder(EnteringBB, Annotator); IslNodeBuilder NodeBuilder(Builder, Annotator, this, *DL, *LI, *SE, *DT, S); + IslExprBuilder &ExprBuilder = NodeBuilder.getExprBuilder(); // Only build the run-time condition and parameters _after_ having // introduced the conditional branch. This is important as the conditional @@ -191,7 +192,13 @@ public: NodeBuilder.addParameters(S.getContext()); - Value *RTC = buildRTC(Builder, NodeBuilder.getExprBuilder()); + ExprBuilder.setTrackOverflow(true); + Value *RTC = buildRTC(Builder, ExprBuilder); + Value *OverflowHappened = Builder.CreateNot( + ExprBuilder.getOverflowState(), "polly.rtc.overflown"); + RTC = Builder.CreateAnd(RTC, OverflowHappened, "polly.rtc.result"); + ExprBuilder.setTrackOverflow(false); + Builder.GetInsertBlock()->getTerminator()->setOperand(0, RTC); Builder.SetInsertPoint(&StartBlock->front()); diff --git a/polly/lib/CodeGen/IslExprBuilder.cpp b/polly/lib/CodeGen/IslExprBuilder.cpp index 912eb3984b6..b8c8e6557c9 100644 --- a/polly/lib/CodeGen/IslExprBuilder.cpp +++ b/polly/lib/CodeGen/IslExprBuilder.cpp @@ -10,6 +10,7 @@ //===----------------------------------------------------------------------===// #include "polly/CodeGen/IslExprBuilder.h" +#include "polly/Options.h" #include "polly/ScopInfo.h" #include "polly/Support/GICHelper.h" #include "polly/Support/ScopHelper.h" @@ -19,6 +20,123 @@ using namespace llvm; using namespace polly; +/// @brief Different overflow tracking modes. +enum OverflowTrackingChoice { + OT_NEVER, ///< Never tack potential overflows. + OT_REQUEST, ///< Track potential overflows if requested. + OT_ALWAYS ///< Always track potential overflows. +}; + +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."), + clEnumValEnd), + cl::Hidden, cl::init(OT_REQUEST), cl::ZeroOrMore, cl::cat(PollyCategory)); + +IslExprBuilder::IslExprBuilder(Scop &S, PollyIRBuilder &Builder, + IDToValueTy &IDToValue, ValueMapT &GlobalMap, + const DataLayout &DL, ScalarEvolution &SE, + DominatorTree &DT, LoopInfo &LI) + : S(S), Builder(Builder), IDToValue(IDToValue), GlobalMap(GlobalMap), + DL(DL), SE(SE), DT(DT), LI(LI) { + OverflowState = (OTMode == OT_ALWAYS) ? Builder.getFalse() : nullptr; +} + +void IslExprBuilder::setTrackOverflow(bool Enable) { + // If potential overflows are tracked always or never we ignore requests + // to change the behaviour. + if (OTMode != OT_REQUEST) + return; + + if (Enable) { + // If tracking should be enabled initialize the OverflowState. + OverflowState = Builder.getFalse(); + } else { + // If tracking should be disabled just unset the OverflowState. + OverflowState = nullptr; + } +} + +Value *IslExprBuilder::getOverflowState() const { + // If the overflow tracking was requested but it is disabled we avoid the + // additional nullptr checks at the call sides but instead provide a + // meaningful result. + if (OTMode == OT_NEVER) + return Builder.getFalse(); + return OverflowState; +} + +Value *IslExprBuilder::createBinOp(BinaryOperator::BinaryOps Opc, Value *LHS, + Value *RHS, const Twine &Name) { + // Handle the plain operation (without overflow tracking) first. + if (!OverflowState) { + switch (Opc) { + case Instruction::Add: + return Builder.CreateNSWAdd(LHS, RHS, Name); + case Instruction::Sub: + return Builder.CreateNSWSub(LHS, RHS, Name); + case Instruction::Mul: + return Builder.CreateNSWMul(LHS, RHS, Name); + default: + llvm_unreachable("Unknown binary operator!"); + } + } + + Function *F = nullptr; + Module *M = Builder.GetInsertBlock()->getModule(); + switch (Opc) { + case Instruction::Add: + F = Intrinsic::getDeclaration(M, Intrinsic::sadd_with_overflow, + {LHS->getType()}); + break; + case Instruction::Sub: + F = Intrinsic::getDeclaration(M, Intrinsic::ssub_with_overflow, + {LHS->getType()}); + break; + case Instruction::Mul: + F = Intrinsic::getDeclaration(M, Intrinsic::smul_with_overflow, + {LHS->getType()}); + break; + default: + llvm_unreachable("No overflow intrinsic for binary operator found!"); + } + + auto *ResultStruct = Builder.CreateCall(F, {LHS, RHS}, Name); + assert(ResultStruct->getType()->isStructTy()); + + auto *OverflowFlag = + Builder.CreateExtractValue(ResultStruct, 1, Name + ".obit"); + + // If all overflows are tracked we do not combine the results as this could + // cause dominance problems. Instead we will always keep the last overflow + // flag as current state. + if (OTMode == OT_ALWAYS) + OverflowState = OverflowFlag; + else + OverflowState = + Builder.CreateOr(OverflowState, OverflowFlag, "polly.overflow.state"); + + return Builder.CreateExtractValue(ResultStruct, 0, Name + ".res"); +} + +Value *IslExprBuilder::createAdd(Value *LHS, Value *RHS, const Twine &Name) { + return createBinOp(Instruction::Add, LHS, RHS, Name); +} + +Value *IslExprBuilder::createSub(Value *LHS, Value *RHS, const Twine &Name) { + return createBinOp(Instruction::Sub, LHS, RHS, Name); +} + +Value *IslExprBuilder::createMul(Value *LHS, Value *RHS, const Twine &Name) { + return createBinOp(Instruction::Mul, LHS, RHS, Name); +} + Type *IslExprBuilder::getWidestType(Type *T1, Type *T2) { assert(isa<IntegerType>(T1) && isa<IntegerType>(T2)); @@ -142,8 +260,7 @@ Value *IslExprBuilder::createAccessAddress(isl_ast_expr *Expr) { if (Ty != IndexOp->getType()) IndexOp = Builder.CreateIntCast(IndexOp, Ty, true); - IndexOp = - Builder.CreateAdd(IndexOp, NextIndex, "polly.access.add." + BaseName); + IndexOp = createAdd(IndexOp, NextIndex, "polly.access.add." + BaseName); } // For every but the last dimension multiply the size, for the last @@ -167,8 +284,7 @@ Value *IslExprBuilder::createAccessAddress(isl_ast_expr *Expr) { if (Ty != DimSize->getType()) DimSize = Builder.CreateSExtOrTrunc(DimSize, Ty, "polly.access.sext." + BaseName); - IndexOp = - Builder.CreateMul(IndexOp, DimSize, "polly.access.mul." + BaseName); + IndexOp = createMul(IndexOp, DimSize, "polly.access.mul." + BaseName); } Access = Builder.CreateGEP(Base, IndexOp, "polly.access." + BaseName); @@ -237,13 +353,13 @@ Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) { default: llvm_unreachable("This is no binary isl ast expression"); case isl_ast_op_add: - Res = Builder.CreateNSWAdd(LHS, RHS); + Res = createAdd(LHS, RHS); break; case isl_ast_op_sub: - Res = Builder.CreateNSWSub(LHS, RHS); + Res = createSub(LHS, RHS); break; case isl_ast_op_mul: - Res = Builder.CreateNSWMul(LHS, RHS); + Res = createMul(LHS, RHS); break; case isl_ast_op_div: Res = Builder.CreateSDiv(LHS, RHS, "pexp.div", true); @@ -265,8 +381,8 @@ Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) { // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d Value *One = ConstantInt::get(MaxType, 1); Value *Zero = ConstantInt::get(MaxType, 0); - Value *Sum1 = Builder.CreateSub(LHS, RHS, "pexp.fdiv_q.0"); - Value *Sum2 = Builder.CreateAdd(Sum1, One, "pexp.fdiv_q.1"); + Value *Sum1 = createSub(LHS, RHS, "pexp.fdiv_q.0"); + Value *Sum2 = createAdd(Sum1, One, "pexp.fdiv_q.1"); Value *isNegative = Builder.CreateICmpSLT(LHS, Zero, "pexp.fdiv_q.2"); Value *Dividend = Builder.CreateSelect(isNegative, Sum2, LHS, "pexp.fdiv_q.3"); diff --git a/polly/lib/CodeGen/IslNodeBuilder.cpp b/polly/lib/CodeGen/IslNodeBuilder.cpp index 601a2f83278..ccec67ea547 100644 --- a/polly/lib/CodeGen/IslNodeBuilder.cpp +++ b/polly/lib/CodeGen/IslNodeBuilder.cpp @@ -1001,7 +1001,13 @@ Value *IslNodeBuilder::preloadInvariantLoad(const MemoryAccess &MA, isl_ast_expr *DomainCond = isl_ast_build_expr_from_set(Build, Domain); Domain = nullptr; + ExprBuilder.setTrackOverflow(true); Value *Cond = ExprBuilder.create(DomainCond); + Value *OverflowHappened = Builder.CreateNot(ExprBuilder.getOverflowState(), + "polly.preload.cond.overflown"); + Cond = Builder.CreateAnd(Cond, OverflowHappened, "polly.preload.cond.result"); + ExprBuilder.setTrackOverflow(false); + if (!Cond->getType()->isIntegerTy(1)) Cond = Builder.CreateIsNotNull(Cond); |

