-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[VPlan] Separate out logic to manage IR flags to VPIRFlags (NFC). #140621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
bec85ec
3696842
1b729db
ff1b1e9
33efbe2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -164,25 +164,19 @@ class VPBuilder { | |
DebugLoc DL, const Twine &Name = "") { | ||
return createInstruction(Opcode, Operands, DL, Name); | ||
} | ||
VPInstruction *createNaryOp(unsigned Opcode, | ||
std::initializer_list<VPValue *> Operands, | ||
std::optional<FastMathFlags> FMFs = {}, | ||
DebugLoc DL = {}, const Twine &Name = "") { | ||
if (FMFs) | ||
return tryInsertInstruction( | ||
new VPInstruction(Opcode, Operands, *FMFs, DL, Name)); | ||
return createInstruction(Opcode, Operands, DL, Name); | ||
VPInstruction *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands, | ||
const VPIRFlags &Flags, DebugLoc DL = {}, | ||
const Twine &Name = "") { | ||
return tryInsertInstruction( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consistency nit: worth overloading |
||
new VPInstruction(Opcode, Operands, Flags, DL, Name)); | ||
} | ||
|
||
VPInstruction *createNaryOp(unsigned Opcode, | ||
std::initializer_list<VPValue *> Operands, | ||
Type *ResultTy, | ||
std::optional<FastMathFlags> FMFs = {}, | ||
Type *ResultTy, const VPIRFlags &Flags = {}, | ||
DebugLoc DL = {}, const Twine &Name = "") { | ||
if (FMFs) | ||
return tryInsertInstruction(new VPInstructionWithType( | ||
Opcode, Operands, ResultTy, *FMFs, DL, Name)); | ||
return tryInsertInstruction( | ||
new VPInstructionWithType(Opcode, Operands, ResultTy, DL, Name)); | ||
new VPInstructionWithType(Opcode, Operands, ResultTy, Flags, DL, Name)); | ||
} | ||
|
||
VPInstruction *createOverflowingOp(unsigned Opcode, | ||
|
@@ -236,18 +230,20 @@ class VPBuilder { | |
assert(Pred >= CmpInst::FIRST_ICMP_PREDICATE && | ||
Pred <= CmpInst::LAST_ICMP_PREDICATE && "invalid predicate"); | ||
return tryInsertInstruction( | ||
new VPInstruction(Instruction::ICmp, Pred, A, B, DL, Name)); | ||
new VPInstruction(Instruction::ICmp, {A, B}, Pred, DL, Name)); | ||
} | ||
|
||
VPInstruction *createPtrAdd(VPValue *Ptr, VPValue *Offset, DebugLoc DL = {}, | ||
const Twine &Name = "") { | ||
return tryInsertInstruction( | ||
new VPInstruction(Ptr, Offset, GEPNoWrapFlags::none(), DL, Name)); | ||
new VPInstruction(VPInstruction::PtrAdd, {Ptr, Offset}, | ||
GEPNoWrapFlags::none(), DL, Name)); | ||
} | ||
VPValue *createInBoundsPtrAdd(VPValue *Ptr, VPValue *Offset, DebugLoc DL = {}, | ||
const Twine &Name = "") { | ||
return tryInsertInstruction( | ||
new VPInstruction(Ptr, Offset, GEPNoWrapFlags::inBounds(), DL, Name)); | ||
new VPInstruction(VPInstruction::PtrAdd, {Ptr, Offset}, | ||
GEPNoWrapFlags::inBounds(), DL, Name)); | ||
} | ||
|
||
VPInstruction *createScalarPhi(ArrayRef<VPValue *> IncomingValues, | ||
|
@@ -269,7 +265,7 @@ class VPBuilder { | |
VPInstruction *createScalarCast(Instruction::CastOps Opcode, VPValue *Op, | ||
Type *ResultTy, DebugLoc DL) { | ||
return tryInsertInstruction( | ||
new VPInstructionWithType(Opcode, Op, ResultTy, DL)); | ||
new VPInstructionWithType(Opcode, Op, ResultTy, {}, DL)); | ||
} | ||
|
||
VPWidenCastRecipe *createWidenCast(Instruction::CastOps Opcode, VPValue *Op, | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -577,8 +577,8 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPValue { | |||||
#endif | ||||||
}; | ||||||
|
||||||
/// Class to record LLVM IR flag for a recipe along with it. | ||||||
class VPRecipeWithIRFlags : public VPSingleDefRecipe { | ||||||
/// Class to record and manage LLVM IR flags. | ||||||
class VPIRFlags { | ||||||
enum class OperationType : unsigned char { | ||||||
Cmp, | ||||||
OverflowingBinOp, | ||||||
|
@@ -637,23 +637,10 @@ class VPRecipeWithIRFlags : public VPSingleDefRecipe { | |||||
unsigned AllFlags; | ||||||
}; | ||||||
|
||||||
protected: | ||||||
void transferFlags(VPRecipeWithIRFlags &Other) { | ||||||
OpType = Other.OpType; | ||||||
AllFlags = Other.AllFlags; | ||||||
} | ||||||
|
||||||
public: | ||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL) { | ||||||
OpType = OperationType::Other; | ||||||
AllFlags = 0; | ||||||
} | ||||||
VPIRFlags() : OpType(OperationType::Other), AllFlags(0) {} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to document the interface here and below. |
||||||
|
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
Instruction &I) | ||||||
: VPSingleDefRecipe(SC, Operands, &I, I.getDebugLoc()) { | ||||||
VPIRFlags(Instruction &I) { | ||||||
if (auto *Op = dyn_cast<CmpInst>(&I)) { | ||||||
OpType = OperationType::Cmp; | ||||||
CmpPredicate = Op->getPredicate(); | ||||||
|
@@ -681,63 +668,27 @@ class VPRecipeWithIRFlags : public VPSingleDefRecipe { | |||||
} | ||||||
} | ||||||
|
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
CmpInst::Predicate Pred, DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::Cmp), | ||||||
CmpPredicate(Pred) {} | ||||||
VPIRFlags(CmpInst::Predicate Pred) | ||||||
: OpType(OperationType::Cmp), CmpPredicate(Pred) {} | ||||||
|
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
WrapFlagsTy WrapFlags, DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), | ||||||
OpType(OperationType::OverflowingBinOp), WrapFlags(WrapFlags) {} | ||||||
VPIRFlags(WrapFlagsTy WrapFlags) | ||||||
: OpType(OperationType::OverflowingBinOp), WrapFlags(WrapFlags) {} | ||||||
|
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
FastMathFlags FMFs, DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::FPMathOp), | ||||||
FMFs(FMFs) {} | ||||||
VPIRFlags(FastMathFlags FMFs) : OpType(OperationType::FPMathOp), FMFs(FMFs) {} | ||||||
|
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
DisjointFlagsTy DisjointFlags, DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::DisjointOp), | ||||||
DisjointFlags(DisjointFlags) {} | ||||||
VPIRFlags(DisjointFlagsTy DisjointFlags) | ||||||
: OpType(OperationType::DisjointOp), DisjointFlags(DisjointFlags) {} | ||||||
|
||||||
template <typename IterT> | ||||||
VPRecipeWithIRFlags(const unsigned char SC, IterT Operands, | ||||||
NonNegFlagsTy NonNegFlags, DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::NonNegOp), | ||||||
NonNegFlags(NonNegFlags) {} | ||||||
VPIRFlags(NonNegFlagsTy NonNegFlags) | ||||||
: OpType(OperationType::NonNegOp), NonNegFlags(NonNegFlags) {} | ||||||
|
||||||
protected: | ||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
GEPNoWrapFlags GEPFlags, DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::GEPOp), | ||||||
GEPFlags(GEPFlags) {} | ||||||
VPIRFlags(GEPNoWrapFlags GEPFlags) | ||||||
: OpType(OperationType::GEPOp), GEPFlags(GEPFlags) {} | ||||||
|
||||||
public: | ||||||
static inline bool classof(const VPRecipeBase *R) { | ||||||
return R->getVPDefID() == VPRecipeBase::VPInstructionSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenGEPSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenCallSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenCastSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenIntrinsicSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPReductionSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPReductionEVLSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPReplicateSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPVectorEndPointerSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPVectorPointerSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPExtendedReductionSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPMulAccumulateReductionSC; | ||||||
} | ||||||
|
||||||
static inline bool classof(const VPUser *U) { | ||||||
auto *R = dyn_cast<VPRecipeBase>(U); | ||||||
return R && classof(R); | ||||||
} | ||||||
|
||||||
static inline bool classof(const VPValue *V) { | ||||||
auto *R = dyn_cast_or_null<VPRecipeBase>(V->getDefiningRecipe()); | ||||||
return R && classof(R); | ||||||
void transferFlags(VPIRFlags &Other) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now Used only by recipe |
||||||
OpType = Other.OpType; | ||||||
AllFlags = Other.AllFlags; | ||||||
} | ||||||
|
||||||
/// Drop all poison-generating flags. | ||||||
|
@@ -851,11 +802,60 @@ class VPRecipeWithIRFlags : public VPSingleDefRecipe { | |||||
return DisjointFlags.IsDisjoint; | ||||||
} | ||||||
|
||||||
#if !defined(NDEBUG) | ||||||
/// Returns true if the set flags are valid for \p Opcode. | ||||||
bool flagsValidForOpcode(unsigned Opcode) const; | ||||||
#endif | ||||||
|
||||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||
void printFlags(raw_ostream &O) const; | ||||||
#endif | ||||||
}; | ||||||
|
||||||
/// A pure-virtual common base class for recipes defining a single VPValue and | ||||||
/// using IR flags. | ||||||
struct VPRecipeWithIRFlags : public VPSingleDefRecipe, public VPIRFlags { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This retains existing name, but perhaps |
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), VPIRFlags() {} | ||||||
|
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
Instruction &I) | ||||||
: VPSingleDefRecipe(SC, Operands, &I, I.getDebugLoc()), VPIRFlags(I) {} | ||||||
|
||||||
VPRecipeWithIRFlags(const unsigned char SC, ArrayRef<VPValue *> Operands, | ||||||
const VPIRFlags &Flags, DebugLoc DL = {}) | ||||||
: VPSingleDefRecipe(SC, Operands, DL), VPIRFlags(Flags) {} | ||||||
|
||||||
static inline bool classof(const VPRecipeBase *R) { | ||||||
return R->getVPDefID() == VPRecipeBase::VPInstructionSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenGEPSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenCallSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenCastSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPWidenIntrinsicSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPReductionSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPReductionEVLSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPReplicateSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPVectorEndPointerSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPVectorPointerSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPExtendedReductionSC || | ||||||
R->getVPDefID() == VPRecipeBase::VPMulAccumulateReductionSC; | ||||||
} | ||||||
|
||||||
static inline bool classof(const VPUser *U) { | ||||||
auto *R = dyn_cast<VPRecipeBase>(U); | ||||||
return R && classof(R); | ||||||
} | ||||||
|
||||||
static inline bool classof(const VPValue *V) { | ||||||
auto *R = dyn_cast_or_null<VPRecipeBase>(V->getDefiningRecipe()); | ||||||
return R && classof(R); | ||||||
} | ||||||
|
||||||
void execute(VPTransformState &State) override = 0; | ||||||
}; | ||||||
|
||||||
/// Helper to access the operand that contains the unroll part for this recipe | ||||||
/// after unrolling. | ||||||
template <unsigned PartOpIdx> class VPUnrollPartAccessor { | ||||||
|
@@ -958,54 +958,21 @@ class VPInstruction : public VPRecipeWithIRFlags, | |||||
/// value for lane \p Lane. | ||||||
Value *generatePerLane(VPTransformState &State, const VPLane &Lane); | ||||||
|
||||||
#if !defined(NDEBUG) | ||||||
/// Return true if the VPInstruction is a floating point math operation, i.e. | ||||||
/// has fast-math flags. | ||||||
bool isFPMathOp() const; | ||||||
#endif | ||||||
|
||||||
public: | ||||||
VPInstruction(unsigned Opcode, ArrayRef<VPValue *> Operands, DebugLoc DL, | ||||||
VPInstruction(unsigned Opcode, ArrayRef<VPValue *> Operands, DebugLoc DL = {}, | ||||||
const Twine &Name = "") | ||||||
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DL), | ||||||
Opcode(Opcode), Name(Name.str()) {} | ||||||
|
||||||
VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands, | ||||||
DebugLoc DL = {}, const Twine &Name = "") | ||||||
: VPInstruction(Opcode, ArrayRef<VPValue *>(Operands), DL, Name) {} | ||||||
|
||||||
VPInstruction(unsigned Opcode, CmpInst::Predicate Pred, VPValue *A, | ||||||
VPValue *B, DebugLoc DL = {}, const Twine &Name = ""); | ||||||
|
||||||
VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands, | ||||||
WrapFlagsTy WrapFlags, DebugLoc DL = {}, const Twine &Name = "") | ||||||
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, WrapFlags, DL), | ||||||
Opcode(Opcode), Name(Name.str()) {} | ||||||
|
||||||
VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands, | ||||||
DisjointFlagsTy DisjointFlag, DebugLoc DL = {}, | ||||||
const Twine &Name = "") | ||||||
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DisjointFlag, DL), | ||||||
Opcode(Opcode), Name(Name.str()) { | ||||||
assert(Opcode == Instruction::Or && "only OR opcodes can be disjoint"); | ||||||
} | ||||||
|
||||||
VPInstruction(VPValue *Ptr, VPValue *Offset, GEPNoWrapFlags Flags, | ||||||
DebugLoc DL = {}, const Twine &Name = "") | ||||||
: VPRecipeWithIRFlags(VPDef::VPInstructionSC, | ||||||
ArrayRef<VPValue *>({Ptr, Offset}), Flags, DL), | ||||||
Opcode(VPInstruction::PtrAdd), Name(Name.str()) {} | ||||||
|
||||||
VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands, | ||||||
FastMathFlags FMFs, DebugLoc DL = {}, const Twine &Name = ""); | ||||||
VPInstruction(unsigned Opcode, ArrayRef<VPValue *> Operands, | ||||||
const VPIRFlags &Flags, DebugLoc DL = {}, | ||||||
const Twine &Name = ""); | ||||||
|
||||||
VP_CLASSOF_IMPL(VPDef::VPInstructionSC) | ||||||
|
||||||
VPInstruction *clone() override { | ||||||
SmallVector<VPValue *, 2> Operands(operands()); | ||||||
auto *New = new VPInstruction(Opcode, Operands, getDebugLoc(), Name); | ||||||
New->transferFlags(*this); | ||||||
return New; | ||||||
return new VPInstruction(Opcode, Operands, *this, getDebugLoc(), Name); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would this
Suggested change
also work? Additional instances below. |
||||||
} | ||||||
|
||||||
unsigned getOpcode() const { return Opcode; } | ||||||
|
@@ -1082,13 +1049,9 @@ class VPInstructionWithType : public VPInstruction { | |||||
|
||||||
public: | ||||||
VPInstructionWithType(unsigned Opcode, ArrayRef<VPValue *> Operands, | ||||||
Type *ResultTy, DebugLoc DL, const Twine &Name = "") | ||||||
: VPInstruction(Opcode, Operands, DL, Name), ResultTy(ResultTy) {} | ||||||
VPInstructionWithType(unsigned Opcode, | ||||||
std::initializer_list<VPValue *> Operands, | ||||||
Type *ResultTy, FastMathFlags FMFs, DebugLoc DL = {}, | ||||||
Type *ResultTy, const VPIRFlags &Flags, DebugLoc DL, | ||||||
const Twine &Name = "") | ||||||
: VPInstruction(Opcode, Operands, FMFs, DL, Name), ResultTy(ResultTy) {} | ||||||
: VPInstruction(Opcode, Operands, Flags, DL, Name), ResultTy(ResultTy) {} | ||||||
lukel97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
static inline bool classof(const VPRecipeBase *R) { | ||||||
// VPInstructionWithType are VPInstructions with specific opcodes requiring | ||||||
|
@@ -1113,8 +1076,9 @@ class VPInstructionWithType : public VPInstruction { | |||||
|
||||||
VPInstruction *clone() override { | ||||||
SmallVector<VPValue *, 2> Operands(operands()); | ||||||
auto *New = new VPInstructionWithType( | ||||||
getOpcode(), Operands, getResultType(), getDebugLoc(), getName()); | ||||||
auto *New = | ||||||
new VPInstructionWithType(getOpcode(), Operands, getResultType(), *this, | ||||||
lukel97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
getDebugLoc(), getName()); | ||||||
New->setUnderlyingValue(getUnderlyingValue()); | ||||||
return New; | ||||||
} | ||||||
|
@@ -1373,15 +1337,12 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags, public VPIRMetadata { | |||||
} | ||||||
|
||||||
VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy, | ||||||
DebugLoc DL = {}) | ||||||
: VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, DL), VPIRMetadata(), | ||||||
Opcode(Opcode), ResultTy(ResultTy) {} | ||||||
|
||||||
VPWidenCastRecipe(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy, | ||||||
bool IsNonNeg, DebugLoc DL = {}) | ||||||
: VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, NonNegFlagsTy(IsNonNeg), | ||||||
DL), | ||||||
Opcode(Opcode), ResultTy(ResultTy) {} | ||||||
const VPIRFlags &Flags = {}, DebugLoc DL = {}) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I presume changing the bool to VPIRFlags is to bring it inline with VPInstructionWithType, so we can replace it in #129712? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
: VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, Flags, DL), | ||||||
VPIRMetadata(), Opcode(Opcode), ResultTy(ResultTy) { | ||||||
assert(flagsValidForOpcode(Opcode) && | ||||||
"Set flags not supported for the provided opcode"); | ||||||
} | ||||||
|
||||||
~VPWidenCastRecipe() override = default; | ||||||
|
||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, also above between lines 162,163