[polly] r249971 - Allow eager evaluated binary && and || conditions
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 11 06:21:05 PDT 2015
Author: jdoerfert
Date: Sun Oct 11 08:21:03 2015
New Revision: 249971
URL: http://llvm.org/viewvc/llvm-project?rev=249971&view=rev
Log:
Allow eager evaluated binary && and || conditions
The domain generation can handle lazy && and || by default but eager
evaluated expressions were dismissed as non-affine. With this patch we
will allow arbitrary combinations of and/or bit-operations in the
conditions of branches.
Differential Revision: http://reviews.llvm.org/D13624
Added:
polly/trunk/test/ScopInfo/eager-binary-and-or-conditions.ll
polly/trunk/test/ScopInfo/multiple-binary-or-conditions.ll
Modified:
polly/trunk/lib/Analysis/ScopDetection.cpp
polly/trunk/lib/Analysis/ScopInfo.cpp
Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=249971&r1=249970&r2=249971&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Sun Oct 11 08:21:03 2015
@@ -340,6 +340,17 @@ bool ScopDetection::isValidSwitch(BasicB
bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
Value *Condition, bool IsLoopBranch,
DetectionContext &Context) const {
+
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
+ auto Opcode = BinOp->getOpcode();
+ if (Opcode == Instruction::And || Opcode == Instruction::Or) {
+ Value *Op0 = BinOp->getOperand(0);
+ Value *Op1 = BinOp->getOperand(1);
+ return isValidBranch(BB, BI, Op0, IsLoopBranch, Context) &&
+ isValidBranch(BB, BI, Op1, IsLoopBranch, Context);
+ }
+ }
+
// Non constant conditions of branches need to be ICmpInst.
if (!isa<ICmpInst>(Condition)) {
if (!IsLoopBranch && AllowNonAffineSubRegions &&
Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=249971&r1=249970&r2=249971&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Sun Oct 11 08:21:03 2015
@@ -998,35 +998,39 @@ buildConditionSets(Scop &S, SwitchInst *
isl_pw_aff_free(LHS);
}
-/// @brief Build the conditions sets for the terminator @p TI in the @p Domain.
+/// @brief Build the conditions sets for the branch condition @p Condition in
+/// the @p Domain.
///
/// This will fill @p ConditionSets with the conditions under which control
/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
/// have as many elements as @p TI has successors.
static void
-buildConditionSets(Scop &S, TerminatorInst *TI, Loop *L,
+buildConditionSets(Scop &S, Value *Condition, TerminatorInst *TI, Loop *L,
__isl_keep isl_set *Domain,
SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
- if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
- return buildConditionSets(S, SI, L, Domain, ConditionSets);
-
- assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch.");
-
- if (TI->getNumSuccessors() == 1) {
- ConditionSets.push_back(isl_set_copy(Domain));
- return;
- }
-
- Value *Condition = getConditionFromTerminator(TI);
- assert(Condition && "No condition for Terminator");
-
isl_set *ConsequenceCondSet = nullptr;
if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
if (CCond->isZero())
ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
else
ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
+ } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
+ auto Opcode = BinOp->getOpcode();
+ assert(Opcode == Instruction::And || Opcode == Instruction::Or);
+
+ buildConditionSets(S, BinOp->getOperand(0), TI, L, Domain, ConditionSets);
+ buildConditionSets(S, BinOp->getOperand(1), TI, L, Domain, ConditionSets);
+
+ isl_set_free(ConditionSets.pop_back_val());
+ isl_set *ConsCondPart0 = ConditionSets.pop_back_val();
+ isl_set_free(ConditionSets.pop_back_val());
+ isl_set *ConsCondPart1 = ConditionSets.pop_back_val();
+
+ if (Opcode == Instruction::And)
+ ConsequenceCondSet = isl_set_intersect(ConsCondPart0, ConsCondPart1);
+ else
+ ConsequenceCondSet = isl_set_union(ConsCondPart0, ConsCondPart1);
} else {
auto *ICond = dyn_cast<ICmpInst>(Condition);
assert(ICond &&
@@ -1051,6 +1055,32 @@ buildConditionSets(Scop &S, TerminatorIn
isl_set_intersect(AlternativeCondSet, isl_set_copy(Domain))));
}
+/// @brief Build the conditions sets for the terminator @p TI in the @p Domain.
+///
+/// This will fill @p ConditionSets with the conditions under which control
+/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
+/// have as many elements as @p TI has successors.
+static void
+buildConditionSets(Scop &S, TerminatorInst *TI, Loop *L,
+ __isl_keep isl_set *Domain,
+ SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
+
+ if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
+ return buildConditionSets(S, SI, L, Domain, ConditionSets);
+
+ assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch.");
+
+ if (TI->getNumSuccessors() == 1) {
+ ConditionSets.push_back(isl_set_copy(Domain));
+ return;
+ }
+
+ Value *Condition = getConditionFromTerminator(TI);
+ assert(Condition && "No condition for Terminator");
+
+ return buildConditionSets(S, Condition, TI, L, Domain, ConditionSets);
+}
+
void ScopStmt::buildDomain() {
isl_id *Id;
Added: polly/trunk/test/ScopInfo/eager-binary-and-or-conditions.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/eager-binary-and-or-conditions.ll?rev=249971&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/eager-binary-and-or-conditions.ll (added)
+++ polly/trunk/test/ScopInfo/eager-binary-and-or-conditions.ll Sun Oct 11 08:21:03 2015
@@ -0,0 +1,87 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen -analyze < %s
+;
+; void or(float *A, long n, long m) {
+; for (long i = 0; i < 100; i++) {
+; if (i < n || i < m)
+; A[i] += i;
+; }
+; }
+;
+; void and(float *A, long n, long m) {
+; for (long i = 0; i < 100; i++) {
+; if (i < n && i < m)
+; A[i] += i;
+; }
+; }
+;
+; CHECK: Function: or
+; CHECK: Stmt_if_then
+; CHECK: Domain :=
+; CHECK: [n, m] -> { Stmt_if_then[i0] : (i0 <= 99 and i0 >= 0 and i0 <= -1 + m) or (i0 <= 99 and i0 >= 0 and i0 <= -1 + n) };
+;
+; CHECK: Function: and
+; CHECK: Stmt_if_then
+; CHECK: Domain :=
+; CHECK: [n, m] -> { Stmt_if_then[i0] : i0 <= 99 and i0 >= 0 and i0 <= -1 + m and i0 <= -1 + n }
+;
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: nounwind uwtable
+define void @or(float* nocapture %A, i64 %n, i64 %m) #0 {
+entry:
+ br label %for.body
+
+for.body: ; preds = %for.inc, %entry
+ %i.03 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
+ %cmp1 = icmp slt i64 %i.03, %n
+ %cmp2 = icmp slt i64 %i.03, %m
+ %or.cond = or i1 %cmp1, %cmp2
+ br i1 %or.cond, label %if.then, label %for.inc
+
+if.then: ; preds = %for.body
+ %conv = sitofp i64 %i.03 to float
+ %arrayidx = getelementptr inbounds float, float* %A, i64 %i.03
+ %0 = load float, float* %arrayidx, align 4
+ %add = fadd float %conv, %0
+ store float %add, float* %arrayidx, align 4
+ br label %for.inc
+
+for.inc: ; preds = %if.then, %for.body
+ %inc = add nuw nsw i64 %i.03, 1
+ %exitcond = icmp eq i64 %inc, 100
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.inc
+ ret void
+}
+
+; Function Attrs: nounwind uwtable
+define void @and(float* nocapture %A, i64 %n, i64 %m) #0 {
+entry:
+ br label %for.body
+
+for.body: ; preds = %for.inc, %entry
+ %i.03 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
+ %cmp1 = icmp slt i64 %i.03, %n
+ %cmp2 = icmp slt i64 %i.03, %m
+ %or.cond = and i1 %cmp1, %cmp2
+ br i1 %or.cond, label %if.then, label %for.inc
+
+if.then: ; preds = %for.body
+ %conv = sitofp i64 %i.03 to float
+ %arrayidx = getelementptr inbounds float, float* %A, i64 %i.03
+ %0 = load float, float* %arrayidx, align 4
+ %add = fadd float %conv, %0
+ store float %add, float* %arrayidx, align 4
+ br label %for.inc
+
+for.inc: ; preds = %for.body, %if.then
+ %inc = add nuw nsw i64 %i.03, 1
+ %exitcond = icmp eq i64 %inc, 100
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.inc
+ ret void
+}
Added: polly/trunk/test/ScopInfo/multiple-binary-or-conditions.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/multiple-binary-or-conditions.ll?rev=249971&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/multiple-binary-or-conditions.ll (added)
+++ polly/trunk/test/ScopInfo/multiple-binary-or-conditions.ll Sun Oct 11 08:21:03 2015
@@ -0,0 +1,47 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-codegen -analyze < %s
+;
+; void or(float *A, long n, long m) {
+; for (long i = 0; i < 100; i++) {
+; if (i < n || i < m || i > p)
+; A[i] += i;
+; }
+; }
+;
+; CHECK: Function: or
+; CHECK: Stmt_if_then
+; CHECK: Domain :=
+; CHECK: [n, m, p] -> { Stmt_if_then[i0] : (i0 >= 1 + p and i0 <= 99 and i0 >= 0) or (i0 <= 99 and i0 >= 0 and i0 <= -1 + m) or (i0 <= 99 and i0 >= 0 and i0 <= -1 + n) };
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: nounwind uwtable
+define void @or(float* nocapture %A, i64 %n, i64 %m, i64 %p) #0 {
+entry:
+ br label %for.body
+
+for.body: ; preds = %for.inc, %entry
+ %i.03 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
+ %cmp1 = icmp slt i64 %i.03, %n
+ %cmp2 = icmp slt i64 %i.03, %m
+ %cmp3 = icmp sgt i64 %i.03, %p
+ %or.tmp = or i1 %cmp1, %cmp2
+ %or.cond = or i1 %or.tmp, %cmp3
+ br i1 %or.cond, label %if.then, label %for.inc
+
+if.then: ; preds = %for.body
+ %conv = sitofp i64 %i.03 to float
+ %arrayidx = getelementptr inbounds float, float* %A, i64 %i.03
+ %0 = load float, float* %arrayidx, align 4
+ %add = fadd float %conv, %0
+ store float %add, float* %arrayidx, align 4
+ br label %for.inc
+
+for.inc: ; preds = %if.then, %for.body
+ %inc = add nuw nsw i64 %i.03, 1
+ %exitcond = icmp eq i64 %inc, 100
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.inc
+ ret void
+}
More information about the llvm-commits
mailing list