[llvm-commits] [llvm] r40977 - /llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp
Devang Patel
dpatel at apple.com
Thu Aug 9 17:33:50 PDT 2007
Author: dpatel
Date: Thu Aug 9 19:33:50 2007
New Revision: 40977
URL: http://llvm.org/viewvc/llvm-project?rev=40977&view=rev
Log:
ExitCondition and Induction variable are loop constraints
not split condition constraints.
Modified:
llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp?rev=40977&r1=40976&r2=40977&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp Thu Aug 9 19:33:50 2007
@@ -53,46 +53,32 @@
class SplitInfo {
public:
- SplitInfo() : IndVar(NULL), SplitValue(NULL), ExitValue(NULL),
- SplitCondition(NULL), ExitCondition(NULL),
- IndVarIncrement(NULL) {}
+ SplitInfo() : SplitValue(NULL), SplitCondition(NULL) {}
- // Induction variable whose range is being split by this transformation.
- PHINode *IndVar;
-
// Induction variable's range is split at this value.
Value *SplitValue;
- // Induction variable's final loop exit value.
- Value *ExitValue;
-
// This compare instruction compares IndVar against SplitValue.
ICmpInst *SplitCondition;
- // Loop exit condition.
- ICmpInst *ExitCondition;
-
- Instruction *IndVarIncrement;
-
// Clear split info.
void clear() {
- IndVar = NULL;
SplitValue = NULL;
- ExitValue = NULL;
SplitCondition = NULL;
- ExitCondition = NULL;
- IndVarIncrement = NULL;
}
- /// Return true if V is a induction variable or induction variable's
- /// increment for loop L.
- bool findIndVar(Value *V, Loop *L);
};
-
+
private:
/// Find condition inside a loop that is suitable candidate for index split.
void findSplitCondition();
+ /// Find loop's exit condition.
+ void findLoopConditionals();
+
+ /// Return induction variable associated with value V.
+ void findIndVar(Value *V, Loop *L);
+
/// processOneIterationLoop - Current loop L contains compare instruction
/// that compares induction variable, IndVar, agains loop invariant. If
/// entire (i.e. meaningful) loop body is dominated by this compare
@@ -112,6 +98,13 @@
unsigned findSplitCost(Loop *L, SplitInfo &SD);
bool splitLoop(SplitInfo &SD);
+ void initialize() {
+ IndVar = NULL;
+ IndVarIncrement = NULL;
+ ExitCondition = NULL;
+ StartValue = ExitValue = NULL;
+ }
+
private:
// Current Loop.
@@ -119,6 +112,19 @@
ScalarEvolution *SE;
DominatorTree *DT;
SmallVector<SplitInfo, 4> SplitData;
+
+ // Induction variable whose range is being split by this transformation.
+ PHINode *IndVar;
+ Instruction *IndVarIncrement;
+
+ // Loop exit condition.
+ ICmpInst *ExitCondition;
+
+ // Induction variable's initial value.
+ Value *StartValue;
+
+ // Induction variable's final loop exit value.
+ Value *ExitValue;
};
char LoopIndexSplit::ID = 0;
@@ -137,6 +143,13 @@
SE = &getAnalysis<ScalarEvolution>();
DT = &getAnalysis<DominatorTree>();
+ initialize();
+
+ findLoopConditionals();
+
+ if (!ExitCondition)
+ return false;
+
findSplitCondition();
if (SplitData.empty())
@@ -183,24 +196,24 @@
/// Return true if V is a induction variable or induction variable's
/// increment for loop L.
-bool LoopIndexSplit::SplitInfo::findIndVar(Value *V, Loop *L) {
+void LoopIndexSplit::findIndVar(Value *V, Loop *L) {
Instruction *I = dyn_cast<Instruction>(V);
if (!I)
- return false;
+ return;
// Check if I is a phi node from loop header or not.
if (PHINode *PN = dyn_cast<PHINode>(V)) {
if (PN->getParent() == L->getHeader()) {
- IndVar = PN;
- return true;
+ IndVar = PN;
+ return;
}
}
// Check if I is a add instruction whose one operand is
// phi node from loop header and second operand is constant.
if (I->getOpcode() != Instruction::Add)
- return false;
+ return;
Value *Op0 = I->getOperand(0);
Value *Op1 = I->getOperand(1);
@@ -210,7 +223,7 @@
&& isa<ConstantInt>(Op1)) {
IndVar = PN;
IndVarIncrement = I;
- return true;
+ return;
}
}
@@ -219,11 +232,66 @@
&& isa<ConstantInt>(Op0)) {
IndVar = PN;
IndVarIncrement = I;
- return true;
+ return;
}
}
- return false;
+ return;
+}
+
+// Find loop's exit condition and associated induction variable.
+void LoopIndexSplit::findLoopConditionals() {
+
+ BasicBlock *ExitBlock = NULL;
+
+ for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
+ I != E; ++I) {
+ BasicBlock *BB = *I;
+ if (!L->isLoopExit(BB))
+ continue;
+ if (ExitBlock)
+ return;
+ ExitBlock = BB;
+ }
+
+ if (!ExitBlock)
+ return;
+
+ // If exit block's terminator is conditional branch inst then we have found
+ // exit condition.
+ BranchInst *BR = dyn_cast<BranchInst>(ExitBlock->getTerminator());
+ if (!BR || BR->isUnconditional())
+ return;
+
+ ICmpInst *CI = dyn_cast<ICmpInst>(BR->getCondition());
+ if (!CI)
+ return;
+
+ ExitCondition = CI;
+
+ // Exit condition's one operand is loop invariant exit value and second
+ // operand is SCEVAddRecExpr based on induction variable.
+ Value *V0 = CI->getOperand(0);
+ Value *V1 = CI->getOperand(1);
+
+ SCEVHandle SH0 = SE->getSCEV(V0);
+ SCEVHandle SH1 = SE->getSCEV(V1);
+
+ if (SH0->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH1)) {
+ ExitValue = V0;
+ findIndVar(V1, L);
+ }
+ else if (SH1->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH0)) {
+ ExitValue = V1;
+ findIndVar(V0, L);
+ }
+
+ if (!ExitValue || !IndVar)
+ ExitCondition = NULL;
+ else if (IndVar) {
+ BasicBlock *Preheader = L->getLoopPreheader();
+ StartValue = IndVar->getIncomingValueForBlock(Preheader);
+ }
}
/// Find condition inside a loop that is suitable candidate for index split.
@@ -246,7 +314,7 @@
continue;
ICmpInst *CI = dyn_cast<ICmpInst>(BR->getCondition());
- if (!CI)
+ if (!CI || CI == ExitCondition)
return;
// If one operand is loop invariant and second operand is SCEVAddRecExpr
@@ -260,14 +328,26 @@
if (SH0->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH1)) {
SD.SplitValue = V0;
SD.SplitCondition = CI;
- if (SD.findIndVar(V1, L))
- SplitData.push_back(SD);
+ if (PHINode *PN = dyn_cast<PHINode>(V1)) {
+ if (PN == IndVar)
+ SplitData.push_back(SD);
+ }
+ else if (Instruction *Insn = dyn_cast<Instruction>(V1)) {
+ if (IndVarIncrement && IndVarIncrement == Insn)
+ SplitData.push_back(SD);
+ }
}
else if (SH1->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH0)) {
SD.SplitValue = V1;
SD.SplitCondition = CI;
- if (SD.findIndVar(V0, L))
- SplitData.push_back(SD);
+ if (PHINode *PN = dyn_cast<PHINode>(V0)) {
+ if (PN == IndVar)
+ SplitData.push_back(SD);
+ }
+ else if (Instruction *Insn = dyn_cast<Instruction>(V0)) {
+ if (IndVarIncrement && IndVarIncrement == Insn)
+ SplitData.push_back(SD);
+ }
}
}
}
@@ -340,7 +420,7 @@
BasicBlock *Preheader = L->getLoopPreheader();
Instruction *Terminator = Header->getTerminator();
- Value *StartValue = SD.IndVar->getIncomingValueForBlock(Preheader);
+ StartValue = IndVar->getIncomingValueForBlock(Preheader);
// Replace split condition in header.
// Transform
@@ -349,14 +429,14 @@
// c1 = icmp uge i32 SplitValue, StartValue
// c2 = icmp ult i32 vSplitValue, ExitValue
// and i32 c1, c2
- bool SignedPredicate = SD.ExitCondition->isSignedPredicate();
+ bool SignedPredicate = ExitCondition->isSignedPredicate();
Instruction *C1 = new ICmpInst(SignedPredicate ?
ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE,
SD.SplitValue, StartValue, "lisplit",
Terminator);
Instruction *C2 = new ICmpInst(SignedPredicate ?
ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
- SD.SplitValue, SD.ExitValue, "lisplit",
+ SD.SplitValue, ExitValue, "lisplit",
Terminator);
Instruction *NSplitCond = BinaryOperator::createAnd(C1, C2, "lisplit",
Terminator);
@@ -413,11 +493,11 @@
continue;
// Induction variable is OK.
- if (I == SD.IndVar)
+ if (I == IndVar)
continue;
// Induction variable increment is OK.
- if (I == SD.IndVarIncrement)
+ if (I == IndVarIncrement)
continue;
// Terminator is also harmless.
@@ -444,11 +524,11 @@
continue;
// Induction variable increment is OK.
- if (SD.IndVarIncrement && SD.IndVarIncrement == I)
+ if (IndVarIncrement && IndVarIncrement == I)
continue;
// Check if I is induction variable increment instruction.
- if (!SD.IndVarIncrement && I->getOpcode() == Instruction::Add) {
+ if (!IndVarIncrement && I->getOpcode() == Instruction::Add) {
Value *Op0 = I->getOperand(0);
Value *Op1 = I->getOperand(1);
@@ -457,14 +537,14 @@
if ((PN = dyn_cast<PHINode>(Op0))) {
if ((CI = dyn_cast<ConstantInt>(Op1)))
- SD.IndVarIncrement = I;
+ IndVarIncrement = I;
} else
if ((PN = dyn_cast<PHINode>(Op1))) {
if ((CI = dyn_cast<ConstantInt>(Op0)))
- SD.IndVarIncrement = I;
+ IndVarIncrement = I;
}
- if (SD.IndVarIncrement && PN == SD.IndVar && CI->isOne())
+ if (IndVarIncrement && PN == IndVar && CI->isOne())
continue;
}
@@ -472,38 +552,17 @@
// Exit condition is OK if it compares loop invariant exit value,
// which is checked below.
else if (ICmpInst *EC = dyn_cast<ICmpInst>(I)) {
- ++BI;
- Instruction *N = BI;
- if (N == ExitBlock->getTerminator()) {
- SD.ExitCondition = EC;
+ if (EC == ExitCondition)
continue;
- }
}
+ if (I == ExitBlock->getTerminator())
+ continue;
+
// Otherwise we have instruction that may not be safe.
return false;
}
- // Check if Exit condition is comparing induction variable against
- // loop invariant value. If one operand is induction variable and
- // the other operand is loop invaraint then Exit condition is safe.
- if (SD.ExitCondition) {
- Value *Op0 = SD.ExitCondition->getOperand(0);
- Value *Op1 = SD.ExitCondition->getOperand(1);
-
- Instruction *Insn0 = dyn_cast<Instruction>(Op0);
- Instruction *Insn1 = dyn_cast<Instruction>(Op1);
-
- if (Insn0 && Insn0 == SD.IndVarIncrement)
- SD.ExitValue = Op1;
- else if (Insn1 && Insn1 == SD.IndVarIncrement)
- SD.ExitValue = Op0;
-
- SCEVHandle ValueSCEV = SE->getSCEV(SD.ExitValue);
- if (!ValueSCEV->isLoopInvariant(L))
- return false;
- }
-
// We could not find any reason to consider ExitBlock unsafe.
return true;
}
@@ -528,6 +587,21 @@
}
bool LoopIndexSplit::splitLoop(SplitInfo &SD) {
- // FIXME :)
+ // True loop is original loop. False loop is cloned loop.
+ //[*] Calculate True loop's new Exit Value in loop preheader.
+ // NewExitValue = min(SplitValue, ExitValue)
+ //[*] Calculate False loop's new Start Value in loop preheader.
+ // NewStartValue = min(SplitValue, TrueLoop.StartValue)
+ //[*] Split Exit Edge.
+ //[*] Clone loop. Avoid true destination of split condition and
+ // the blocks dominated by true destination.
+ //[*] True loops exit edge enters False loop.
+ //[*] Eliminate split condition's false branch from True loop.
+ // Update true loop dom info.
+ //[*] Update True loop's exit value using NewExitValue.
+ //[*] Update False loop's start value using NewStartValue.
+ //[*] Fix lack of true branch in False loop CFG.
+ // Update false loop dom info.
+ //[*] Update dom info in general.
return false;
}
More information about the llvm-commits
mailing list