aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
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);
+ }
+}
+