aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
authorDevang Patel <dpatel@apple.com>2008-11-03 18:32:19 +0000
committerDevang Patel <dpatel@apple.com>2008-11-03 18:32:19 +0000
commit58d43d4a41b21085c063bdd21a2abb68056e2a6f (patch)
treedd922f06e11232bcc76f9501a809473504e55c57 /lib/Transforms
parent8f092252d3fe75064abe330e0e6f75e213f4ac06 (diff)
Turn floating point IVs into integer IVs where possible.
This allows SCEV users to effectively calculate trip count. LSR later on transforms back integer IVs to floating point IVs later on to avoid int-to-float casts inside the loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58625 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/Scalar/IndVarSimplify.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp
index 4dfd8b920b..56829bd60c 100644
--- a/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -95,6 +95,7 @@ namespace {
void DeleteTriviallyDeadInstructions(std::set<Instruction*> &Insts);
void OptimizeCanonicalIVType(Loop *L);
+ void HandleFloatingPointIV(Loop *L);
};
}
@@ -466,6 +467,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
// auxillary induction variables.
std::vector<std::pair<PHINode*, SCEVHandle> > IndVars;
+ HandleFloatingPointIV(L);
for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
PHINode *PN = cast<PHINode>(I);
if (PN->getType()->isInteger()) { // FIXME: when we have fast-math, enable!
@@ -718,3 +720,151 @@ void IndVarSimplify::OptimizeCanonicalIVType(Loop *L) {
Incr->eraseFromParent();
}
+/// HandleFloatingPointIV - If the loop has floating induction variable
+/// then insert corresponding integer induction variable if possible.
+void IndVarSimplify::HandleFloatingPointIV(Loop *L) {
+ BasicBlock *Header = L->getHeader();
+ SmallVector <PHINode *, 4> FPHIs;
+ Instruction *NonPHIInsn = NULL;
+
+ // Collect all floating point IVs first.
+ BasicBlock::iterator I = Header->begin();
+ while(true) {
+ if (!isa<PHINode>(I)) {
+ NonPHIInsn = I;
+ break;
+ }
+ PHINode *PH = cast<PHINode>(I);
+ if (PH->getType()->isFloatingPoint())
+ FPHIs.push_back(PH);
+ ++I;
+ }
+
+ for (SmallVector<PHINode *, 4>::iterator I = FPHIs.begin(), E = FPHIs.end();
+ I != E; ++I) {
+ PHINode *PH = *I;
+ unsigned IncomingEdge = L->contains(PH->getIncomingBlock(0));
+ unsigned BackEdge = IncomingEdge^1;
+
+ // Check incoming value.
+ ConstantFP *CZ = dyn_cast<ConstantFP>(PH->getIncomingValue(IncomingEdge));
+ if (!CZ) continue;
+ APFloat PHInit = CZ->getValueAPF();
+ if (!PHInit.isPosZero()) continue;
+
+ // Check IV increment.
+ BinaryOperator *Incr =
+ dyn_cast<BinaryOperator>(PH->getIncomingValue(BackEdge));
+ if (!Incr) continue;
+ if (Incr->getOpcode() != Instruction::Add) continue;
+ ConstantFP *IncrValue = NULL;
+ unsigned IncrVIndex = 1;
+ if (Incr->getOperand(1) == PH)
+ IncrVIndex = 0;
+ IncrValue = dyn_cast<ConstantFP>(Incr->getOperand(IncrVIndex));
+ if (!IncrValue) continue;
+ APFloat IVAPF = IncrValue->getValueAPF();
+ APFloat One = APFloat(IVAPF.getSemantics(), 1);
+ if (!IVAPF.bitwiseIsEqual(One)) continue;
+
+ // Check Incr uses.
+ Value::use_iterator IncrUse = Incr->use_begin();
+ Instruction *U1 = cast<Instruction>(IncrUse++);
+ if (IncrUse == Incr->use_end()) continue;
+ Instruction *U2 = cast<Instruction>(IncrUse++);
+ if (IncrUse != Incr->use_end()) continue;
+
+ // Find exict condition.
+ FCmpInst *EC = dyn_cast<FCmpInst>(U1);
+ if (!EC)
+ EC = dyn_cast<FCmpInst>(U2);
+ if (!EC) continue;
+ bool skip = false;
+ Instruction *Terminator = EC->getParent()->getTerminator();
+ for(Value::use_iterator ECUI = EC->use_begin(), ECUE = EC->use_end();
+ ECUI != ECUE; ++ECUI) {
+ Instruction *U = cast<Instruction>(ECUI);
+ if (U != Terminator) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip) continue;
+
+ // Find exit value.
+ ConstantFP *EV = NULL;
+ unsigned EVIndex = 1;
+ if (EC->getOperand(1) == Incr)
+ EVIndex = 0;
+ EV = dyn_cast<ConstantFP>(EC->getOperand(EVIndex));
+ if (!EV) continue;
+ APFloat EVAPF = EV->getValueAPF();
+ if (EVAPF.isNegative()) continue;
+
+ // Find corresponding integer exit value.
+ uint64_t integerVal = Type::Int32Ty->getPrimitiveSizeInBits();
+ bool isExact = false;
+ if (EVAPF.convertToInteger(&integerVal, 32, false, APFloat::rmTowardZero, &isExact)
+ != APFloat::opOK)
+ continue;
+ if (!isExact) continue;
+
+ // Find new predicate for integer comparison.
+ CmpInst::Predicate NewPred = CmpInst::BAD_ICMP_PREDICATE;
+ switch (EC->getPredicate()) {
+ case CmpInst::FCMP_OEQ:
+ case CmpInst::FCMP_UEQ:
+ NewPred = CmpInst::ICMP_EQ;
+ break;
+ case CmpInst::FCMP_OGT:
+ case CmpInst::FCMP_UGT:
+ NewPred = CmpInst::ICMP_UGT;
+ break;
+ case CmpInst::FCMP_OGE:
+ case CmpInst::FCMP_UGE:
+ NewPred = CmpInst::ICMP_UGE;
+ break;
+ case CmpInst::FCMP_OLT:
+ case CmpInst::FCMP_ULT:
+ NewPred = CmpInst::ICMP_ULT;
+ break;
+ case CmpInst::FCMP_OLE:
+ case CmpInst::FCMP_ULE:
+ NewPred = CmpInst::ICMP_ULE;
+ break;
+ default:
+ break;
+ }
+ if (NewPred == CmpInst::BAD_ICMP_PREDICATE) continue;
+
+ // Insert new integer induction variable.
+ SCEVExpander Rewriter(*SE, *LI);
+ PHINode *NewIV =
+ cast<PHINode>(Rewriter.getOrInsertCanonicalInductionVariable(L,Type::Int32Ty));
+ ConstantInt *NewEV = ConstantInt::get(Type::Int32Ty, integerVal);
+ Value *LHS = (EVIndex == 1 ? NewIV->getIncomingValue(BackEdge) : NewEV);
+ Value *RHS = (EVIndex == 1 ? NewEV : NewIV->getIncomingValue(BackEdge));
+ ICmpInst *NewEC = new ICmpInst(NewPred, LHS, RHS, EC->getNameStart(),
+ EC->getParent()->getTerminator());
+
+ // Delete old, floating point, exit comparision instruction.
+ SE->deleteValueFromRecords(EC);
+ EC->replaceAllUsesWith(NewEC);
+ EC->eraseFromParent();
+
+ // Delete old, floating point, increment instruction.
+ SE->deleteValueFromRecords(Incr);
+ Incr->replaceAllUsesWith(UndefValue::get(Incr->getType()));
+ Incr->eraseFromParent();
+
+ // Replace floating induction variable.
+ UIToFPInst *Conv = new UIToFPInst(NewIV, PH->getType(), "indvar.conv",
+ NonPHIInsn);
+ PH->replaceAllUsesWith(Conv);
+
+ SE->deleteValueFromRecords(PH);
+ PH->removeIncomingValue((unsigned)0);
+ PH->removeIncomingValue((unsigned)0);
+ }
+}
+