Skip to content

Commit

Permalink
[LoopVectorize] Extract InductionInfo into a helper class...
Browse files Browse the repository at this point in the history
... and move it into LoopUtils where it can be used by other passes, just like ReductionDescriptor. The API is very similar to ReductionDescriptor - that is, not very nice at all. Sorting these both out will come in a followup.

NFC

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246145 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
James Molloy committed Aug 27, 2015
1 parent c20a798 commit 18671a3
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 139 deletions.
53 changes: 48 additions & 5 deletions include/llvm/Transforms/Utils/LoopUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,54 @@ class RecurrenceDescriptor {
Instruction *UnsafeAlgebraInst;
};

/// A struct for saving information about induction variables.
class InductionDescriptor {
public:
/// This enum represents the kinds of inductions that we support.
enum InductionKind {
IK_NoInduction, ///< Not an induction variable.
IK_IntInduction, ///< Integer induction variable. Step = C.
IK_PtrInduction ///< Pointer induction var. Step = C / sizeof(elem).
};

private:
/// Private constructor - use \c isInductionPHI.
InductionDescriptor(Value *Start, InductionKind K, ConstantInt *Step);
public:
/// Default constructor - creates an invalid induction.
InductionDescriptor()
: StartValue(nullptr), IK(IK_NoInduction), StepValue(nullptr) {}

/// Get the consecutive direction. Returns:
/// 0 - unknown or non-consecutive.
/// 1 - consecutive and increasing.
/// -1 - consecutive and decreasing.
int getConsecutiveDirection() const;

/// Compute the transformed value of Index at offset StartValue using step
/// StepValue.
/// For integer induction, returns StartValue + Index * StepValue.
/// For pointer induction, returns StartValue[Index * StepValue].
/// FIXME: The newly created binary instructions should contain nsw/nuw
/// flags, which can be found from the original scalar operations.
Value *transform(IRBuilder<> &B, Value *Index) const;

Value *getStartValue() const { return StartValue; }
InductionKind getKind() const { return IK; }
ConstantInt *getStepValue() const { return StepValue; }

static bool isInductionPHI(PHINode *Phi, ScalarEvolution *SE,
InductionDescriptor &D);

private:
/// Start value.
TrackingVH<Value> StartValue;
/// Induction kind.
InductionKind IK;
/// Step value.
ConstantInt *StepValue;
};

BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);

/// \brief Simplify each loop in a loop nest recursively.
Expand Down Expand Up @@ -277,11 +325,6 @@ bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock*> &,
/// Updates safety information in LICMSafetyInfo argument.
void computeLICMSafetyInfo(LICMSafetyInfo *, Loop *);

/// \brief Checks if the given PHINode in a loop header is an induction
/// variable. Returns true if this is an induction PHI along with the step
/// value.
bool isInductionPHI(PHINode *, ScalarEvolution *, ConstantInt *&);

/// \brief Returns the instructions that use values defined in the loop.
SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Transforms/Scalar/LoopInterchange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,9 @@ bool LoopInterchangeLegality::findInductionAndReductions(
return false;
for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
RecurrenceDescriptor RD;
InductionDescriptor ID;
PHINode *PHI = cast<PHINode>(I);
ConstantInt *StepValue = nullptr;
if (isInductionPHI(PHI, SE, StepValue))
if (InductionDescriptor::isInductionPHI(PHI, SE, ID))
Inductions.push_back(PHI);
else if (RecurrenceDescriptor::isReductionPHI(PHI, L, RD))
Reductions.push_back(PHI);
Expand Down
60 changes: 56 additions & 4 deletions lib/Transforms/Utils/LoopUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,54 @@ Value *RecurrenceDescriptor::createMinMaxOp(IRBuilder<> &Builder,
return Select;
}

bool llvm::isInductionPHI(PHINode *Phi, ScalarEvolution *SE,
ConstantInt *&StepValue) {
InductionDescriptor::InductionDescriptor(Value *Start, InductionKind K,
ConstantInt *Step)
: StartValue(Start), IK(K), StepValue(Step) {
assert(IK != IK_NoInduction && "Not an induction");
assert(StartValue && "StartValue is null");
assert(StepValue && !StepValue->isZero() && "StepValue is zero");
assert((IK != IK_PtrInduction || StartValue->getType()->isPointerTy()) &&
"StartValue is not a pointer for pointer induction");
assert((IK != IK_IntInduction || StartValue->getType()->isIntegerTy()) &&
"StartValue is not an integer for integer induction");
assert(StepValue->getType()->isIntegerTy() &&
"StepValue is not an integer");
}

int InductionDescriptor::getConsecutiveDirection() const {
if (StepValue && (StepValue->isOne() || StepValue->isMinusOne()))
return StepValue->getSExtValue();
return 0;
}

Value *InductionDescriptor::transform(IRBuilder<> &B, Value *Index) const {
switch (IK) {
case IK_IntInduction:
assert(Index->getType() == StartValue->getType() &&
"Index type does not match StartValue type");
if (StepValue->isMinusOne())
return B.CreateSub(StartValue, Index);
if (!StepValue->isOne())
Index = B.CreateMul(Index, StepValue);
return B.CreateAdd(StartValue, Index);

case IK_PtrInduction:
assert(Index->getType() == StepValue->getType() &&
"Index type does not match StepValue type");
if (StepValue->isMinusOne())
Index = B.CreateNeg(Index);
else if (!StepValue->isOne())
Index = B.CreateMul(Index, StepValue);
return B.CreateGEP(nullptr, StartValue, Index);

case IK_NoInduction:
return nullptr;
}
llvm_unreachable("invalid enum");
}

bool InductionDescriptor::isInductionPHI(PHINode *Phi, ScalarEvolution *SE,
InductionDescriptor &D) {
Type *PhiTy = Phi->getType();
// We only handle integer and pointer inductions variables.
if (!PhiTy->isIntegerTy() && !PhiTy->isPointerTy())
Expand All @@ -471,6 +517,10 @@ bool llvm::isInductionPHI(PHINode *Phi, ScalarEvolution *SE,
return false;
}

assert(AR->getLoop()->getHeader() == Phi->getParent() &&
"PHI is an AddRec for a different loop?!");
Value *StartValue =
Phi->getIncomingValueForBlock(AR->getLoop()->getLoopPreheader());
const SCEV *Step = AR->getStepRecurrence(*SE);
// Calculate the pointer stride and check if it is consecutive.
const SCEVConstant *C = dyn_cast<SCEVConstant>(Step);
Expand All @@ -479,7 +529,7 @@ bool llvm::isInductionPHI(PHINode *Phi, ScalarEvolution *SE,

ConstantInt *CV = C->getValue();
if (PhiTy->isIntegerTy()) {
StepValue = CV;
D = InductionDescriptor(StartValue, IK_IntInduction, CV);
return true;
}

Expand All @@ -498,7 +548,9 @@ bool llvm::isInductionPHI(PHINode *Phi, ScalarEvolution *SE,
int64_t CVSize = CV->getSExtValue();
if (CVSize % Size)
return false;
StepValue = ConstantInt::getSigned(CV->getType(), CVSize / Size);
auto *StepValue = ConstantInt::getSigned(CV->getType(), CVSize / Size);

D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue);
return true;
}

Expand Down
Loading

0 comments on commit 18671a3

Please sign in to comment.