Refactor RecurrenceInstDesc

Moved RecurrenceInstDesc into RecurrenceDescriptor to simplify the namespaces.

llvm-svn: 239862
This commit is contained in:
Tyler Nowicki 2015-06-16 22:59:45 +00:00
parent 86e90b3cfa
commit 27b2c39eb3
3 changed files with 87 additions and 95 deletions

View File

@ -54,42 +54,6 @@ struct LICMSafetyInfo {
/// special case of chains of recurrences (CR). See ScalarEvolution for CR /// special case of chains of recurrences (CR). See ScalarEvolution for CR
/// references. /// references.
/// This POD struct holds information about a potential recurrence operation.
class RecurrenceInstDesc {
public:
// This enum represents the kind of minmax recurrence.
enum MinMaxRecurrenceKind {
MRK_Invalid,
MRK_UIntMin,
MRK_UIntMax,
MRK_SIntMin,
MRK_SIntMax,
MRK_FloatMin,
MRK_FloatMax
};
RecurrenceInstDesc(bool IsRecur, Instruction *I)
: IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid) {}
RecurrenceInstDesc(Instruction *I, MinMaxRecurrenceKind K)
: IsRecurrence(true), PatternLastInst(I), MinMaxKind(K) {}
bool isRecurrence() { return IsRecurrence; }
MinMaxRecurrenceKind getMinMaxKind() { return MinMaxKind; }
Instruction *getPatternInst() { return PatternLastInst; }
private:
// Is this instruction a recurrence candidate.
bool IsRecurrence;
// The last instruction in a min/max pattern (select of the select(icmp())
// pattern), or the current recurrence instruction otherwise.
Instruction *PatternLastInst;
// If this is a min/max pattern the comparison predicate.
MinMaxRecurrenceKind MinMaxKind;
};
/// This struct holds information about recurrence variables. /// This struct holds information about recurrence variables.
class RecurrenceDescriptor { class RecurrenceDescriptor {
@ -108,23 +72,58 @@ public:
RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()). RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()).
}; };
// This enum represents the kind of minmax recurrence.
enum MinMaxRecurrenceKind {
MRK_Invalid,
MRK_UIntMin,
MRK_UIntMax,
MRK_SIntMin,
MRK_SIntMax,
MRK_FloatMin,
MRK_FloatMax
};
RecurrenceDescriptor() RecurrenceDescriptor()
: StartValue(nullptr), LoopExitInstr(nullptr), Kind(RK_NoRecurrence), : StartValue(nullptr), LoopExitInstr(nullptr), Kind(RK_NoRecurrence),
MinMaxKind(RecurrenceInstDesc::MRK_Invalid) {} MinMaxKind(MRK_Invalid) {}
RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K, RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K,
RecurrenceInstDesc::MinMaxRecurrenceKind MK) MinMaxRecurrenceKind MK)
: StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK) {} : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK) {}
/// This POD struct holds information about a potential recurrence operation.
class InstDesc {
public:
InstDesc(bool IsRecur, Instruction *I)
: IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid) {}
InstDesc(Instruction *I, MinMaxRecurrenceKind K)
: IsRecurrence(true), PatternLastInst(I), MinMaxKind(K) {}
bool isRecurrence() { return IsRecurrence; }
MinMaxRecurrenceKind getMinMaxKind() { return MinMaxKind; }
Instruction *getPatternInst() { return PatternLastInst; }
private:
// Is this instruction a recurrence candidate.
bool IsRecurrence;
// The last instruction in a min/max pattern (select of the select(icmp())
// pattern), or the current recurrence instruction otherwise.
Instruction *PatternLastInst;
// If this is a min/max pattern the comparison predicate.
MinMaxRecurrenceKind MinMaxKind;
};
/// Returns a struct describing if the instruction 'I' can be a recurrence /// Returns a struct describing if the instruction 'I' can be a recurrence
/// variable of type 'Kind'. If the recurrence is a min/max pattern of /// variable of type 'Kind'. If the recurrence is a min/max pattern of
/// select(icmp()) this function advances the instruction pointer 'I' from the /// select(icmp()) this function advances the instruction pointer 'I' from the
/// compare instruction to the select instruction and stores this pointer in /// compare instruction to the select instruction and stores this pointer in
/// 'PatternLastInst' member of the returned struct. /// 'PatternLastInst' member of the returned struct.
static RecurrenceInstDesc isRecurrenceInstr(Instruction *I, static InstDesc isRecurrenceInstr(Instruction *I, RecurrenceKind Kind,
RecurrenceKind Kind, InstDesc &Prev, bool HasFunNoNaNAttr);
RecurrenceInstDesc &Prev,
bool HasFunNoNaNAttr);
/// Returns true if instuction I has multiple uses in Insts /// Returns true if instuction I has multiple uses in Insts
static bool hasMultipleUsesOf(Instruction *I, static bool hasMultipleUsesOf(Instruction *I,
@ -136,8 +135,7 @@ public:
/// Returns a struct describing if the instruction if the instruction is a /// Returns a struct describing if the instruction if the instruction is a
/// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y) /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y)
/// or max(X, Y). /// or max(X, Y).
static RecurrenceInstDesc isMinMaxSelectCmpPattern(Instruction *I, static InstDesc isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev);
RecurrenceInstDesc &Prev);
/// Returns identity corresponding to the RecurrenceKind. /// Returns identity corresponding to the RecurrenceKind.
static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp); static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp);
@ -147,8 +145,7 @@ public:
static unsigned getRecurrenceBinOp(RecurrenceKind Kind); static unsigned getRecurrenceBinOp(RecurrenceKind Kind);
/// Returns a Min/Max operation corresponding to MinMaxRecurrenceKind. /// Returns a Min/Max operation corresponding to MinMaxRecurrenceKind.
static Value *createMinMaxOp(IRBuilder<> &Builder, static Value *createMinMaxOp(IRBuilder<> &Builder, MinMaxRecurrenceKind RK,
RecurrenceInstDesc::MinMaxRecurrenceKind RK,
Value *Left, Value *Right); Value *Left, Value *Right);
/// Returns true if Phi is a reduction of type Kind and adds it to the /// Returns true if Phi is a reduction of type Kind and adds it to the
@ -164,9 +161,7 @@ public:
RecurrenceKind getRecurrenceKind() { return Kind; } RecurrenceKind getRecurrenceKind() { return Kind; }
RecurrenceInstDesc::MinMaxRecurrenceKind getMinMaxRecurrenceKind() { MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; }
return MinMaxKind;
}
TrackingVH<Value> getRecurrenceStartValue() { return StartValue; } TrackingVH<Value> getRecurrenceStartValue() { return StartValue; }
@ -181,7 +176,7 @@ private:
// The kind of the recurrence. // The kind of the recurrence.
RecurrenceKind Kind; RecurrenceKind Kind;
// If this a min/max recurrence the kind of recurrence. // If this a min/max recurrence the kind of recurrence.
RecurrenceInstDesc::MinMaxRecurrenceKind MinMaxKind; MinMaxRecurrenceKind MinMaxKind;
}; };
BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P); BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);

View File

@ -66,7 +66,7 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurrenceKind Kind,
// the number of instruction we saw from the recognized min/max pattern, // the number of instruction we saw from the recognized min/max pattern,
// to make sure we only see exactly the two instructions. // to make sure we only see exactly the two instructions.
unsigned NumCmpSelectPatternInst = 0; unsigned NumCmpSelectPatternInst = 0;
RecurrenceInstDesc ReduxDesc(false, nullptr); InstDesc ReduxDesc(false, nullptr);
SmallPtrSet<Instruction *, 8> VisitedInsts; SmallPtrSet<Instruction *, 8> VisitedInsts;
SmallVector<Instruction *, 8> Worklist; SmallVector<Instruction *, 8> Worklist;
@ -164,7 +164,7 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurrenceKind Kind,
// Process instructions only once (termination). Each reduction cycle // Process instructions only once (termination). Each reduction cycle
// value must only be used once, except by phi nodes and min/max // value must only be used once, except by phi nodes and min/max
// reductions which are represented as a cmp followed by a select. // reductions which are represented as a cmp followed by a select.
RecurrenceInstDesc IgnoredVal(false, nullptr); InstDesc IgnoredVal(false, nullptr);
if (VisitedInsts.insert(UI).second) { if (VisitedInsts.insert(UI).second) {
if (isa<PHINode>(UI)) if (isa<PHINode>(UI))
PHIs.push_back(UI); PHIs.push_back(UI);
@ -210,9 +210,8 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurrenceKind Kind,
/// Returns true if the instruction is a Select(ICmp(X, Y), X, Y) instruction /// Returns true if the instruction is a Select(ICmp(X, Y), X, Y) instruction
/// pattern corresponding to a min(X, Y) or max(X, Y). /// pattern corresponding to a min(X, Y) or max(X, Y).
RecurrenceInstDesc RecurrenceDescriptor::InstDesc
RecurrenceDescriptor::isMinMaxSelectCmpPattern(Instruction *I, RecurrenceDescriptor::isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev) {
RecurrenceInstDesc &Prev) {
assert((isa<ICmpInst>(I) || isa<FCmpInst>(I) || isa<SelectInst>(I)) && assert((isa<ICmpInst>(I) || isa<FCmpInst>(I) || isa<SelectInst>(I)) &&
"Expect a select instruction"); "Expect a select instruction");
@ -223,79 +222,78 @@ RecurrenceDescriptor::isMinMaxSelectCmpPattern(Instruction *I,
// select. // select.
if ((Cmp = dyn_cast<ICmpInst>(I)) || (Cmp = dyn_cast<FCmpInst>(I))) { if ((Cmp = dyn_cast<ICmpInst>(I)) || (Cmp = dyn_cast<FCmpInst>(I))) {
if (!Cmp->hasOneUse() || !(Select = dyn_cast<SelectInst>(*I->user_begin()))) if (!Cmp->hasOneUse() || !(Select = dyn_cast<SelectInst>(*I->user_begin())))
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
return RecurrenceInstDesc(Select, Prev.getMinMaxKind()); return InstDesc(Select, Prev.getMinMaxKind());
} }
// Only handle single use cases for now. // Only handle single use cases for now.
if (!(Select = dyn_cast<SelectInst>(I))) if (!(Select = dyn_cast<SelectInst>(I)))
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
if (!(Cmp = dyn_cast<ICmpInst>(I->getOperand(0))) && if (!(Cmp = dyn_cast<ICmpInst>(I->getOperand(0))) &&
!(Cmp = dyn_cast<FCmpInst>(I->getOperand(0)))) !(Cmp = dyn_cast<FCmpInst>(I->getOperand(0))))
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
if (!Cmp->hasOneUse()) if (!Cmp->hasOneUse())
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
Value *CmpLeft; Value *CmpLeft;
Value *CmpRight; Value *CmpRight;
// Look for a min/max pattern. // Look for a min/max pattern.
if (m_UMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) if (m_UMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_UIntMin); return InstDesc(Select, MRK_UIntMin);
else if (m_UMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) else if (m_UMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_UIntMax); return InstDesc(Select, MRK_UIntMax);
else if (m_SMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) else if (m_SMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_SIntMax); return InstDesc(Select, MRK_SIntMax);
else if (m_SMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) else if (m_SMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_SIntMin); return InstDesc(Select, MRK_SIntMin);
else if (m_OrdFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) else if (m_OrdFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_FloatMin); return InstDesc(Select, MRK_FloatMin);
else if (m_OrdFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) else if (m_OrdFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_FloatMax); return InstDesc(Select, MRK_FloatMax);
else if (m_UnordFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) else if (m_UnordFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_FloatMin); return InstDesc(Select, MRK_FloatMin);
else if (m_UnordFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) else if (m_UnordFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))
return RecurrenceInstDesc(Select, RecurrenceInstDesc::MRK_FloatMax); return InstDesc(Select, MRK_FloatMax);
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
} }
RecurrenceInstDesc RecurrenceDescriptor::InstDesc
RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurrenceKind Kind, RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurrenceKind Kind,
RecurrenceInstDesc &Prev, InstDesc &Prev, bool HasFunNoNaNAttr) {
bool HasFunNoNaNAttr) {
bool FP = I->getType()->isFloatingPointTy(); bool FP = I->getType()->isFloatingPointTy();
bool FastMath = FP && I->hasUnsafeAlgebra(); bool FastMath = FP && I->hasUnsafeAlgebra();
switch (I->getOpcode()) { switch (I->getOpcode()) {
default: default:
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
case Instruction::PHI: case Instruction::PHI:
if (FP && if (FP &&
(Kind != RK_FloatMult && Kind != RK_FloatAdd && Kind != RK_FloatMinMax)) (Kind != RK_FloatMult && Kind != RK_FloatAdd && Kind != RK_FloatMinMax))
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
return RecurrenceInstDesc(I, Prev.getMinMaxKind()); return InstDesc(I, Prev.getMinMaxKind());
case Instruction::Sub: case Instruction::Sub:
case Instruction::Add: case Instruction::Add:
return RecurrenceInstDesc(Kind == RK_IntegerAdd, I); return InstDesc(Kind == RK_IntegerAdd, I);
case Instruction::Mul: case Instruction::Mul:
return RecurrenceInstDesc(Kind == RK_IntegerMult, I); return InstDesc(Kind == RK_IntegerMult, I);
case Instruction::And: case Instruction::And:
return RecurrenceInstDesc(Kind == RK_IntegerAnd, I); return InstDesc(Kind == RK_IntegerAnd, I);
case Instruction::Or: case Instruction::Or:
return RecurrenceInstDesc(Kind == RK_IntegerOr, I); return InstDesc(Kind == RK_IntegerOr, I);
case Instruction::Xor: case Instruction::Xor:
return RecurrenceInstDesc(Kind == RK_IntegerXor, I); return InstDesc(Kind == RK_IntegerXor, I);
case Instruction::FMul: case Instruction::FMul:
return RecurrenceInstDesc(Kind == RK_FloatMult && FastMath, I); return InstDesc(Kind == RK_FloatMult && FastMath, I);
case Instruction::FSub: case Instruction::FSub:
case Instruction::FAdd: case Instruction::FAdd:
return RecurrenceInstDesc(Kind == RK_FloatAdd && FastMath, I); return InstDesc(Kind == RK_FloatAdd && FastMath, I);
case Instruction::FCmp: case Instruction::FCmp:
case Instruction::ICmp: case Instruction::ICmp:
case Instruction::Select: case Instruction::Select:
if (Kind != RK_IntegerMinMax && if (Kind != RK_IntegerMinMax &&
(!HasFunNoNaNAttr || Kind != RK_FloatMinMax)) (!HasFunNoNaNAttr || Kind != RK_FloatMinMax))
return RecurrenceInstDesc(false, I); return InstDesc(false, I);
return isMinMaxSelectCmpPattern(I, Prev); return isMinMaxSelectCmpPattern(I, Prev);
} }
} }
@ -417,36 +415,35 @@ unsigned RecurrenceDescriptor::getRecurrenceBinOp(RecurrenceKind Kind) {
} }
} }
Value *RecurrenceDescriptor::createMinMaxOp( Value *RecurrenceDescriptor::createMinMaxOp(IRBuilder<> &Builder,
IRBuilder<> &Builder, RecurrenceInstDesc::MinMaxRecurrenceKind RK, MinMaxRecurrenceKind RK,
Value *Left, Value *Right) { Value *Left, Value *Right) {
CmpInst::Predicate P = CmpInst::ICMP_NE; CmpInst::Predicate P = CmpInst::ICMP_NE;
switch (RK) { switch (RK) {
default: default:
llvm_unreachable("Unknown min/max recurrence kind"); llvm_unreachable("Unknown min/max recurrence kind");
case RecurrenceInstDesc::MRK_UIntMin: case MRK_UIntMin:
P = CmpInst::ICMP_ULT; P = CmpInst::ICMP_ULT;
break; break;
case RecurrenceInstDesc::MRK_UIntMax: case MRK_UIntMax:
P = CmpInst::ICMP_UGT; P = CmpInst::ICMP_UGT;
break; break;
case RecurrenceInstDesc::MRK_SIntMin: case MRK_SIntMin:
P = CmpInst::ICMP_SLT; P = CmpInst::ICMP_SLT;
break; break;
case RecurrenceInstDesc::MRK_SIntMax: case MRK_SIntMax:
P = CmpInst::ICMP_SGT; P = CmpInst::ICMP_SGT;
break; break;
case RecurrenceInstDesc::MRK_FloatMin: case MRK_FloatMin:
P = CmpInst::FCMP_OLT; P = CmpInst::FCMP_OLT;
break; break;
case RecurrenceInstDesc::MRK_FloatMax: case MRK_FloatMax:
P = CmpInst::FCMP_OGT; P = CmpInst::FCMP_OGT;
break; break;
} }
Value *Cmp; Value *Cmp;
if (RK == RecurrenceInstDesc::MRK_FloatMin || if (RK == MRK_FloatMin || RK == MRK_FloatMax)
RK == RecurrenceInstDesc::MRK_FloatMax)
Cmp = Builder.CreateFCmp(P, Left, Right, "rdx.minmax.cmp"); Cmp = Builder.CreateFCmp(P, Left, Right, "rdx.minmax.cmp");
else else
Cmp = Builder.CreateICmp(P, Left, Right, "rdx.minmax.cmp"); Cmp = Builder.CreateICmp(P, Left, Right, "rdx.minmax.cmp");

View File

@ -3098,7 +3098,7 @@ void InnerLoopVectorizer::vectorizeLoop() {
RecurrenceDescriptor::RecurrenceKind RK = RdxDesc.getRecurrenceKind(); RecurrenceDescriptor::RecurrenceKind RK = RdxDesc.getRecurrenceKind();
TrackingVH<Value> ReductionStartValue = RdxDesc.getRecurrenceStartValue(); TrackingVH<Value> ReductionStartValue = RdxDesc.getRecurrenceStartValue();
Instruction *LoopExitInst = RdxDesc.getLoopExitInstr(); Instruction *LoopExitInst = RdxDesc.getLoopExitInstr();
RecurrenceInstDesc::MinMaxRecurrenceKind MinMaxKind = RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind =
RdxDesc.getMinMaxRecurrenceKind(); RdxDesc.getMinMaxRecurrenceKind();
setDebugLocFromInst(Builder, ReductionStartValue); setDebugLocFromInst(Builder, ReductionStartValue);