/// The type of reduction operation.
RecurKind RdxKind;
+ static bool isCmpSelMinMax(Instruction *I) {
+ return match(I, m_Select(m_Cmp(), m_Value(), m_Value())) &&
+ RecurrenceDescriptor::isMinMaxRecurrenceKind(getRdxKind(I));
+ }
+
/// Checks if instruction is associative and can be vectorized.
static bool isVectorizable(RecurKind Kind, Instruction *I) {
if (Kind == RecurKind::None)
/// Get the index of the first operand.
static unsigned getFirstOperandIndex(Instruction *I) {
- return isa<SelectInst>(I) ? 1 : 0;
+ return isCmpSelMinMax(I) ? 1 : 0;
}
/// Total number of operands in the reduction operation.
static unsigned getNumberOfOperands(Instruction *I) {
- return isa<SelectInst>(I) ? 3 : 2;
+ return isCmpSelMinMax(I) ? 3 : 2;
}
/// Checks if the instruction is in basic block \p BB.
/// For a min/max reduction check that both compare and select are in \p BB.
- static bool hasSameParent(Instruction *I, BasicBlock *BB, bool IsRedOp) {
- auto *Sel = dyn_cast<SelectInst>(I);
- if (IsRedOp && Sel) {
+ static bool hasSameParent(Instruction *I, BasicBlock *BB) {
+ if (isCmpSelMinMax(I)) {
+ auto *Sel = cast<SelectInst>(I);
auto *Cmp = cast<Instruction>(Sel->getCondition());
return Sel->getParent() == BB && Cmp->getParent() == BB;
}
}
/// Expected number of uses for reduction operations/reduced values.
- static bool hasRequiredNumberOfUses(bool MatchCmpSel, Instruction *I) {
- // SelectInst must be used twice while the condition op must have single
- // use only.
- if (MatchCmpSel) {
+ static bool hasRequiredNumberOfUses(bool IsCmpSelMinMax, Instruction *I) {
+ if (IsCmpSelMinMax) {
+ // SelectInst must be used twice while the condition op must have single
+ // use only.
if (auto *Sel = dyn_cast<SelectInst>(I))
return Sel->hasNUses(2) && Sel->getCondition()->hasOneUse();
return I->hasNUses(2);
/// Initializes the list of reduction operations.
void initReductionOps(Instruction *I) {
- if (isa<SelectInst>(I))
+ if (isCmpSelMinMax(I))
ReductionOps.assign(2, ReductionOpsType());
else
ReductionOps.assign(1, ReductionOpsType());
/// Add all reduction operations for the reduction instruction \p I.
void addReductionOps(Instruction *I) {
- if (auto *Sel = dyn_cast<SelectInst>(I)) {
- ReductionOps[0].emplace_back(Sel->getCondition());
- ReductionOps[1].emplace_back(Sel);
+ if (isCmpSelMinMax(I)) {
+ ReductionOps[0].emplace_back(cast<SelectInst>(I)->getCondition());
+ ReductionOps[1].emplace_back(I);
} else {
ReductionOps[0].emplace_back(I);
}
// ultimate reduction.
const bool IsRdxInst = EdgeRdxKind == RdxKind;
if (EdgeInst != Phi && EdgeInst != Inst &&
- hasSameParent(EdgeInst, Inst->getParent(), IsRdxInst) &&
- hasRequiredNumberOfUses(isa<SelectInst>(Inst), EdgeInst) &&
+ hasSameParent(EdgeInst, Inst->getParent()) &&
+ hasRequiredNumberOfUses(isCmpSelMinMax(Inst), EdgeInst) &&
(!LeafOpcode || LeafOpcode == EdgeInst->getOpcode() || IsRdxInst)) {
if (IsRdxInst) {
// We need to be able to reassociate the reduction operations.
// Emit a reduction. If the root is a select (min/max idiom), the insert
// point is the compare condition of that select.
Instruction *RdxRootInst = cast<Instruction>(ReductionRoot);
- if (isa<SelectInst>(RdxRootInst))
+ if (isCmpSelMinMax(RdxRootInst))
Builder.SetInsertPoint(getCmpForMinMaxReduction(RdxRootInst));
else
Builder.SetInsertPoint(RdxRootInst);