Skip to content

Commit e280239

Browse files
[LV] Build VPlan for CSA
1 parent 0c71559 commit e280239

18 files changed

+3760
-3697
lines changed

llvm/include/llvm/Analysis/CSADescriptors.h

-78
This file was deleted.

llvm/include/llvm/Analysis/IVDescriptors.h

+57-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// This file "describes" induction and recurrence variables.
9+
// This file "describes" induction, recurrence, and conditional scalar
10+
// assignment (CSA) variables.
1011
//
1112
//===----------------------------------------------------------------------===//
1213

@@ -423,6 +424,61 @@ class InductionDescriptor {
423424
SmallVector<Instruction *, 2> RedundantCasts;
424425
};
425426

427+
/// A Conditional Scalar Assignment (CSA) is an assignment from an initial
428+
/// scalar that may or may not occur.
429+
class CSADescriptor {
430+
/// If the conditional assignment occurs inside a loop, then Phi chooses
431+
/// the value of the assignment from the entry block or the loop body block.
432+
PHINode *Phi = nullptr;
433+
434+
/// The initial value of the CSA. If the condition guarding the assignment is
435+
/// not met, then the assignment retains this value.
436+
Value *InitScalar = nullptr;
437+
438+
/// The Instruction that conditionally assigned to inside the loop.
439+
Instruction *Assignment = nullptr;
440+
441+
/// Create a CSA Descriptor that models a valid CSA with its members
442+
/// initialized correctly.
443+
CSADescriptor(PHINode *Phi, Instruction *Assignment, Value *InitScalar)
444+
: Phi(Phi), InitScalar(InitScalar), Assignment(Assignment) {}
445+
446+
public:
447+
/// Create a CSA Descriptor that models an invalid CSA.
448+
CSADescriptor() = default;
449+
450+
/// If Phi is the root of a CSA, set CSADesc as the CSA rooted by
451+
/// Phi. Otherwise, return a false, leaving CSADesc unmodified.
452+
static bool isCSAPhi(PHINode *Phi, Loop *TheLoop, CSADescriptor &CSADesc);
453+
454+
operator bool() const { return isValid(); }
455+
456+
/// Returns whether SI is the Assignment in CSA
457+
static bool isCSASelect(CSADescriptor Desc, SelectInst *SI) {
458+
return Desc.getAssignment() == SI;
459+
}
460+
461+
/// Return whether this CSADescriptor models a valid CSA.
462+
bool isValid() const { return Phi && InitScalar && Assignment; }
463+
464+
/// Return the PHI that roots this CSA.
465+
PHINode *getPhi() const { return Phi; }
466+
467+
/// Return the initial value of the CSA. This is the value if the conditional
468+
/// assignment does not occur.
469+
Value *getInitScalar() const { return InitScalar; }
470+
471+
/// The Instruction that is used after the loop
472+
Instruction *getAssignment() const { return Assignment; }
473+
474+
/// Return the condition that this CSA is conditional upon.
475+
Value *getCond() const {
476+
if (auto *SI = dyn_cast_or_null<SelectInst>(Assignment))
477+
return SI->getCondition();
478+
return nullptr;
479+
}
480+
};
481+
426482
} // end namespace llvm
427483

428484
#endif // LLVM_ANALYSIS_IVDESCRIPTORS_H

llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H
2828

2929
#include "llvm/ADT/MapVector.h"
30-
#include "llvm/Analysis/CSADescriptors.h"
3130
#include "llvm/Analysis/LoopAccessAnalysis.h"
3231
#include "llvm/Support/TypeSize.h"
3332
#include "llvm/Transforms/Utils/LoopUtils.h"

llvm/lib/Analysis/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ add_llvm_component_library(LLVMAnalysis
4646
CostModel.cpp
4747
CodeMetrics.cpp
4848
ConstantFolding.cpp
49-
CSADescriptors.cpp
5049
CtxProfAnalysis.cpp
5150
CycleAnalysis.cpp
5251
DDG.cpp

llvm/lib/Analysis/CSADescriptors.cpp

-73
This file was deleted.

llvm/lib/Analysis/IVDescriptors.cpp

+57-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// This file "describes" induction and recurrence variables.
9+
// This file "describes" induction, recurrence, and conditional scalar
10+
// assignment (CSA) variables.
1011
//
1112
//===----------------------------------------------------------------------===//
1213

@@ -1570,3 +1571,58 @@ bool InductionDescriptor::isInductionPHI(
15701571
D = InductionDescriptor(StartValue, IK_PtrInduction, Step);
15711572
return true;
15721573
}
1574+
1575+
/// Return CSADescriptor that describes a CSA that matches one of these
1576+
/// patterns:
1577+
/// phi loop_inv, (select cmp, value, phi)
1578+
/// phi loop_inv, (select cmp, phi, value)
1579+
/// phi (select cmp, value, phi), loop_inv
1580+
/// phi (select cmp, phi, value), loop_inv
1581+
/// If the CSA does not match any of these paterns, return a CSADescriptor
1582+
/// that describes an InvalidCSA.
1583+
bool CSADescriptor::isCSAPhi(PHINode *Phi, Loop *TheLoop, CSADescriptor &CSA) {
1584+
1585+
// Must be a scalar
1586+
Type *Type = Phi->getType();
1587+
if (!Type->isIntegerTy() && !Type->isFloatingPointTy() &&
1588+
!Type->isPointerTy())
1589+
return false;
1590+
1591+
// Match phi loop_inv, (select cmp, value, phi)
1592+
// or phi loop_inv, (select cmp, phi, value)
1593+
// or phi (select cmp, value, phi), loop_inv
1594+
// or phi (select cmp, phi, value), loop_inv
1595+
if (Phi->getNumIncomingValues() != 2)
1596+
return false;
1597+
auto SelectInstIt = find_if(Phi->incoming_values(), [&Phi](const Use &U) {
1598+
return match(U.get(), m_Select(m_Value(), m_Specific(Phi), m_Value())) ||
1599+
match(U.get(), m_Select(m_Value(), m_Value(), m_Specific(Phi)));
1600+
});
1601+
if (SelectInstIt == Phi->incoming_values().end())
1602+
return false;
1603+
auto LoopInvIt = find_if(Phi->incoming_values(), [&](Use &U) {
1604+
return U.get() != *SelectInstIt && TheLoop->isLoopInvariant(U.get());
1605+
});
1606+
if (LoopInvIt == Phi->incoming_values().end())
1607+
return false;
1608+
1609+
// Phi or Sel must be used only outside the loop,
1610+
// excluding if Phi use Sel or Sel use Phi
1611+
auto IsOnlyUsedOutsideLoop = [&](Value *V, Value *Ignore) {
1612+
return all_of(V->users(), [Ignore, TheLoop](User *U) {
1613+
if (U == Ignore)
1614+
return true;
1615+
if (auto *I = dyn_cast<Instruction>(U))
1616+
return !TheLoop->contains(I);
1617+
return true;
1618+
});
1619+
};
1620+
Instruction *Select = cast<SelectInst>(SelectInstIt->get());
1621+
Value *LoopInv = LoopInvIt->get();
1622+
if (!IsOnlyUsedOutsideLoop(Phi, Select) ||
1623+
!IsOnlyUsedOutsideLoop(Select, Phi))
1624+
return false;
1625+
1626+
CSA = CSADescriptor(Phi, Select, LoopInv);
1627+
return true;
1628+
}

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,8 @@ bool LoopVectorizationLegality::canVectorizeInstrs() {
891891
// Check if the PHI can be classified as a CSA PHI.
892892
if (EnableCSA || (TTI->enableCSAVectorization() &&
893893
EnableCSA.getNumOccurrences() == 0)) {
894-
if (auto CSADesc = CSADescriptor::isCSAPhi(Phi, TheLoop)) {
894+
CSADescriptor CSADesc;
895+
if (CSADescriptor::isCSAPhi(Phi, TheLoop, CSADesc)) {
895896
addCSAPhi(Phi, CSADesc, AllowedExit);
896897
continue;
897898
}
@@ -1887,7 +1888,7 @@ bool LoopVectorizationLegality::canFoldTailByMasking() const {
18871888
// TODO: handle non-reduction outside users when tail is folded by masking.
18881889
for (auto *AE : AllowedExit) {
18891890
// Check that all users of allowed exit values are inside the loop or
1890-
// are the live-out of a reduction or a CSA
1891+
// are the live-out of a reduction or a CSA.
18911892
if (ReductionLiveOuts.count(AE) || CSALiveOuts.count(AE))
18921893
continue;
18931894
for (User *U : AE->users()) {

llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h

+33-2
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ class VPBuilder {
174174
new VPInstruction(Opcode, Operands, WrapFlags, DL, Name));
175175
}
176176

177-
VPValue *createNot(VPValue *Operand, DebugLoc DL = {},
178-
const Twine &Name = "") {
177+
VPInstruction *createNot(VPValue *Operand, DebugLoc DL = {},
178+
const Twine &Name = "") {
179179
return createInstruction(VPInstruction::Not, {Operand}, DL, Name);
180180
}
181181

@@ -231,6 +231,37 @@ class VPBuilder {
231231
Ptr, Offset, VPRecipeWithIRFlags::GEPFlagsTy(true), DL, Name));
232232
}
233233

234+
VPInstruction *createCSAMaskPhi(VPValue *InitMask, DebugLoc DL,
235+
const Twine &Name) {
236+
return createInstruction(VPInstruction::CSAMaskPhi, {InitMask}, DL, Name);
237+
}
238+
239+
VPInstruction *createAnyOf(VPValue *Cond, DebugLoc DL, const Twine &Name) {
240+
return createInstruction(VPInstruction::AnyOf, {Cond}, DL, Name);
241+
}
242+
243+
VPInstruction *createCSAMaskSel(VPValue *Cond, VPValue *MaskPhi,
244+
VPValue *AnyOf, DebugLoc DL,
245+
const Twine &Name) {
246+
return createInstruction(VPInstruction::CSAMaskSel, {Cond, MaskPhi, AnyOf},
247+
DL, Name);
248+
}
249+
250+
VPInstruction *createAnyOfEVL(VPValue *Cond, VPValue *EVL, DebugLoc DL,
251+
const Twine &Name) {
252+
return createInstruction(VPInstruction::AnyOfEVL, {Cond, EVL}, DL, Name);
253+
}
254+
255+
VPInstruction *createCSAVLPhi(DebugLoc DL, const Twine &Name) {
256+
return createInstruction(VPInstruction::CSAVLPhi, {}, DL, Name);
257+
}
258+
259+
VPInstruction *createCSAVLSel(VPValue *AnyOfEVL, VPValue *VLPhi, VPValue *EVL,
260+
DebugLoc DL, const Twine &Name) {
261+
return createInstruction(VPInstruction::CSAVLSel, {AnyOfEVL, VLPhi, EVL},
262+
DL, Name);
263+
}
264+
234265
VPDerivedIVRecipe *createDerivedIV(InductionDescriptor::InductionKind Kind,
235266
FPMathOperator *FPBinOp, VPValue *Start,
236267
VPCanonicalIVPHIRecipe *CanonicalIV,

0 commit comments

Comments
 (0)