diff --git a/polly/include/polly/CodeGen/IslAst.h b/polly/include/polly/CodeGen/IslAst.h index 023d12b27af8..6b8a90ac2534 100644 --- a/polly/include/polly/CodeGen/IslAst.h +++ b/polly/include/polly/CodeGen/IslAst.h @@ -33,6 +33,7 @@ class raw_ostream; } struct isl_ast_node; +struct isl_ast_expr; struct isl_ast_build; struct isl_pw_multi_aff; @@ -64,6 +65,14 @@ public: isl_ast_node *getAst(); + /// @brief Get the run conditon. + /// + /// Only if the run condition evaluates at run-time to a non-zero value, the + /// assumptions that have been taken hold. If the run condition evaluates to + /// zero/false some assumptions do not hold and the original code needs to + /// be executed. + __isl_give isl_ast_expr *getRunCondition(); + bool runOnScop(Scop &S); void printScop(llvm::raw_ostream &OS) const; virtual void getAnalysisUsage(AnalysisUsage &AU) const; diff --git a/polly/lib/CodeGen/IslAst.cpp b/polly/lib/CodeGen/IslAst.cpp index 94cc65f4e16c..629d86c94f44 100644 --- a/polly/lib/CodeGen/IslAst.cpp +++ b/polly/lib/CodeGen/IslAst.cpp @@ -464,6 +464,9 @@ bool IslAstInfo::runOnScop(Scop &Scop) { } __isl_give isl_ast_node *IslAstInfo::getAst() { return Ast->getAst(); } +__isl_give isl_ast_expr *IslAstInfo::getRunCondition() { + return Ast->getRunCondition(); +} void IslAstInfo::printScop(raw_ostream &OS) const { Function *F = S->getRegion().getEntry()->getParent(); diff --git a/polly/lib/CodeGen/IslCodeGeneration.cpp b/polly/lib/CodeGen/IslCodeGeneration.cpp index 465d1101d3a0..cde2a54b80f6 100644 --- a/polly/lib/CodeGen/IslCodeGeneration.cpp +++ b/polly/lib/CodeGen/IslCodeGeneration.cpp @@ -542,6 +542,7 @@ public: void addParameters(__isl_take isl_set *Context); void create(__isl_take isl_ast_node *Node); + IslExprBuilder &getExprBuilder() { return ExprBuilder; } private: IRBuilder<> &Builder; @@ -1032,6 +1033,17 @@ public: IRBuilder<> Builder(StartBlock->begin()); IslNodeBuilder NodeBuilder(Builder, this); + + // Build condition that evaluates at run-time if all assumptions taken + // for the scop hold. If we detect some assumptions do not hold, the + // original code is executed. + Value *V = NodeBuilder.getExprBuilder().create(AstInfo.getRunCondition()); + Value *Zero = ConstantInt::get(V->getType(), 0); + V = Builder.CreateICmp(CmpInst::ICMP_NE, Zero, V); + BasicBlock *PrevBB = StartBlock->getUniquePredecessor(); + BranchInst *Branch = dyn_cast(PrevBB->getTerminator()); + Branch->setCondition(V); + NodeBuilder.addParameters(S.getContext()); NodeBuilder.create(Ast); return true; diff --git a/polly/test/Isl/CodeGen/run-time-condition.ll b/polly/test/Isl/CodeGen/run-time-condition.ll new file mode 100644 index 000000000000..9d57630abab0 --- /dev/null +++ b/polly/test/Isl/CodeGen/run-time-condition.ll @@ -0,0 +1,31 @@ +; RUN: opt %loadPolly -basicaa -polly-codegen-isl -S %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @run-time-condition(i16* noalias %A, i16* noalias %B) { +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %indvar = phi i64 [ 0, %entry ], [ %inc, %for.body ] + %cmp = icmp slt i64 %indvar, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %arrayidx = getelementptr inbounds i16* %B, i64 0 + %load = load i16* %arrayidx + %add10 = add nsw i16 %load, 1 + %arrayidx13 = getelementptr inbounds i16* %A, i64 %indvar + store i16 %add10, i16* %arrayidx13, align 2 + %inc = add nsw i64 %indvar, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +; The trivial case, no run-time checks required. +; +; CHECK: polly.split_new_and_old: +; CHECK: br i1 true, label %polly.start, label %for.cond