RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurrenceKind Kind, InstDesc &Prev, bool HasFunNoNaNAttr) { Instruction *UAI = Prev.getUnsafeAlgebraInst(); if (!UAI && isa<FPMathOperator>(I) && !I->hasAllowReassoc()) UAI = I; // Found an unsafe (unvectorizable) algebra instruction. switch (I->getOpcode()) { default: return InstDesc(false, I); case Instruction::PHI: return InstDesc(I, Prev.getMinMaxKind(), Prev.getUnsafeAlgebraInst()); case Instruction::Sub: case Instruction::Add: return InstDesc(Kind == RK_IntegerAdd, I); case Instruction::Mul: return InstDesc(Kind == RK_IntegerMult, I); case Instruction::And: return InstDesc(Kind == RK_IntegerAnd, I); case Instruction::Or: return InstDesc(Kind == RK_IntegerOr, I); case Instruction::Xor: return InstDesc(Kind == RK_IntegerXor, I); case Instruction::FMul: return InstDesc(Kind == RK_FloatMult, I, UAI); case Instruction::FSub: case Instruction::FAdd: return InstDesc(Kind == RK_FloatAdd, I, UAI); case Instruction::Select: if (Kind == RK_FloatAdd || Kind == RK_FloatMult) return isConditionalRdxPattern(Kind, I); LLVM_FALLTHROUGH; case Instruction::FCmp: case Instruction::ICmp: if (Kind != RK_IntegerMinMax && (!HasFunNoNaNAttr || Kind != RK_FloatMinMax)) return InstDesc(false, I); return isMinMaxSelectCmpPattern(I, Prev); } }
RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurrenceKind Kind, InstDesc &Prev, bool HasFunNoNaNAttr) { bool FP = I->getType()->isFloatingPointTy(); Instruction *UAI = Prev.getUnsafeAlgebraInst(); if (!UAI && FP && !I->hasUnsafeAlgebra()) UAI = I; // Found an unsafe (unvectorizable) algebra instruction. switch (I->getOpcode()) { default: return InstDesc(false, I); case Instruction::PHI: return InstDesc(I, Prev.getMinMaxKind(), Prev.getUnsafeAlgebraInst()); case Instruction::Sub: case Instruction::Add: return InstDesc(Kind == RK_IntegerAdd, I); case Instruction::Mul: return InstDesc(Kind == RK_IntegerMult, I); case Instruction::And: return InstDesc(Kind == RK_IntegerAnd, I); case Instruction::Or: return InstDesc(Kind == RK_IntegerOr, I); case Instruction::Xor: return InstDesc(Kind == RK_IntegerXor, I); case Instruction::FMul: return InstDesc(Kind == RK_FloatMult, I, UAI); case Instruction::FSub: case Instruction::FAdd: return InstDesc(Kind == RK_FloatAdd, I, UAI); case Instruction::FCmp: case Instruction::ICmp: case Instruction::Select: if (Kind != RK_IntegerMinMax && (!HasFunNoNaNAttr || Kind != RK_FloatMinMax)) return InstDesc(false, I); return isMinMaxSelectCmpPattern(I, Prev); } }
/// 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). RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev) { assert((isa<ICmpInst>(I) || isa<FCmpInst>(I) || isa<SelectInst>(I)) && "Expect a select instruction"); Instruction *Cmp = nullptr; SelectInst *Select = nullptr; // We must handle the select(cmp()) as a single instruction. Advance to the // select. if ((Cmp = dyn_cast<ICmpInst>(I)) || (Cmp = dyn_cast<FCmpInst>(I))) { if (!Cmp->hasOneUse() || !(Select = dyn_cast<SelectInst>(*I->user_begin()))) return InstDesc(false, I); return InstDesc(Select, Prev.getMinMaxKind()); } // Only handle single use cases for now. if (!(Select = dyn_cast<SelectInst>(I))) return InstDesc(false, I); if (!(Cmp = dyn_cast<ICmpInst>(I->getOperand(0))) && !(Cmp = dyn_cast<FCmpInst>(I->getOperand(0)))) return InstDesc(false, I); if (!Cmp->hasOneUse()) return InstDesc(false, I); Value *CmpLeft; Value *CmpRight; // Look for a min/max pattern. if (m_UMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_UIntMin); else if (m_UMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_UIntMax); else if (m_SMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_SIntMax); else if (m_SMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_SIntMin); else if (m_OrdFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_FloatMin); else if (m_OrdFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_FloatMax); else if (m_UnordFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_FloatMin); else if (m_UnordFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select)) return InstDesc(Select, MRK_FloatMax); return InstDesc(false, I); }