-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[VPlan] Verify dominance for incoming values of phi-like recipes. #124838
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
b357af4
9113022
c61233f
a73a137
90b2d4d
f768b97
d6d6bb5
8dfd569
595b057
a2b4ebb
46780ab
5fee077
450901e
31eec38
60d5ec9
5554c6d
ba48230
8e60892
370eaf1
56d4784
d4317a8
d371f10
e5cf64d
5fa41af
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 | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -1135,7 +1135,9 @@ class VPPhiAccessors { | |||||||
const VPBasicBlock *getIncomingBlock(unsigned Idx) const; | ||||||||
|
||||||||
/// Returns the number of incoming values, also number of incoming blocks. | ||||||||
unsigned getNumIncoming() const { return getAsRecipe()->getNumOperands(); } | ||||||||
virtual unsigned getNumIncoming() const { | ||||||||
return getAsRecipe()->getNumOperands(); | ||||||||
} | ||||||||
|
||||||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||||
/// Print the recipe. | ||||||||
|
@@ -1234,7 +1236,7 @@ class VPIRInstruction : public VPRecipeBase { | |||||||
/// cast/dyn_cast/isa and execute() implementation. A single VPValue operand is | ||||||||
/// allowed, and it is used to add a new incoming value for the single | ||||||||
/// predecessor VPBB. | ||||||||
struct VPIRPhi : public VPIRInstruction { | ||||||||
struct VPIRPhi : public VPIRInstruction, public VPPhiAccessors { | ||||||||
VPIRPhi(PHINode &PN) : VPIRInstruction(PN) {} | ||||||||
|
||||||||
static inline bool classof(const VPRecipeBase *U) { | ||||||||
|
@@ -1251,6 +1253,9 @@ struct VPIRPhi : public VPIRInstruction { | |||||||
void print(raw_ostream &O, const Twine &Indent, | ||||||||
VPSlotTracker &SlotTracker) const override; | ||||||||
#endif | ||||||||
|
||||||||
protected: | ||||||||
const VPRecipeBase *getAsRecipe() const override { return this; } | ||||||||
}; | ||||||||
|
||||||||
/// Helper to manage IR metadata for recipes. It filters out metadata that | ||||||||
|
@@ -1785,13 +1790,15 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags, | |||||||
/// * VPWidenPointerInductionRecipe: Generate vector and scalar values for a | ||||||||
/// pointer induction. Produces either a vector PHI per-part or scalar values | ||||||||
/// per-lane based on the canonical induction. | ||||||||
class VPHeaderPHIRecipe : public VPSingleDefRecipe { | ||||||||
class VPHeaderPHIRecipe : public VPSingleDefRecipe, public VPPhiAccessors { | ||||||||
protected: | ||||||||
VPHeaderPHIRecipe(unsigned char VPDefID, Instruction *UnderlyingInstr, | ||||||||
VPValue *Start, DebugLoc DL = {}) | ||||||||
: VPSingleDefRecipe(VPDefID, ArrayRef<VPValue *>({Start}), UnderlyingInstr, DL) { | ||||||||
} | ||||||||
|
||||||||
const VPRecipeBase *getAsRecipe() const override { return this; } | ||||||||
|
||||||||
public: | ||||||||
~VPHeaderPHIRecipe() override = default; | ||||||||
|
||||||||
|
@@ -1980,6 +1987,11 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe { | |||||||
return isUnrolled() ? getOperand(getNumOperands() - 2) : nullptr; | ||||||||
} | ||||||||
|
||||||||
/// Returns the number of incoming values, also number of incoming blocks. | ||||||||
/// Note that at the moment, VPWidenIntOrFpInductionRecipes only have a single | ||||||||
/// incoming value, its start value. | ||||||||
unsigned getNumIncoming() const override { return 1; } | ||||||||
|
||||||||
/// Returns the first defined value as TruncInst, if it is one or nullptr | ||||||||
/// otherwise. | ||||||||
TruncInst *getTruncInst() { return Trunc; } | ||||||||
|
@@ -3283,6 +3295,46 @@ class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags, | |||||||
} | ||||||||
}; | ||||||||
|
||||||||
/// Casting from VPRecipeBase -> VPPhiAccessors is supported for all recipe | ||||||||
/// types implementing VPPhiAccessors. Used by isa<> & co. | ||||||||
template <> struct CastIsPossible<VPPhiAccessors, const VPRecipeBase *> { | ||||||||
static inline bool isPossible(const VPRecipeBase *f) { | ||||||||
// TODO: include VPPredInstPHIRecipe too, once it implements VPPhiAccessors. | ||||||||
return isa<VPIRPhi, VPHeaderPHIRecipe, VPWidenPHIRecipe, VPPhi>(f); | ||||||||
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. VPPredInstPHIRecipe might be another? 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. Yes, but I left it out for now because more work will be needed as there the operands also don't match the # of predecessors. |
||||||||
} | ||||||||
}; | ||||||||
/// Support casting from VPRecipeBase -> VPPhiAccessors, by down-casting to the | ||||||||
/// recipe types implementing VPPhiAccessors. Used by cast<>, dyn_cast<> & co. | ||||||||
template <> | ||||||||
struct CastInfo<VPPhiAccessors, const VPRecipeBase *> | ||||||||
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. Where is CastInfo used? 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 is used by |
||||||||
: public CastIsPossible<VPPhiAccessors, const VPRecipeBase *> { | ||||||||
|
||||||||
using Self = CastInfo<VPPhiAccessors, const VPRecipeBase *>; | ||||||||
|
||||||||
/// doCast is used by cast<>. | ||||||||
static inline VPPhiAccessors *doCast(const VPRecipeBase *R) { | ||||||||
return const_cast<VPPhiAccessors *>([R]() -> const VPPhiAccessors * { | ||||||||
switch (R->getVPDefID()) { | ||||||||
case VPDef::VPInstructionSC: | ||||||||
return cast<VPPhi>(R); | ||||||||
case VPDef::VPIRInstructionSC: | ||||||||
return cast<VPIRPhi>(R); | ||||||||
case VPDef::VPWidenPHISC: | ||||||||
return cast<VPWidenPHIRecipe>(R); | ||||||||
default: | ||||||||
return cast<VPHeaderPHIRecipe>(R); | ||||||||
Comment on lines
+3324
to
+3325
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. An unreachable default, or one that returns null for !isPossible cases, trigger const_cast failure? 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. VPHeaderPhiRecipe includes multiple recipes, which is why I put it in the default, to avoid missing cases if new ones get added. The cast should already verify and assert that the cast is possible. |
||||||||
} | ||||||||
}()); | ||||||||
} | ||||||||
|
||||||||
/// doCastIfPossible is used by dyn_cast<>. | ||||||||
static inline VPPhiAccessors *doCastIfPossible(const VPRecipeBase *f) { | ||||||||
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. Where is doCastIfPossible used? 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 is used by 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.
Suggested change
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. added thanks |
||||||||
if (!Self::isPossible(f)) | ||||||||
return nullptr; | ||||||||
return doCast(f); | ||||||||
} | ||||||||
}; | ||||||||
|
||||||||
/// VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph. It | ||||||||
/// holds a sequence of zero or more VPRecipe's each representing a sequence of | ||||||||
/// output IR instructions. All PHI-like recipes must come before any non-PHI recipes. | ||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -192,8 +192,7 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) { | |||||
if (!verifyPhiRecipes(VPBB)) | ||||||
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. Should the dominance verification of phi-like recipes take place inside 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 am not sure how we could move the new code to 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.
does the above second sentence from below still hold? 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. It should be complete now, updated, thanks! |
||||||
return false; | ||||||
|
||||||
// Verify that defs in VPBB dominate all their uses. The current | ||||||
// implementation is still incomplete. | ||||||
// Verify that defs in VPBB dominate all their uses. | ||||||
DenseMap<const VPRecipeBase *, unsigned> RecipeNumbering; | ||||||
unsigned Cnt = 0; | ||||||
for (const VPRecipeBase &R : *VPBB) | ||||||
|
@@ -220,12 +219,31 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) { | |||||
|
||||||
for (const VPUser *U : V->users()) { | ||||||
auto *UI = cast<VPRecipeBase>(U); | ||||||
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. unrelated nit:
Suggested change
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. Will fix independently. |
||||||
// TODO: check dominance of incoming values for phis properly. | ||||||
if (!UI || | ||||||
isa<VPHeaderPHIRecipe, VPWidenPHIRecipe, VPPredInstPHIRecipe, | ||||||
VPIRPhi>(UI) || | ||||||
(isa<VPInstruction>(UI) && | ||||||
cast<VPInstruction>(UI)->getOpcode() == Instruction::PHI)) | ||||||
if (auto *Phi = dyn_cast<VPPhiAccessors>(UI)) { | ||||||
for (unsigned Idx = 0; Idx != Phi->getNumIncoming(); ++Idx) { | ||||||
VPValue *IncomingVPV = Phi->getIncomingValue(Idx); | ||||||
if (IncomingVPV != V) | ||||||
continue; | ||||||
|
||||||
const VPBasicBlock *IncomingVPBB = Phi->getIncomingBlock(Idx); | ||||||
if (VPDT.dominates(VPBB, IncomingVPBB)) | ||||||
continue; | ||||||
|
||||||
errs() << "Incoming def at index " << Idx | ||||||
<< " does not dominate incoming block!\n"; | ||||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||
VPSlotTracker Tracker(VPBB->getPlan()); | ||||||
IncomingVPV->getDefiningRecipe()->print(errs(), " ", Tracker); | ||||||
errs() << "\n does not dominate " << IncomingVPBB->getName() | ||||||
<< " for\n"; | ||||||
UI->print(errs(), " ", Tracker); | ||||||
#endif | ||||||
return false; | ||||||
} | ||||||
continue; | ||||||
} | ||||||
// TODO: Also verify VPPredInstPHIRecipe. | ||||||
if (isa<VPPredInstPHIRecipe>(UI)) | ||||||
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. Anything to check? 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. Yep, added a TODO for now, thanks |
||||||
continue; | ||||||
|
||||||
// If the user is in the same block, check it comes after R in the | ||||||
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.
Suggested change
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. independent typo. 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. Yep can fix separately, thanks |
||||||
|
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.
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.
Added thanks