From 64c733fe5d75d8117dd32a70c4778551709c56a0 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 23 Sep 2020 14:44:31 +0100 Subject: [PATCH] [VPlan] Disconnect VPValue and VPUser. This refactors VPuser to not inherit from VPValue to facilitate introducing operations that introduce multiple VPValues (e.g. VPInterleaveRecipe). Reviewed By: Ayal Differential Revision: https://reviews.llvm.org/D84679 --- docs/Proposals/VectorizationPlan.rst | 6 ++---- lib/Transforms/Vectorize/VPlan.h | 4 ++-- lib/Transforms/Vectorize/VPlanSLP.cpp | 19 ++++++++++-------- lib/Transforms/Vectorize/VPlanValue.h | 28 +++++++++------------------ 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/docs/Proposals/VectorizationPlan.rst b/docs/Proposals/VectorizationPlan.rst index 6d6a38890c0..76469f80545 100644 --- a/docs/Proposals/VectorizationPlan.rst +++ b/docs/Proposals/VectorizationPlan.rst @@ -151,10 +151,8 @@ The low-level design of VPlan comprises of the following classes. VPUser, but no operands. :VPUser: - A VPValue representing a general vertex in the def-use graph of VPlan. It has - operands which are of type VPValue. When instantiated, it represents a - live-out Instruction that exists outside VPlan. VPUser is similar in some - aspects to LLVM's User class. + A VPUser represents an entity that uses a number of VPValues as operands. + VPUser is similar in some aspects to LLVM's User class. :VPInstruction: A VPInstruction is both a VPRecipe and a VPUser. It models a single diff --git a/lib/Transforms/Vectorize/VPlan.h b/lib/Transforms/Vectorize/VPlan.h index cdc18266f4e..9d1368e6c32 100644 --- a/lib/Transforms/Vectorize/VPlan.h +++ b/lib/Transforms/Vectorize/VPlan.h @@ -682,7 +682,7 @@ public: /// While as any Recipe it may generate a sequence of IR instructions when /// executed, these instructions would always form a single-def expression as /// the VPInstruction is also a single def-use vertex. -class VPInstruction : public VPUser, public VPRecipeBase { +class VPInstruction : public VPUser, public VPValue, public VPRecipeBase { friend class VPlanSlp; public: @@ -712,7 +712,7 @@ protected: public: VPInstruction(unsigned Opcode, ArrayRef Operands) - : VPUser(VPValue::VPInstructionSC, Operands), + : VPUser(Operands), VPValue(VPValue::VPInstructionSC), VPRecipeBase(VPRecipeBase::VPInstructionSC), Opcode(Opcode) {} VPInstruction(unsigned Opcode, std::initializer_list Operands) diff --git a/lib/Transforms/Vectorize/VPlanSLP.cpp b/lib/Transforms/Vectorize/VPlanSLP.cpp index b072ca9c392..2abe8a86844 100644 --- a/lib/Transforms/Vectorize/VPlanSLP.cpp +++ b/lib/Transforms/Vectorize/VPlanSLP.cpp @@ -161,7 +161,8 @@ static SmallVector getOperands(ArrayRef Values, unsigned OperandIndex) { SmallVector Operands; for (VPValue *V : Values) { - auto *U = cast(V); + // Currently we only support VPInstructions. + auto *U = cast(V); Operands.push_back(U->getOperand(OperandIndex)); } return Operands; @@ -222,18 +223,20 @@ static bool areConsecutiveOrMatch(VPInstruction *A, VPInstruction *B, /// Traverses and compares operands of V1 and V2 to MaxLevel. static unsigned getLAScore(VPValue *V1, VPValue *V2, unsigned MaxLevel, VPInterleavedAccessInfo &IAI) { - if (!isa(V1) || !isa(V2)) + auto *I1 = dyn_cast(V1); + auto *I2 = dyn_cast(V2); + // Currently we only support VPInstructions. + if (!I1 || !I2) return 0; if (MaxLevel == 0) - return (unsigned)areConsecutiveOrMatch(cast(V1), - cast(V2), IAI); + return (unsigned)areConsecutiveOrMatch(I1, I2, IAI); unsigned Score = 0; - for (unsigned I = 0, EV1 = cast(V1)->getNumOperands(); I < EV1; ++I) - for (unsigned J = 0, EV2 = cast(V2)->getNumOperands(); J < EV2; ++J) - Score += getLAScore(cast(V1)->getOperand(I), - cast(V2)->getOperand(J), MaxLevel - 1, IAI); + for (unsigned I = 0, EV1 = I1->getNumOperands(); I < EV1; ++I) + for (unsigned J = 0, EV2 = I2->getNumOperands(); J < EV2; ++J) + Score += + getLAScore(I1->getOperand(I), I2->getOperand(J), MaxLevel - 1, IAI); return Score; } diff --git a/lib/Transforms/Vectorize/VPlanValue.h b/lib/Transforms/Vectorize/VPlanValue.h index 3fec4d603c2..3274b6cf979 100644 --- a/lib/Transforms/Vectorize/VPlanValue.h +++ b/lib/Transforms/Vectorize/VPlanValue.h @@ -10,9 +10,9 @@ /// This file contains the declarations of the entities induced by Vectorization /// Plans, e.g. the instructions the VPlan intends to generate if executed. /// VPlan models the following entities: -/// VPValue -/// |-- VPUser -/// | |-- VPInstruction +/// VPValue VPUser +/// | | +/// VPInstruction /// These are documented in docs/VectorizationPlan.rst. /// //===----------------------------------------------------------------------===// @@ -76,7 +76,7 @@ public: /// are actually instantiated. Values of this enumeration are kept in the /// SubclassID field of the VPValue objects. They are used for concrete /// type identification. - enum { VPValueSC, VPUserSC, VPInstructionSC }; + enum { VPValueSC, VPInstructionSC }; VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV) {} VPValue(const VPValue &) = delete; @@ -132,23 +132,19 @@ raw_ostream &operator<<(raw_ostream &OS, const VPValue &V); /// This class augments VPValue with operands which provide the inverse def-use /// edges from VPValue's users to their defs. -class VPUser : public VPValue { +class VPUser { SmallVector Operands; -protected: - VPUser(const unsigned char SC) : VPValue(SC) {} - VPUser(const unsigned char SC, ArrayRef Operands) : VPValue(SC) { +public: + VPUser() {} + VPUser(ArrayRef Operands) { for (VPValue *Operand : Operands) addOperand(Operand); } -public: - VPUser() : VPValue(VPValue::VPUserSC) {} - VPUser(ArrayRef Operands) : VPUser(VPValue::VPUserSC, Operands) {} VPUser(std::initializer_list Operands) : VPUser(ArrayRef(Operands)) {} - template - VPUser(iterator_range Operands) : VPValue(VPValue::VPUserSC) { + template VPUser(iterator_range Operands) { for (VPValue *Operand : Operands) addOperand(Operand); } @@ -156,12 +152,6 @@ public: VPUser(const VPUser &) = delete; VPUser &operator=(const VPUser &) = delete; - /// Method to support type inquiry through isa, cast, and dyn_cast. - static inline bool classof(const VPValue *V) { - return V->getVPValueID() >= VPUserSC && - V->getVPValueID() <= VPInstructionSC; - } - void addOperand(VPValue *Operand) { Operands.push_back(Operand); Operand->addUser(*this);