From bacf5193cf55166fb8d00ba12cbec7a2bd035d2b Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Fri, 10 Aug 2007 00:33:50 +0000 Subject: [PATCH] ExitCondition and Induction variable are loop constraints not split condition constraints. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40977 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/LoopIndexSplit.cpp | 216 +++++++++++++++-------- 1 file changed, 145 insertions(+), 71 deletions(-) diff --git a/lib/Transforms/Scalar/LoopIndexSplit.cpp b/lib/Transforms/Scalar/LoopIndexSplit.cpp index 17bae1e4e25..887a730e623 100644 --- a/lib/Transforms/Scalar/LoopIndexSplit.cpp +++ b/lib/Transforms/Scalar/LoopIndexSplit.cpp @@ -53,46 +53,32 @@ namespace { 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 @@ namespace { 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 @@ namespace { ScalarEvolution *SE; DominatorTree *DT; SmallVector 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 @@ bool LoopIndexSplit::runOnLoop(Loop *IncomingLoop, LPPassManager &LPM) { SE = &getAnalysis(); DT = &getAnalysis(); + initialize(); + + findLoopConditionals(); + + if (!ExitCondition) + return false; + findSplitCondition(); if (SplitData.empty()) @@ -183,24 +196,24 @@ bool LoopIndexSplit::runOnLoop(Loop *IncomingLoop, LPPassManager &LPM) { /// 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(V); if (!I) - return false; + return; // Check if I is a phi node from loop header or not. if (PHINode *PN = dyn_cast(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 @@ bool LoopIndexSplit::SplitInfo::findIndVar(Value *V, Loop *L) { && isa(Op1)) { IndVar = PN; IndVarIncrement = I; - return true; + return; } } @@ -219,11 +232,66 @@ bool LoopIndexSplit::SplitInfo::findIndVar(Value *V, Loop *L) { && isa(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(ExitBlock->getTerminator()); + if (!BR || BR->isUnconditional()) + return; + + ICmpInst *CI = dyn_cast(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(SH1)) { + ExitValue = V0; + findIndVar(V1, L); + } + else if (SH1->isLoopInvariant(L) && isa(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 @@ void LoopIndexSplit::findSplitCondition() { continue; ICmpInst *CI = dyn_cast(BR->getCondition()); - if (!CI) + if (!CI || CI == ExitCondition) return; // If one operand is loop invariant and second operand is SCEVAddRecExpr @@ -260,14 +328,26 @@ void LoopIndexSplit::findSplitCondition() { if (SH0->isLoopInvariant(L) && isa(SH1)) { SD.SplitValue = V0; SD.SplitCondition = CI; - if (SD.findIndVar(V1, L)) - SplitData.push_back(SD); + if (PHINode *PN = dyn_cast(V1)) { + if (PN == IndVar) + SplitData.push_back(SD); + } + else if (Instruction *Insn = dyn_cast(V1)) { + if (IndVarIncrement && IndVarIncrement == Insn) + SplitData.push_back(SD); + } } else if (SH1->isLoopInvariant(L) && isa(SH0)) { SD.SplitValue = V1; SD.SplitCondition = CI; - if (SD.findIndVar(V0, L)) - SplitData.push_back(SD); + if (PHINode *PN = dyn_cast(V0)) { + if (PN == IndVar) + SplitData.push_back(SD); + } + else if (Instruction *Insn = dyn_cast(V0)) { + if (IndVarIncrement && IndVarIncrement == Insn) + SplitData.push_back(SD); + } } } } @@ -340,7 +420,7 @@ bool LoopIndexSplit::processOneIterationLoop(SplitInfo &SD, LPPassManager &LPM) 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 @@ bool LoopIndexSplit::processOneIterationLoop(SplitInfo &SD, LPPassManager &LPM) // 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 @@ bool LoopIndexSplit::safeHeader(SplitInfo &SD, BasicBlock *Header) { 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 @@ bool LoopIndexSplit::safeExitBlock(SplitInfo &SD, BasicBlock *ExitBlock) { 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 @@ bool LoopIndexSplit::safeExitBlock(SplitInfo &SD, BasicBlock *ExitBlock) { if ((PN = dyn_cast(Op0))) { if ((CI = dyn_cast(Op1))) - SD.IndVarIncrement = I; + IndVarIncrement = I; } else if ((PN = dyn_cast(Op1))) { if ((CI = dyn_cast(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 @@ bool LoopIndexSplit::safeExitBlock(SplitInfo &SD, BasicBlock *ExitBlock) { // Exit condition is OK if it compares loop invariant exit value, // which is checked below. else if (ICmpInst *EC = dyn_cast(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(Op0); - Instruction *Insn1 = dyn_cast(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 @@ unsigned LoopIndexSplit::findSplitCost(Loop *L, SplitInfo &SD) { } 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; }