Skip to content

Commit cb19c8e

Browse files
committed
[LV] Add a new reduction pattern match
Adding a new reduction pattern match for vectorizing code similar to TSVC s3111: for (int i = 0; i < N; i++) if (a[i] > b) sum += a[i]; This patch adds support for fadd, fsub and fmull, as well as multiple branches and different (but compatible) instructions (ex. add+sub) in different branches. I have forwarded to trunk, added fsub and fmul functionality and additional tests, but the credit goes to Takahiro, who did most of the actual work. Differential Revision: https://reviews.llvm.org/D49168 Patch by Takahiro Miyoshi <takahiro.miyoshi@linaro.org>. llvm-svn: 344172
1 parent 2e76cab commit cb19c8e

File tree

3 files changed

+737
-7
lines changed

3 files changed

+737
-7
lines changed

llvm/include/llvm/Analysis/IVDescriptors.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ class RecurrenceDescriptor {
140140

141141
/// Returns true if instruction I has multiple uses in Insts
142142
static bool hasMultipleUsesOf(Instruction *I,
143-
SmallPtrSetImpl<Instruction *> &Insts);
143+
SmallPtrSetImpl<Instruction *> &Insts,
144+
unsigned MaxNumUses);
144145

145146
/// Returns true if all uses of the instruction I is within the Set.
146147
static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set);
@@ -150,6 +151,10 @@ class RecurrenceDescriptor {
150151
/// or max(X, Y).
151152
static InstDesc isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev);
152153

154+
/// Returns a struct describing if the instruction is a
155+
/// Select(FCmp(X, Y), (Z = X op PHINode), PHINode) instruction pattern.
156+
static InstDesc isConditionalRdxPattern(RecurrenceKind Kind, Instruction *I);
157+
153158
/// Returns identity corresponding to the RecurrenceKind.
154159
static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp);
155160

llvm/lib/Analysis/IVDescriptors.cpp

+65-6
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,17 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurrenceKind Kind,
299299
return false;
300300
}
301301

302+
bool IsASelect = isa<SelectInst>(Cur);
303+
304+
// A conditional reduction operation must only have 2 or less uses in
305+
// VisitedInsts.
306+
if (IsASelect && (Kind == RK_FloatAdd || Kind == RK_FloatMult) &&
307+
hasMultipleUsesOf(Cur, VisitedInsts, 2))
308+
return false;
309+
302310
// A reduction operation must only have one use of the reduction value.
303-
if (!IsAPhi && Kind != RK_IntegerMinMax && Kind != RK_FloatMinMax &&
304-
hasMultipleUsesOf(Cur, VisitedInsts))
311+
if (!IsAPhi && !IsASelect && Kind != RK_IntegerMinMax &&
312+
Kind != RK_FloatMinMax && hasMultipleUsesOf(Cur, VisitedInsts, 1))
305313
return false;
306314

307315
// All inputs to a PHI node must be a reduction value.
@@ -362,7 +370,8 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurrenceKind Kind,
362370
} else if (!isa<PHINode>(UI) &&
363371
((!isa<FCmpInst>(UI) && !isa<ICmpInst>(UI) &&
364372
!isa<SelectInst>(UI)) ||
365-
!isMinMaxSelectCmpPattern(UI, IgnoredVal).isRecurrence()))
373+
(!isConditionalRdxPattern(Kind, UI).isRecurrence() &&
374+
!isMinMaxSelectCmpPattern(UI, IgnoredVal).isRecurrence())))
366375
return false;
367376

368377
// Remember that we completed the cycle.
@@ -491,6 +500,52 @@ RecurrenceDescriptor::isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev) {
491500
return InstDesc(false, I);
492501
}
493502

503+
/// Returns true if the select instruction has users in the compare-and-add
504+
/// reduction pattern below. The select instruction argument is the last one
505+
/// in the sequence.
506+
///
507+
/// %sum.1 = phi ...
508+
/// ...
509+
/// %cmp = fcmp pred %0, %CFP
510+
/// %add = fadd %0, %sum.1
511+
/// %sum.2 = select %cmp, %add, %sum.1
512+
RecurrenceDescriptor::InstDesc
513+
RecurrenceDescriptor::isConditionalRdxPattern(
514+
RecurrenceKind Kind, Instruction *I) {
515+
SelectInst *SI = dyn_cast<SelectInst>(I);
516+
if (!SI)
517+
return InstDesc(false, I);
518+
519+
CmpInst *CI = dyn_cast<CmpInst>(SI->getCondition());
520+
// Only handle single use cases for now.
521+
if (!CI || !CI->hasOneUse())
522+
return InstDesc(false, I);
523+
524+
Value *TrueVal = SI->getTrueValue();
525+
Value *FalseVal = SI->getFalseValue();
526+
// Handle only when either of operands of select instruction is a PHI
527+
// node for now.
528+
if ((isa<PHINode>(*TrueVal) && isa<PHINode>(*FalseVal)) ||
529+
(!isa<PHINode>(*TrueVal) && !isa<PHINode>(*FalseVal)))
530+
return InstDesc(false, I);
531+
532+
Instruction *I1 =
533+
isa<PHINode>(*TrueVal) ? dyn_cast<Instruction>(FalseVal)
534+
: dyn_cast<Instruction>(TrueVal);
535+
if (!I1 || !I1->isBinaryOp())
536+
return InstDesc(false, I);
537+
538+
Value *Op1, *Op2;
539+
if (m_FAdd(m_Value(Op1), m_Value(Op2)).match(I1) ||
540+
m_FSub(m_Value(Op1), m_Value(Op2)).match(I1))
541+
return InstDesc(Kind == RK_FloatAdd, SI);
542+
543+
if (m_FMul(m_Value(Op1), m_Value(Op2)).match(I1))
544+
return InstDesc(Kind == RK_FloatMult, SI);
545+
546+
return InstDesc(false, I);
547+
}
548+
494549
RecurrenceDescriptor::InstDesc
495550
RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurrenceKind Kind,
496551
InstDesc &Prev, bool HasFunNoNaNAttr) {
@@ -520,9 +575,12 @@ RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurrenceKind Kind,
520575
case Instruction::FSub:
521576
case Instruction::FAdd:
522577
return InstDesc(Kind == RK_FloatAdd, I, UAI);
578+
case Instruction::Select:
579+
if (Kind == RK_FloatAdd || Kind == RK_FloatMult)
580+
return isConditionalRdxPattern(Kind, I);
581+
LLVM_FALLTHROUGH;
523582
case Instruction::FCmp:
524583
case Instruction::ICmp:
525-
case Instruction::Select:
526584
if (Kind != RK_IntegerMinMax &&
527585
(!HasFunNoNaNAttr || Kind != RK_FloatMinMax))
528586
return InstDesc(false, I);
@@ -531,13 +589,14 @@ RecurrenceDescriptor::isRecurrenceInstr(Instruction *I, RecurrenceKind Kind,
531589
}
532590

533591
bool RecurrenceDescriptor::hasMultipleUsesOf(
534-
Instruction *I, SmallPtrSetImpl<Instruction *> &Insts) {
592+
Instruction *I, SmallPtrSetImpl<Instruction *> &Insts,
593+
unsigned MaxNumUses) {
535594
unsigned NumUses = 0;
536595
for (User::op_iterator Use = I->op_begin(), E = I->op_end(); Use != E;
537596
++Use) {
538597
if (Insts.count(dyn_cast<Instruction>(*Use)))
539598
++NumUses;
540-
if (NumUses > 1)
599+
if (NumUses > MaxNumUses)
541600
return true;
542601
}
543602

0 commit comments

Comments
 (0)