[polly] r248701 - Allow switch instructions in SCoPs
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 28 02:33:23 PDT 2015
Author: jdoerfert
Date: Mon Sep 28 04:33:22 2015
New Revision: 248701
URL: http://llvm.org/viewvc/llvm-project?rev=248701&view=rev
Log:
Allow switch instructions in SCoPs
This patch allows switch instructions with affine conditions in the
SCoP. Also switch instructions in non-affine subregions are allowed.
Both did not require much changes to the code, though there was some
refactoring needed to integrate them without code duplication.
In the llvm-test suite the number of profitable SCoPs increased from
135 to 139 but more importantly we can handle more benchmarks and user
inputs without preprocessing.
Differential Revision: http://reviews.llvm.org/D13200
Added:
polly/trunk/test/Isl/CodeGen/non-affine-switch.ll
polly/trunk/test/Isl/CodeGen/switch-in-non-affine-region.ll
polly/trunk/test/ScopInfo/switch-1.ll
polly/trunk/test/ScopInfo/switch-2.ll
polly/trunk/test/ScopInfo/switch-3.ll
polly/trunk/test/ScopInfo/switch-4.ll
polly/trunk/test/ScopInfo/switch-5.ll
polly/trunk/test/ScopInfo/switch-6.ll
polly/trunk/test/ScopInfo/switch-7.ll
Modified:
polly/trunk/include/polly/ScopDetection.h
polly/trunk/include/polly/ScopDetectionDiagnostic.h
polly/trunk/include/polly/Support/ScopHelper.h
polly/trunk/lib/Analysis/ScopDetection.cpp
polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp
polly/trunk/lib/Analysis/ScopInfo.cpp
polly/trunk/lib/CodeGen/BlockGenerators.cpp
polly/trunk/lib/Support/ScopHelper.cpp
Modified: polly/trunk/include/polly/ScopDetection.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopDetection.h?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopDetection.h (original)
+++ polly/trunk/include/polly/ScopDetection.h Mon Sep 28 04:33:22 2015
@@ -271,6 +271,28 @@ private:
/// @return True if the instruction is valid, false otherwise.
bool isValidInstruction(Instruction &Inst, DetectionContext &Context) const;
+ /// @brief Check if the switch @p SI with condition @p Condition is valid.
+ ///
+ /// @param BB The block to check.
+ /// @param SI The switch to check.
+ /// @param Condition The switch condition.
+ /// @param Context The context of scop detection.
+ ///
+ /// @return True if the branch @p BI is valid.
+ bool isValidSwitch(BasicBlock &BB, SwitchInst *SI, Value *Condition,
+ DetectionContext &Context) const;
+
+ /// @brief Check if the branch @p BI with condition @p Condition is valid.
+ ///
+ /// @param BB The block to check.
+ /// @param BI The branch to check.
+ /// @param Condition The branch condition.
+ /// @param Context The context of scop detection.
+ ///
+ /// @return True if the branch @p BI is valid.
+ bool isValidBranch(BasicBlock &BB, BranchInst *BI, Value *Condition,
+ DetectionContext &Context) const;
+
/// @brief Check if the control flow in a basic block is valid.
///
/// @param BB The BB to check the control flow.
Modified: polly/trunk/include/polly/ScopDetectionDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopDetectionDiagnostic.h?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopDetectionDiagnostic.h (original)
+++ polly/trunk/include/polly/ScopDetectionDiagnostic.h Mon Sep 28 04:33:22 2015
@@ -62,7 +62,7 @@ void emitValidRemarks(const llvm::Functi
enum RejectReasonKind {
// CFG Category
rrkCFG,
- rrkNonBranchTerminator,
+ rrkInvalidTerminator,
rrkCondition,
rrkLastCFG,
@@ -230,13 +230,13 @@ public:
};
//===----------------------------------------------------------------------===//
-/// @brief Captures a non-branch terminator within a Scop candidate.
-class ReportNonBranchTerminator : public ReportCFG {
+/// @brief Captures bad terminator within a Scop candidate.
+class ReportInvalidTerminator : public ReportCFG {
BasicBlock *BB;
public:
- ReportNonBranchTerminator(BasicBlock *BB)
- : ReportCFG(rrkNonBranchTerminator), BB(BB) {}
+ ReportInvalidTerminator(BasicBlock *BB)
+ : ReportCFG(rrkInvalidTerminator), BB(BB) {}
/// @name LLVM-RTTI interface
//@{
Modified: polly/trunk/include/polly/Support/ScopHelper.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ScopHelper.h?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ScopHelper.h (original)
+++ polly/trunk/include/polly/Support/ScopHelper.h Mon Sep 28 04:33:22 2015
@@ -30,6 +30,7 @@ class StringRef;
class DataLayout;
class DominatorTree;
class RegionInfo;
+class TerminatorInst;
class ScalarEvolution;
}
@@ -113,5 +114,14 @@ llvm::Value *expandCodeFor(Scop &S, llvm
///
/// @return True if the block is a error block, false otherwise.
bool isErrorBlock(llvm::BasicBlock &BB);
+
+/// @brief Return the condition for the terminator @p TI.
+///
+/// For unconditional branches the "i1 true" condition will be returned.
+///
+/// @param TI The terminator to get the condition from.
+///
+/// @return The condition of @p TI and nullptr if none could be extracted.
+llvm::Value *getConditionFromTerminator(llvm::TerminatorInst *TI);
}
#endif
Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Mon Sep 28 04:33:22 2015
@@ -299,40 +299,35 @@ bool ScopDetection::addOverApproximatedR
return (AllowNonAffineSubLoops || Context.BoxedLoopsSet.empty());
}
-bool ScopDetection::isValidCFG(BasicBlock &BB,
- DetectionContext &Context) const {
+bool ScopDetection::isValidSwitch(BasicBlock &BB, SwitchInst *SI,
+ Value *Condition,
+ DetectionContext &Context) const {
Region &CurRegion = Context.CurRegion;
- TerminatorInst *TI = BB.getTerminator();
-
- // Return instructions are only valid if the region is the top level region.
- if (isa<ReturnInst>(TI) && !CurRegion.getExit() && TI->getNumOperands() == 0)
- return true;
-
- BranchInst *Br = dyn_cast<BranchInst>(TI);
+ Loop *L = LI->getLoopFor(&BB);
+ const SCEV *ConditionSCEV = SE->getSCEVAtScope(Condition, L);
- if (!Br)
- return invalid<ReportNonBranchTerminator>(Context, /*Assert=*/true, &BB);
-
- if (Br->isUnconditional())
- return true;
+ if (!isAffineExpr(&CurRegion, ConditionSCEV, *SE))
+ if (!AllowNonAffineSubRegions ||
+ !addOverApproximatedRegion(RI->getRegionFor(&BB), Context))
+ return invalid<ReportNonAffBranch>(Context, /*Assert=*/true, &BB,
+ ConditionSCEV, ConditionSCEV, SI);
- Value *Condition = Br->getCondition();
+ return true;
+}
- // UndefValue is not allowed as condition.
- if (isa<UndefValue>(Condition))
- return invalid<ReportUndefCond>(Context, /*Assert=*/true, Br, &BB);
+bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
+ Value *Condition,
+ DetectionContext &Context) const {
+ Region &CurRegion = Context.CurRegion;
- // Only Constant and ICmpInst are allowed as condition.
- if (!(isa<Constant>(Condition) || isa<ICmpInst>(Condition))) {
+ // Non constant conditions of branches need to be ICmpInst.
+ if (!isa<ICmpInst>(Condition)) {
if (!AllowNonAffineSubRegions ||
!addOverApproximatedRegion(RI->getRegionFor(&BB), Context))
- return invalid<ReportInvalidCond>(Context, /*Assert=*/true, Br, &BB);
+ return invalid<ReportInvalidCond>(Context, /*Assert=*/true, BI, &BB);
}
- // Allow perfectly nested conditions.
- assert(Br->getNumSuccessors() == 2 && "Unexpected number of successors");
-
if (ICmpInst *ICmp = dyn_cast<ICmpInst>(Condition)) {
// Unsigned comparisons are not allowed. They trigger overflow problems
// in the code generation.
@@ -340,7 +335,7 @@ bool ScopDetection::isValidCFG(BasicBloc
// TODO: This is not sufficient and just hides bugs. However it does pretty
// well.
if (ICmp->isUnsigned() && !AllowUnsigned)
- return invalid<ReportUnsignedCond>(Context, /*Assert=*/true, Br, &BB);
+ return invalid<ReportUnsignedCond>(Context, /*Assert=*/true, BI, &BB);
// Are both operands of the ICmp affine?
if (isa<UndefValue>(ICmp->getOperand(0)) ||
@@ -369,6 +364,38 @@ bool ScopDetection::isValidCFG(BasicBloc
return true;
}
+bool ScopDetection::isValidCFG(BasicBlock &BB,
+ DetectionContext &Context) const {
+ Region &CurRegion = Context.CurRegion;
+
+ TerminatorInst *TI = BB.getTerminator();
+
+ // Return instructions are only valid if the region is the top level region.
+ if (isa<ReturnInst>(TI) && !CurRegion.getExit() && TI->getNumOperands() == 0)
+ return true;
+
+ Value *Condition = getConditionFromTerminator(TI);
+
+ if (!Condition)
+ return invalid<ReportInvalidTerminator>(Context, /*Assert=*/true, &BB);
+
+ // UndefValue is not allowed as condition.
+ if (isa<UndefValue>(Condition))
+ return invalid<ReportUndefCond>(Context, /*Assert=*/true, TI, &BB);
+
+ // Constant conditions are always affine.
+ if (isa<Constant>(Condition))
+ return true;
+
+ if (BranchInst *BI = dyn_cast<BranchInst>(TI))
+ return isValidBranch(BB, BI, Condition, Context);
+
+ SwitchInst *SI = dyn_cast<SwitchInst>(TI);
+ assert(SI && "Terminator was neither branch nor switch");
+
+ return isValidSwitch(BB, SI, Condition, Context);
+}
+
bool ScopDetection::isValidCallInst(CallInst &CI) {
if (CI.doesNotReturn())
return false;
Modified: polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp Mon Sep 28 04:33:22 2015
@@ -141,18 +141,18 @@ bool ReportCFG::classof(const RejectReas
}
//===----------------------------------------------------------------------===//
-// ReportNonBranchTerminator.
+// ReportInvalidTerminator.
-std::string ReportNonBranchTerminator::getMessage() const {
- return ("Non branch instruction terminates BB: " + BB->getName()).str();
+std::string ReportInvalidTerminator::getMessage() const {
+ return ("Invalid instruction terminates BB: " + BB->getName()).str();
}
-const DebugLoc &ReportNonBranchTerminator::getDebugLoc() const {
+const DebugLoc &ReportInvalidTerminator::getDebugLoc() const {
return BB->getTerminator()->getDebugLoc();
}
-bool ReportNonBranchTerminator::classof(const RejectReason *RR) {
- return RR->getKind() == rrkNonBranchTerminator;
+bool ReportInvalidTerminator::classof(const RejectReason *RR) {
+ return RR->getKind() == rrkInvalidTerminator;
}
//===----------------------------------------------------------------------===//
Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Mon Sep 28 04:33:22 2015
@@ -914,8 +914,20 @@ partitionSetParts(__isl_take isl_set *S,
return std::make_pair(UnboundedParts, BoundedParts);
}
+/// @brief Set the dimension Ids from @p From in @p To.
+static __isl_give isl_set *setDimensionIds(__isl_keep isl_set *From,
+ __isl_take isl_set *To) {
+ for (unsigned u = 0, e = isl_set_n_dim(From); u < e; u++) {
+ isl_id *DimId = isl_set_get_dim_id(From, isl_dim_set, u);
+ To = isl_set_set_dim_id(To, isl_dim_set, u, DimId);
+ }
+ return To;
+}
+
+/// @brief Create the conditions under which @p L @p Pred @p R is true.
static __isl_give isl_set *buildConditionSet(ICmpInst::Predicate Pred,
- isl_pw_aff *L, isl_pw_aff *R) {
+ __isl_take isl_pw_aff *L,
+ __isl_take isl_pw_aff *R) {
switch (Pred) {
case ICmpInst::ICMP_EQ:
return isl_pw_aff_eq_set(L, R);
@@ -942,21 +954,82 @@ static __isl_give isl_set *buildConditio
}
}
-/// @brief Build the conditions sets for the branch @p BI in the @p Domain.
+/// @brief Create the conditions under which @p L @p Pred @p R is true.
+///
+/// Helper function that will make sure the dimensions of the result have the
+/// same isl_id's as the @p Domain.
+static __isl_give isl_set *buildConditionSet(ICmpInst::Predicate Pred,
+ __isl_take isl_pw_aff *L,
+ __isl_take isl_pw_aff *R,
+ __isl_keep isl_set *Domain) {
+ isl_set *ConsequenceCondSet = buildConditionSet(Pred, L, R);
+ return setDimensionIds(Domain, ConsequenceCondSet);
+}
+
+/// @brief Build the conditions sets for the switch @p SI in the @p Domain.
+///
+/// This will fill @p ConditionSets with the conditions under which control
+/// will be moved from @p SI to its successors. Hence, @p ConditionSets will
+/// have as many elements as @p SI has successors.
+static void
+buildConditionSets(Scop &S, SwitchInst *SI, Loop *L, __isl_keep isl_set *Domain,
+ SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
+
+ Value *Condition = getConditionFromTerminator(SI);
+ assert(Condition && "No condition for switch");
+
+ ScalarEvolution &SE = *S.getSE();
+ BasicBlock *BB = SI->getParent();
+ isl_pw_aff *LHS, *RHS;
+ LHS = S.getPwAff(SE.getSCEVAtScope(Condition, L), BB);
+
+ unsigned NumSuccessors = SI->getNumSuccessors();
+ ConditionSets.resize(NumSuccessors);
+ for (auto &Case : SI->cases()) {
+ unsigned Idx = Case.getSuccessorIndex();
+ ConstantInt *CaseValue = Case.getCaseValue();
+
+ RHS = S.getPwAff(SE.getSCEV(CaseValue), BB);
+ isl_set *CaseConditionSet =
+ buildConditionSet(ICmpInst::ICMP_EQ, isl_pw_aff_copy(LHS), RHS, Domain);
+ ConditionSets[Idx] = isl_set_coalesce(
+ isl_set_intersect(CaseConditionSet, isl_set_copy(Domain)));
+ }
+
+ assert(ConditionSets[0] == nullptr && "Default condition set was set");
+ isl_set *ConditionSetUnion = isl_set_copy(ConditionSets[1]);
+ for (unsigned u = 2; u < NumSuccessors; u++)
+ ConditionSetUnion =
+ isl_set_union(ConditionSetUnion, isl_set_copy(ConditionSets[u]));
+ ConditionSets[0] = setDimensionIds(
+ Domain, isl_set_subtract(isl_set_copy(Domain), ConditionSetUnion));
+
+ S.markAsOptimized();
+ isl_pw_aff_free(LHS);
+}
+
+/// @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 BI to its successors. Hence, @p ConditionSets will
-/// have as many elements as @p BI has successors.
+/// 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, BranchInst *BI, Loop *L, __isl_keep isl_set *Domain,
+buildConditionSets(Scop &S, TerminatorInst *TI, Loop *L,
+ __isl_keep isl_set *Domain,
SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
- if (BI->isUnconditional()) {
+ 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 = BI->getCondition();
+ Value *Condition = getConditionFromTerminator(TI);
+ assert(Condition && "No condition for Terminator");
isl_set *ConsequenceCondSet = nullptr;
if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
@@ -970,17 +1043,12 @@ buildConditionSets(Scop &S, BranchInst *
"Condition of exiting branch was neither constant nor ICmp!");
ScalarEvolution &SE = *S.getSE();
- BasicBlock *BB = BI->getParent();
+ BasicBlock *BB = TI->getParent();
isl_pw_aff *LHS, *RHS;
LHS = S.getPwAff(SE.getSCEVAtScope(ICond->getOperand(0), L), BB);
RHS = S.getPwAff(SE.getSCEVAtScope(ICond->getOperand(1), L), BB);
- ConsequenceCondSet = buildConditionSet(ICond->getPredicate(), LHS, RHS);
-
- for (unsigned u = 0, e = isl_set_n_dim(Domain); u < e; u++) {
- isl_id *DimId = isl_set_get_dim_id(Domain, isl_dim_set, u);
- ConsequenceCondSet =
- isl_set_set_dim_id(ConsequenceCondSet, isl_dim_set, u, DimId);
- }
+ ConsequenceCondSet =
+ buildConditionSet(ICond->getPredicate(), LHS, RHS, Domain);
}
assert(ConsequenceCondSet);
@@ -1551,13 +1619,13 @@ static inline BasicBlock *getRegionNodeB
}
/// @brief Return the @p idx'th block that is executed after @p RN.
-static inline BasicBlock *getRegionNodeSuccessor(RegionNode *RN, BranchInst *BI,
- unsigned idx) {
+static inline BasicBlock *
+getRegionNodeSuccessor(RegionNode *RN, TerminatorInst *TI, unsigned idx) {
if (RN->isSubRegion()) {
assert(idx == 0);
return RN->getNodeAs<Region>()->getExit();
}
- return BI->getSuccessor(idx);
+ return TI->getSuccessor(idx);
}
/// @brief Return the smallest loop surrounding @p RN.
@@ -1681,20 +1749,20 @@ void Scop::buildDomainsWithBranchConstra
// node. If it is a non-affine subregion we will always execute the single
// exit node, hence the single entry node domain is the condition set. For
// basic blocks we use the helper function buildConditionSets.
- SmallVector<isl_set *, 2> ConditionSets;
- BranchInst *BI = cast<BranchInst>(TI);
+ SmallVector<isl_set *, 8> ConditionSets;
if (RN->isSubRegion())
ConditionSets.push_back(isl_set_copy(Domain));
else
- buildConditionSets(*this, BI, BBLoop, Domain, ConditionSets);
+ buildConditionSets(*this, TI, BBLoop, Domain, ConditionSets);
// Now iterate over the successors and set their initial domain based on
// their condition set. We skip back edges here and have to be careful when
// we leave a loop not to keep constraints over a dimension that doesn't
// exist anymore.
+ assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size());
for (unsigned u = 0, e = ConditionSets.size(); u < e; u++) {
- BasicBlock *SuccBB = getRegionNodeSuccessor(RN, BI, u);
isl_set *CondSet = ConditionSets[u];
+ BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u);
// Skip back edges.
if (DT.dominates(SuccBB, BB)) {
@@ -1915,13 +1983,14 @@ void Scop::addLoopBoundsToHeaderDomain(L
isl_set *LatchBBDom = DomainMap[LatchBB];
isl_set *BackedgeCondition = nullptr;
- BranchInst *BI = cast<BranchInst>(LatchBB->getTerminator());
- if (BI->isUnconditional())
+ TerminatorInst *TI = LatchBB->getTerminator();
+ BranchInst *BI = dyn_cast<BranchInst>(TI);
+ if (BI && BI->isUnconditional())
BackedgeCondition = isl_set_copy(LatchBBDom);
else {
- SmallVector<isl_set *, 2> ConditionSets;
+ SmallVector<isl_set *, 8> ConditionSets;
int idx = BI->getSuccessor(0) != HeaderBB;
- buildConditionSets(*this, BI, L, LatchBBDom, ConditionSets);
+ buildConditionSets(*this, TI, L, LatchBBDom, ConditionSets);
// Free the non back edge condition set as we do not need it.
isl_set_free(ConditionSets[1 - idx]);
Modified: polly/trunk/lib/CodeGen/BlockGenerators.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/BlockGenerators.cpp?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/BlockGenerators.cpp (original)
+++ polly/trunk/lib/CodeGen/BlockGenerators.cpp Mon Sep 28 04:33:22 2015
@@ -1074,15 +1074,13 @@ void RegionGenerator::copyStmt(ScopStmt
continue;
}
- BranchInst *BI = cast<BranchInst>(TI);
-
Instruction *BICopy = BBCopy->getTerminator();
ValueMapT &RegionMap = RegionMaps[BBCopy];
RegionMap.insert(BlockMap.begin(), BlockMap.end());
Builder.SetInsertPoint(BICopy);
- copyInstScalar(Stmt, BI, RegionMap, LTS);
+ copyInstScalar(Stmt, TI, RegionMap, LTS);
BICopy->eraseFromParent();
}
Modified: polly/trunk/lib/Support/ScopHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/ScopHelper.cpp?rev=248701&r1=248700&r2=248701&view=diff
==============================================================================
--- polly/trunk/lib/Support/ScopHelper.cpp (original)
+++ polly/trunk/lib/Support/ScopHelper.cpp Mon Sep 28 04:33:22 2015
@@ -345,3 +345,17 @@ bool polly::isErrorBlock(BasicBlock &BB)
return false;
}
+
+Value *polly::getConditionFromTerminator(TerminatorInst *TI) {
+ if (BranchInst *BR = dyn_cast<BranchInst>(TI)) {
+ if (BR->isUnconditional())
+ return ConstantInt::getTrue(Type::getInt1Ty(TI->getContext()));
+
+ return BR->getCondition();
+ }
+
+ if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
+ return SI->getCondition();
+
+ return nullptr;
+}
Added: polly/trunk/test/Isl/CodeGen/non-affine-switch.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/non-affine-switch.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/non-affine-switch.ll (added)
+++ polly/trunk/test/Isl/CodeGen/non-affine-switch.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,67 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-no-early-exit \
+; RUN: -S -polly-codegen < %s | FileCheck %s
+;
+; void f(int *A, int N) {
+; for (int i = 0; i < N; i++)
+; switch (A[i]) {
+; case 0:
+; A[i] += 1;
+; break;
+; case 1:
+; A[i] += 2;
+; break;
+; }
+; }
+;
+; CHECK: polly.stmt.for.body:
+; CHECK: %scevgep = getelementptr i32, i32* %A, i64 %polly.indvar
+; CHECK: %tmp1_p_scalar_ = load i32, i32* %scevgep, align 4
+; CHECK: switch i32 %tmp1_p_scalar_, label %polly.stmt.sw.epilog.exit [
+; CHECK: i32 0, label %polly.stmt.sw.bb
+; CHECK: i32 1, label %polly.stmt.sw.bb.3
+; CHECK: ]
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp1 = load i32, i32* %arrayidx, align 4
+ switch i32 %tmp1, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb.3
+ ]
+
+sw.bb: ; preds = %for.body
+ %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp2 = load i32, i32* %arrayidx2, align 4
+ %add = add nsw i32 %tmp2, 1
+ store i32 %add, i32* %arrayidx2, align 4
+ br label %sw.epilog
+
+sw.bb.3: ; preds = %for.body
+ %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp3 = load i32, i32* %arrayidx5, align 4
+ %add6 = add nsw i32 %tmp3, 2
+ store i32 %add6, i32* %arrayidx5, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.bb.3, %sw.bb, %for.body
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
Added: polly/trunk/test/Isl/CodeGen/switch-in-non-affine-region.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/switch-in-non-affine-region.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/switch-in-non-affine-region.ll (added)
+++ polly/trunk/test/Isl/CodeGen/switch-in-non-affine-region.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,77 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-no-early-exit \
+; RUN: -S -polly-codegen < %s | FileCheck %s
+;
+; void f(int *A, int N) {
+; for (int i = 0; i < N; i++)
+; if (A[i])
+; switch (i % 4) {
+; case 0:
+; A[i] += 1;
+; break;
+; case 1:
+; A[i] += 2;
+; break;
+; }
+; }
+;
+; CHECK: polly.stmt.if.then:
+; CHECK: %1 = trunc i64 %polly.indvar to i32
+; CHECK: %p_rem = srem i32 %1, 4
+; CHECK: switch i32 %p_rem, label %polly.stmt.sw.epilog [
+; CHECK: i32 0, label %polly.stmt.sw.bb
+; CHECK: i32 1, label %polly.stmt.sw.bb.3
+; CHECK: ]
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp1 = load i32, i32* %arrayidx, align 4
+ %tobool = icmp eq i32 %tmp1, 0
+ br i1 %tobool, label %if.end, label %if.then
+
+if.then: ; preds = %for.body
+ %tmp2 = trunc i64 %indvars.iv to i32
+ %rem = srem i32 %tmp2, 4
+ switch i32 %rem, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb.3
+ ]
+
+sw.bb: ; preds = %if.then
+ %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp3 = load i32, i32* %arrayidx2, align 4
+ %add = add nsw i32 %tmp3, 1
+ store i32 %add, i32* %arrayidx2, align 4
+ br label %sw.epilog
+
+sw.bb.3: ; preds = %if.then
+ %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp4 = load i32, i32* %arrayidx5, align 4
+ %add6 = add nsw i32 %tmp4, 2
+ store i32 %add6, i32* %arrayidx5, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.bb.3, %sw.bb, %if.then
+ br label %if.end
+
+if.end: ; preds = %for.body, %sw.epilog
+ br label %for.inc
+
+for.inc: ; preds = %if.end
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
Added: polly/trunk/test/ScopInfo/switch-1.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/switch-1.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/switch-1.ll (added)
+++ polly/trunk/test/ScopInfo/switch-1.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,111 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void f(int *A, int N) {
+; for (int i = 0; i < N; i++)
+; switch (i % 4) {
+; case 0:
+; break;
+; case 1:
+; A[i] += 1;
+; break;
+; case 2:
+; A[i] += 2;
+; break;
+; case 3:
+; A[i] += 3;
+; break;
+; }
+; }
+;
+; CHECK: Statements {
+; CHECK: Stmt_sw_bb_6
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_6[i0] : exists (e0 = floor((-3 + i0)/4): 4e0 = -3 + i0 and i0 >= 0 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_6[i0] -> [i0, 0] };
+; CHECK: Stmt_sw_bb_2
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_2[i0] : exists (e0 = floor((-2 + i0)/4): 4e0 = -2 + i0 and i0 >= 2 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_2[i0] -> [i0, 1] };
+; CHECK: Stmt_sw_bb_1
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_1[i0] : exists (e0 = floor((-1 + i0)/4): 4e0 = -1 + i0 and i0 >= 1 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_1[i0] -> [i0, 2] };
+; CHECK: }
+;
+;
+; AST: if (1)
+;
+; AST: {
+; AST: for (int c0 = 1; c0 < N - 2; c0 += 4) {
+; AST: Stmt_sw_bb_1(c0);
+; AST: Stmt_sw_bb_2(c0 + 1);
+; AST: Stmt_sw_bb_6(c0 + 2);
+; AST: }
+; AST: if (N >= 2)
+; AST: if (N % 4 >= 2) {
+; AST: Stmt_sw_bb_1(-(N % 4) + N + 1);
+; AST: if ((N - 3) % 4 == 0)
+; AST: Stmt_sw_bb_2(N - 1);
+; AST: }
+; AST: }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %tmp1 = trunc i64 %indvars.iv to i32
+ %rem = srem i32 %tmp1, 4
+ switch i32 %rem, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb.1
+ i32 2, label %sw.bb.2
+ i32 3, label %sw.bb.6
+ ]
+
+sw.bb: ; preds = %for.body
+ br label %sw.epilog
+
+sw.bb.1: ; preds = %for.body
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp2 = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %tmp2, 1
+ store i32 %add, i32* %arrayidx, align 4
+ br label %sw.epilog
+
+sw.bb.2: ; preds = %for.body
+ %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp3 = load i32, i32* %arrayidx4, align 4
+ %add5 = add nsw i32 %tmp3, 2
+ store i32 %add5, i32* %arrayidx4, align 4
+ br label %sw.epilog
+
+sw.bb.6: ; preds = %for.body
+ %arrayidx8 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp4 = load i32, i32* %arrayidx8, align 4
+ %add9 = add nsw i32 %tmp4, 3
+ store i32 %add9, i32* %arrayidx8, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.bb.6, %sw.bb.2, %sw.bb.1, %sw.bb, %for.body
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
Added: polly/trunk/test/ScopInfo/switch-2.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/switch-2.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/switch-2.ll (added)
+++ polly/trunk/test/ScopInfo/switch-2.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,98 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void f(int *A, int N) {
+; for (int i = 0; i < N; i++)
+; switch (i % 4) {
+; case 0:
+; A[i] += 1;
+; break;
+; case 1:
+; break;
+; case 2:
+; A[i] += 2;
+; break;
+; case 3:
+; break;
+; }
+; }
+;
+; CHECK: Statements {
+; CHECK-NOT: Stmt_sw_bb1
+; CHECK: Stmt_sw_bb_2
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_2[i0] : exists (e0 = floor((-2 + i0)/4): 4e0 = -2 + i0 and i0 >= 2 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_2[i0] -> [i0, 0] };
+; CHECK-NOT: Stmt_sw_bb1
+; CHECK: Stmt_sw_bb
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb[i0] : exists (e0 = floor((i0)/4): 4e0 = i0 and i0 >= 0 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb[i0] -> [i0, 1] };
+; CHECK-NOT: Stmt_sw_bb1
+; CHECK: }
+;
+; AST: if (1)
+;
+; AST: for (int c0 = 0; c0 < N; c0 += 4) {
+; AST: Stmt_sw_bb(c0);
+; AST: if (N >= c0 + 3)
+; AST: Stmt_sw_bb_2(c0 + 2);
+; AST: }
+;
+; AST: else
+; AST: { /* original code */ }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %tmp1 = trunc i64 %indvars.iv to i32
+ %rem = srem i32 %tmp1, 4
+ switch i32 %rem, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb.1
+ i32 2, label %sw.bb.2
+ i32 3, label %sw.bb.6
+ ]
+
+sw.bb: ; preds = %for.body
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp2 = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %tmp2, 1
+ store i32 %add, i32* %arrayidx, align 4
+ br label %sw.epilog
+
+sw.bb.1: ; preds = %for.body
+ br label %sw.epilog
+
+sw.bb.2: ; preds = %for.body
+ %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp3 = load i32, i32* %arrayidx4, align 4
+ %add5 = add nsw i32 %tmp3, 2
+ store i32 %add5, i32* %arrayidx4, align 4
+ br label %sw.epilog
+
+sw.bb.6: ; preds = %for.body
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.bb.6, %sw.bb.2, %sw.bb.1, %sw.bb, %for.body
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
Added: polly/trunk/test/ScopInfo/switch-3.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/switch-3.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/switch-3.ll (added)
+++ polly/trunk/test/ScopInfo/switch-3.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,119 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void f(int *A, int N) {
+; for (int i = 0; i < N; i++)
+; switch (i % 4) {
+; case 0:
+; A[i] += 1;
+; case 1:
+; A[i] += 2;
+; break;
+; case 2:
+; A[i] += 3;
+; case 3:
+; A[i] += 4;
+; break;
+; }
+; }
+;
+; CHECK: Statements {
+; CHECK: Stmt_sw_bb_5
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_5[i0] : exists (e0 = floor((-2 + i0)/4): 4e0 = -2 + i0 and i0 >= 2 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_5[i0] -> [i0, 0] };
+; CHECK: Stmt_sw_bb_9
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_9[i0] : exists (e0 = floor((i0)/4): i0 >= 0 and i0 <= -1 + N and 4e0 >= -3 + i0 and 4e0 <= -2 + i0) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_9[i0] -> [i0, 1] };
+; CHECK: Stmt_sw_bb
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb[i0] : exists (e0 = floor((i0)/4): 4e0 = i0 and i0 >= 0 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb[i0] -> [i0, 2] };
+; CHECK: Stmt_sw_bb_1
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_1[i0] : exists (e0 = floor((2 + i0)/4): i0 >= 0 and i0 <= -1 + N and 4e0 >= -1 + i0 and 4e0 <= i0) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_1[i0] -> [i0, 3] };
+; CHECK: }
+;
+; AST: if (1)
+;
+; AST: for (int c0 = 0; c0 < N; c0 += 1) {
+; AST: if ((c0 - 2) % 4 == 0)
+; AST: Stmt_sw_bb_5(c0);
+; AST: if (c0 % 4 >= 2) {
+; AST: Stmt_sw_bb_9(c0);
+; AST: } else {
+; AST: if (c0 % 4 == 0)
+; AST: Stmt_sw_bb(c0);
+; AST: Stmt_sw_bb_1(c0);
+; AST: }
+; AST: }
+;
+; AST: else
+; AST: { /* original code */ }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %tmp1 = trunc i64 %indvars.iv to i32
+ %rem = srem i32 %tmp1, 4
+ switch i32 %rem, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb.1
+ i32 2, label %sw.bb.5
+ i32 3, label %sw.bb.9
+ ]
+
+sw.bb: ; preds = %for.body
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp2 = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %tmp2, 1
+ store i32 %add, i32* %arrayidx, align 4
+ br label %sw.bb.1
+
+sw.bb.1: ; preds = %sw.bb, %for.body
+ %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp3 = load i32, i32* %arrayidx3, align 4
+ %add4 = add nsw i32 %tmp3, 2
+ store i32 %add4, i32* %arrayidx3, align 4
+ br label %sw.epilog
+
+sw.bb.5: ; preds = %for.body
+ %arrayidx7 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp4 = load i32, i32* %arrayidx7, align 4
+ %add8 = add nsw i32 %tmp4, 3
+ store i32 %add8, i32* %arrayidx7, align 4
+ br label %sw.bb.9
+
+sw.bb.9: ; preds = %sw.bb.5, %for.body
+ %arrayidx11 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp5 = load i32, i32* %arrayidx11, align 4
+ %add12 = add nsw i32 %tmp5, 4
+ store i32 %add12, i32* %arrayidx11, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.bb.9, %sw.bb.1, %for.body
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
Added: polly/trunk/test/ScopInfo/switch-4.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/switch-4.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/switch-4.ll (added)
+++ polly/trunk/test/ScopInfo/switch-4.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,143 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void f(int *A, int N) {
+; for (int i = 0; i < N; i++)
+; switch (i % 4) {
+; case 0:
+; A[i] += 1;
+; break;
+; case 1:
+; A[i] += 2;
+; break;
+; case 2:
+; A[i] += 3;
+; break;
+; case 3:
+; A[i] += 4;
+; break;
+; default:
+; A[i - 1] += A[i + 1];
+; }
+; }
+;
+; CHECK: Statements {
+; CHECK: Stmt_sw_bb_9
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_9[i0] : exists (e0 = floor((-3 + i0)/4): 4e0 = -3 + i0 and i0 >= 0 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_9[i0] -> [i0, 0] };
+; CHECK: Stmt_sw_bb_5
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_5[i0] : exists (e0 = floor((-2 + i0)/4): 4e0 = -2 + i0 and i0 >= 2 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_5[i0] -> [i0, 1] };
+; CHECK: Stmt_sw_bb_1
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_1[i0] : exists (e0 = floor((-1 + i0)/4): 4e0 = -1 + i0 and i0 >= 1 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb_1[i0] -> [i0, 2] };
+; CHECK: Stmt_sw_bb
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb[i0] : exists (e0 = floor((i0)/4): 4e0 = i0 and i0 >= 0 and i0 <= -1 + N) };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_sw_bb[i0] -> [i0, 3] };
+; CHECK: Stmt_sw_default
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_default[i0] : 1 = 0 };
+; CHECK: }
+;
+; AST: if (1)
+;
+; AST: {
+; AST: for (int c0 = 0; c0 < N - 3; c0 += 4) {
+; AST: Stmt_sw_bb(c0);
+; AST: Stmt_sw_bb_1(c0 + 1);
+; AST: Stmt_sw_bb_5(c0 + 2);
+; AST: Stmt_sw_bb_9(c0 + 3);
+; AST: }
+; AST: if (N >= 1)
+; AST: if (N % 4 >= 1) {
+; AST: Stmt_sw_bb(-((N - 1) % 4) + N - 1);
+; AST: if (N % 4 >= 2) {
+; AST: Stmt_sw_bb_1(-((N - 1) % 4) + N);
+; AST: if ((N - 3) % 4 == 0)
+; AST: Stmt_sw_bb_5(N - 1);
+; AST: }
+; AST: }
+; AST: }
+;
+; AST: else
+; AST: { /* original code */ }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %tmp3 = trunc i64 %indvars.iv to i32
+ %rem = srem i32 %tmp3, 4
+ switch i32 %rem, label %sw.default [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb.1
+ i32 2, label %sw.bb.5
+ i32 3, label %sw.bb.9
+ ]
+
+sw.bb: ; preds = %for.body
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp4 = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %tmp4, 1
+ store i32 %add, i32* %arrayidx, align 4
+ br label %sw.epilog
+
+sw.bb.1: ; preds = %for.body
+ %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp5 = load i32, i32* %arrayidx3, align 4
+ %add4 = add nsw i32 %tmp5, 2
+ store i32 %add4, i32* %arrayidx3, align 4
+ br label %sw.epilog
+
+sw.bb.5: ; preds = %for.body
+ %arrayidx7 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp6 = load i32, i32* %arrayidx7, align 4
+ %add8 = add nsw i32 %tmp6, 3
+ store i32 %add8, i32* %arrayidx7, align 4
+ br label %sw.epilog
+
+sw.bb.9: ; preds = %for.body
+ %arrayidx11 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp7 = load i32, i32* %arrayidx11, align 4
+ %add12 = add nsw i32 %tmp7, 4
+ store i32 %add12, i32* %arrayidx11, align 4
+ br label %sw.epilog
+
+sw.default: ; preds = %for.body
+ %tmp8 = add nuw nsw i64 %indvars.iv, 1
+ %arrayidx15 = getelementptr inbounds i32, i32* %A, i64 %tmp8
+ %tmp9 = load i32, i32* %arrayidx15, align 4
+ %tmp10 = add nsw i64 %indvars.iv, -1
+ %arrayidx17 = getelementptr inbounds i32, i32* %A, i64 %tmp10
+ %tmp11 = load i32, i32* %arrayidx17, align 4
+ %add18 = add nsw i32 %tmp11, %tmp9
+ store i32 %add18, i32* %arrayidx17, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.default, %sw.bb.9, %sw.bb.5, %sw.bb.1, %sw.bb
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
Added: polly/trunk/test/ScopInfo/switch-5.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/switch-5.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/switch-5.ll (added)
+++ polly/trunk/test/ScopInfo/switch-5.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,74 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void f(int *A, int *B, int N) {
+; for (int i = 0; i < N; i++) {
+; A[i]++;
+; switch (N) {
+; case 0:
+; B[i]++;
+; break;
+; default:
+; return;
+; }
+; }
+; }
+;
+; CHECK: Statements {
+; CHECK: Stmt_for_body
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_for_body[0] : N >= 1 };
+; CHECK: Schedule :=
+; CHECK: [N] -> { Stmt_for_body[i0] -> [0, 0] };
+; CHECK: Stmt_sw_bb
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb[i0] : 1 = 0 };
+; CHECK: }
+;
+; AST: if (N >= 1)
+; AST: Stmt_for_body(0);
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32* %B, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.body: ; preds = %for.cond
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp1 = load i32, i32* %arrayidx, align 4
+ %inc = add nsw i32 %tmp1, 1
+ store i32 %inc, i32* %arrayidx, align 4
+ switch i32 %N, label %sw.default [
+ i32 0, label %sw.bb
+ ]
+
+sw.bb: ; preds = %for.body
+ %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
+ %tmp2 = load i32, i32* %arrayidx2, align 4
+ %inc3 = add nsw i32 %tmp2, 1
+ store i32 %inc3, i32* %arrayidx2, align 4
+ br label %sw.epilog
+
+sw.default: ; preds = %for.body
+ br label %for.end
+
+sw.epilog: ; preds = %sw.bb
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end.loopexit: ; preds = %for.cond
+ br label %for.end
+
+for.end: ; preds = %for.end.loopexit, %sw.default
+ ret void
+}
Added: polly/trunk/test/ScopInfo/switch-6.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/switch-6.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/switch-6.ll (added)
+++ polly/trunk/test/ScopInfo/switch-6.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,118 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void f(int *A, int N) {
+; for (int i = 0; i < N; i++) {
+; switch (i) {
+; case 0:
+; A[i] += 1;
+; break;
+; case 1:
+; A[i] += 2;
+; break;
+; case 2:
+; A[i] += 3;
+; break;
+; case 3:
+; A[i] += 4;
+; break;
+; default:;
+; }
+; }
+; }
+;
+; CHECK: Statements {
+; CHECK: Stmt_sw_bb_9
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_9[3] : N >= 4 };
+; CHECK: Stmt_sw_bb_5
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_5[2] : N >= 3 };
+; CHECK: Stmt_sw_bb_1
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb_1[1] : N >= 2 };
+; CHECK: Stmt_sw_bb
+; CHECK: Domain :=
+; CHECK: [N] -> { Stmt_sw_bb[0] : N >= 1 };
+; CHECK: }
+;
+; AST: if (1)
+;
+; AST: if (N >= 1) {
+; AST: Stmt_sw_bb(0);
+; AST: if (N >= 2) {
+; AST: Stmt_sw_bb_1(1);
+; AST: if (N >= 3) {
+; AST: Stmt_sw_bb_5(2);
+; AST: if (N >= 4)
+; AST: Stmt_sw_bb_9(3);
+; AST: }
+; AST: }
+; AST: }
+;
+; AST: else
+; AST: { /* original code */ }
+;
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %N) {
+entry:
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+ %cmp = icmp slt i64 %indvars.iv, %tmp
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %tmp1 = trunc i64 %indvars.iv to i32
+ switch i32 %tmp1, label %sw.default [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb.1
+ i32 2, label %sw.bb.5
+ i32 3, label %sw.bb.9
+ ]
+
+sw.bb: ; preds = %for.body
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp2 = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %tmp2, 1
+ store i32 %add, i32* %arrayidx, align 4
+ br label %sw.epilog
+
+sw.bb.1: ; preds = %for.body
+ %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp3 = load i32, i32* %arrayidx3, align 4
+ %add4 = add nsw i32 %tmp3, 2
+ store i32 %add4, i32* %arrayidx3, align 4
+ br label %sw.epilog
+
+sw.bb.5: ; preds = %for.body
+ %arrayidx7 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp4 = load i32, i32* %arrayidx7, align 4
+ %add8 = add nsw i32 %tmp4, 3
+ store i32 %add8, i32* %arrayidx7, align 4
+ br label %sw.epilog
+
+sw.bb.9: ; preds = %for.body
+ %arrayidx11 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp5 = load i32, i32* %arrayidx11, align 4
+ %add12 = add nsw i32 %tmp5, 4
+ store i32 %add12, i32* %arrayidx11, align 4
+ br label %sw.epilog
+
+sw.default: ; preds = %for.body
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.default, %sw.bb.9, %sw.bb.5, %sw.bb.1, %sw.bb
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
Added: polly/trunk/test/ScopInfo/switch-7.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/switch-7.ll?rev=248701&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/switch-7.ll (added)
+++ polly/trunk/test/ScopInfo/switch-7.ll Mon Sep 28 04:33:22 2015
@@ -0,0 +1,114 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-ast -analyze < %s | FileCheck %s --check-prefix=AST
+;
+; void f(int *A, int c, int N) {
+; switch (c) {
+; case -1: {
+; for (int j = N; j > 0; j--)
+; A[j] += A[j - 1];
+; break;
+; }
+; case 1: {
+; for (int j = 1; j <= N; j++)
+; A[j] += A[j - 1];
+; break;
+; }
+; }
+; }
+;
+; CHECK: Statements {
+; CHECK: Stmt_for_body_7
+; CHECK: Domain :=
+; CHECK: [c, N] -> { Stmt_for_body_7[i0] : c = 1 and i0 >= 0 and i0 <= -1 + N };
+; CHECK: Schedule :=
+; CHECK: [c, N] -> { Stmt_for_body_7[i0] -> [0, i0] };
+; CHECK: Stmt_for_body
+; CHECK: Domain :=
+; CHECK: [c, N] -> { Stmt_for_body[i0] : c = -1 and i0 >= 0 and i0 <= -1 + N };
+; CHECK: Schedule :=
+; CHECK: [c, N] -> { Stmt_for_body[i0] -> [1, i0] };
+; CHECK: }
+;
+; AST: if (1)
+;
+; AST: if (c == 1) {
+; AST: for (int c0 = 0; c0 < N; c0 += 1)
+; AST: Stmt_for_body_7(c0);
+; AST: } else if (c == -1)
+; AST: for (int c0 = 0; c0 < N; c0 += 1)
+; AST: Stmt_for_body(c0);
+;
+; AST: else
+; AST: { /* original code */ }
+;
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i32 %c, i32 %N) {
+entry:
+ br label %entry.split
+
+entry.split:
+ switch i32 %c, label %sw.epilog [
+ i32 -1, label %sw.bb
+ i32 1, label %sw.bb.3
+ ]
+
+sw.bb: ; preds = %entry
+ %tmp = sext i32 %N to i64
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %sw.bb
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ %tmp, %sw.bb ]
+ %j.0 = phi i32 [ %N, %sw.bb ], [ %dec, %for.inc ]
+ %cmp = icmp sgt i64 %indvars.iv, 0
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %sub = add nsw i32 %j.0, -1
+ %idxprom = sext i32 %sub to i64
+ %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom
+ %tmp6 = load i32, i32* %arrayidx, align 4
+ %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+ %tmp7 = load i32, i32* %arrayidx2, align 4
+ %add = add nsw i32 %tmp7, %tmp6
+ store i32 %add, i32* %arrayidx2, align 4
+ br label %for.inc
+
+for.inc: ; preds = %for.body
+ %dec = add nsw i32 %j.0, -1
+ %indvars.iv.next = add nsw i64 %indvars.iv, -1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ br label %sw.epilog
+
+sw.bb.3: ; preds = %entry
+ %tmp8 = sext i32 %N to i64
+ br label %for.cond.5
+
+for.cond.5: ; preds = %for.inc.14, %sw.bb.3
+ %indvars.iv3 = phi i64 [ %indvars.iv.next4, %for.inc.14 ], [ 1, %sw.bb.3 ]
+ %cmp6 = icmp sgt i64 %indvars.iv3, %tmp8
+ br i1 %cmp6, label %for.end.15, label %for.body.7
+
+for.body.7: ; preds = %for.cond.5
+ %tmp9 = add nsw i64 %indvars.iv3, -1
+ %arrayidx10 = getelementptr inbounds i32, i32* %A, i64 %tmp9
+ %tmp10 = load i32, i32* %arrayidx10, align 4
+ %arrayidx12 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv3
+ %tmp11 = load i32, i32* %arrayidx12, align 4
+ %add13 = add nsw i32 %tmp11, %tmp10
+ store i32 %add13, i32* %arrayidx12, align 4
+ br label %for.inc.14
+
+for.inc.14: ; preds = %for.body.7
+ %indvars.iv.next4 = add nuw nsw i64 %indvars.iv3, 1
+ br label %for.cond.5
+
+for.end.15: ; preds = %for.cond.5
+ br label %sw.epilog
+
+sw.epilog: ; preds = %for.end.15, %for.end, %entry
+ ret void
+}
More information about the llvm-commits
mailing list