[llvm-commits] [llvm] r58625 - in /llvm/trunk: lib/Transforms/Scalar/IndVarSimplify.cpp test/Transforms/IndVarsSimplify/2008-11-03-Floating.ll
Chris Lattner
clattner at apple.com
Sat Nov 15 23:30:32 PST 2008
On Nov 3, 2008, at 10:32 AM, Devang Patel wrote:
> Author: dpatel
> Date: Mon Nov 3 12:32:19 2008
> New Revision: 58625
>
> URL: http://llvm.org/viewvc/llvm-project?rev=58625&view=rev
> Log:
> 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.
Very nice! This does great things to simple loops.
> @@ -466,6 +467,7 @@
> // 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!
This does an extra pass over all phi nodes in a loop. Since there can
be many many of them, this is suboptimal. Would it be reasonable to
make this happen at the same time when EliminatePointerRecurrence is
called?
> +/// HandleFloatingPointIV - If the loop has floating induction
> variable
> +/// then insert corresponding integer induction variable if possible.
> +void IndVarSimplify::HandleFloatingPointIV(Loop *L) {
Please add a comment giving an example of the sort of loop this
benefits. Something like this is sufficient:
for (double i = 0; i < 10000; ++i)
bar((int)i);
>
> + 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;
> + }
Why collect into a list and then handle all at once? It seems that
you can just handle them on the fly like EliminatePointerRecurrence
does.
> + 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;
Please comment about what your checking and why. It is unclear to me
why the initial value has to be 0.0 for example. Why not -0.0, why
not 5.0?
> + // 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;
Again, please describe what and why you're requiring these various
things. I think that requiring an increment by a FP constant is fine,
but it allow should be any FP constant with a non-fractional value.
Also, I don't think you need to copy IVAPF here.
>
> + // Check Incr uses.
> + Value::use_iterator IncrUse = Incr->use_begin();
> + Instruction *U1 = cast<Instruction>(IncrUse++);
Comment that we know there is at least one use, the PHI.
> + if (IncrUse == Incr->use_end()) continue;
> + Instruction *U2 = cast<Instruction>(IncrUse++);
> + if (IncrUse != Incr->use_end()) continue;
> +
> + // Find exict condition.
typo "exict"
>
> + 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;
Instead of using a 'skip' bool, please factor this inner loop out into
a static helper function. However, why do you even do this at all?
Why not just see if Terminator is a cond branch whose condition is EC?
> + // 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();
No need to copy EVAPF.
>
> + 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;
It would be really really nice to allow an exit condition that is an
sitofp, to handle this case:
void foo(int N) {
double i;
for (i = 0; i < N; ++i)
bar((int)i);
}
Any conversion from an integer whose size is smaller than the mantissa
of the FP value should be ok.
> + // Insert new integer induction variable.
> + SCEVExpander Rewriter(*SE, *LI);
You don't need to use SCEVExpander for this, just do what
EliminatePointerRecurrence does.
> + // Replace floating induction variable.
> + UIToFPInst *Conv = new UIToFPInst(NewIV, PH->getType(),
> "indvar.conv",
> + NonPHIInsn);
UIToFP is generally more expensive than SIToFP on common targets (e.g.
X86). Is it safe to use SIToFP? Can you do range/size analysis to
use sitofp when safe if not?
-Chris
More information about the llvm-commits
mailing list