diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -8433,11 +8433,10 @@ if (auto Recipe = RecipeBuilder.tryToCreateWidenRecipe(Instr, Range, Plan)) { - // Check if the recipe can be converted to a VPValue. We need the extra - // down-casting step until VPRecipeBase inherits from VPValue. - VPValue *MaybeVPValue = Recipe->toVPValue(); - if (!Instr->getType()->isVoidTy() && MaybeVPValue) - Plan->addVPValue(Instr, MaybeVPValue); + for (auto *Def : Recipe->definedValues()) { + auto *UV = Def->getUnderlyingValue(); + Plan->addVPValue(UV, Def); + } RecipeBuilder.setRecipe(Instr, Recipe); VPBB->appendRecipe(Recipe); @@ -8613,10 +8612,11 @@ : nullptr; VPReductionRecipe *RedRecipe = new VPReductionRecipe( &RdxDesc, R, ChainOp, VecOp, CondOp, Legal->hasFunNoNaNAttr(), TTI); - WidenRecipe->toVPValue()->replaceAllUsesWith(RedRecipe); + WidenRecipe->getVPValue()->replaceAllUsesWith(RedRecipe); Plan->removeVPValueFor(R); Plan->addVPValue(R, RedRecipe); WidenRecipe->getParent()->insert(RedRecipe, WidenRecipe->getIterator()); + WidenRecipe->getVPValue()->replaceAllUsesWith(RedRecipe); WidenRecipe->eraseFromParent(); if (Kind == RecurrenceDescriptor::RK_IntegerMinMax || @@ -8625,7 +8625,7 @@ RecipeBuilder.getRecipe(cast(R->getOperand(0))); assert(isa(CompareRecipe) && "Expected to replace a VPWidenSC"); - assert(CompareRecipe->toVPValue()->getNumUsers() == 0 && + assert(cast(CompareRecipe)->getNumUsers() == 0 && "Expected no remaining users"); CompareRecipe->eraseFromParent(); } @@ -8862,7 +8862,7 @@ void VPWidenMemoryInstructionRecipe::execute(VPTransformState &State) { VPValue *StoredValue = isStore() ? getStoredValue() : nullptr; State.ILV->vectorizeMemoryInstruction(&Ingredient, State, - StoredValue ? nullptr : toVPValue(), + StoredValue ? nullptr : getVPValue(), getAddr(), StoredValue, getMask()); } diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -677,22 +677,13 @@ /// nullptr otherwise. VPUser *toVPUser(); - /// Returns a pointer to a VPValue, if the recipe inherits from VPValue or - /// nullptr otherwise. - VPValue *toVPValue(); - const VPValue *toVPValue() const; - /// Returns the underlying instruction, if the recipe is a VPValue or nullptr /// otherwise. Instruction *getUnderlyingInstr() { - if (auto *VPV = toVPValue()) - return cast_or_null(VPV->getUnderlyingValue()); - return nullptr; + return cast(getVPValue()->getUnderlyingValue()); } const Instruction *getUnderlyingInstr() const { - if (auto *VPV = toVPValue()) - return cast_or_null(VPV->getUnderlyingValue()); - return nullptr; + return cast(getVPValue()->getUnderlyingValue()); } /// Method to support type inquiry through isa, cast, and dyn_cast. @@ -720,7 +711,7 @@ /// 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 VPValue, public VPUser, public VPRecipeBase { +class VPInstruction : public VPRecipeBase, public VPUser, public VPValue { friend class VPlanSlp; public: @@ -746,12 +737,12 @@ public: VPInstruction(unsigned Opcode, ArrayRef Operands) - : VPValue(VPValue::VPVInstructionSC), VPUser(Operands), - VPRecipeBase(VPRecipeBase::VPInstructionSC), Opcode(Opcode) {} + : VPRecipeBase(VPRecipeBase::VPInstructionSC), VPUser(Operands), + VPValue(VPValue::VPVInstructionSC, nullptr, this), Opcode(Opcode) {} VPInstruction(unsigned Opcode, ArrayRef Operands) - : VPValue(VPValue::VPVInstructionSC), VPUser({}), - VPRecipeBase(VPRecipeBase::VPInstructionSC), Opcode(Opcode) { + : VPRecipeBase(VPRecipeBase::VPInstructionSC), VPUser({}), + VPValue(VPValue::VPVInstructionSC, nullptr, this), Opcode(Opcode) { for (auto *I : Operands) addOperand(I->getVPValue()); } diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp --- a/llvm/lib/Transforms/Vectorize/VPlan.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp @@ -119,22 +119,6 @@ return nullptr; } -VPValue *VPRecipeBase::toVPValue() { - if (getNumDefinedValues() == 1) - return getVPValue(); - if (auto *V = dyn_cast(this)) - return V; - return nullptr; -} - -const VPValue *VPRecipeBase::toVPValue() const { - if (getNumDefinedValues() == 1) - return getVPValue(); - if (auto *V = dyn_cast(this)) - return V; - return nullptr; -} - // Get the top-most entry block of \p Start. This is the entry block of the // containing VPlan. This function is templated to support both const and non-const blocks template static T *getPlanEntry(T *Start) { @@ -352,12 +336,8 @@ void VPBasicBlock::dropAllReferences(VPValue *NewValue) { for (VPRecipeBase &R : Recipes) { - if (VPValue *Def = R.toVPValue()) + for (auto *Def : R.definedValues()) Def->replaceAllUsesWith(NewValue); - else if (auto *IR = dyn_cast(&R)) { - for (auto *Def : IR->definedValues()) - Def->replaceAllUsesWith(NewValue); - } if (auto *User = R.toVPUser()) for (unsigned I = 0, E = User->getNumOperands(); I != E; I++) diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h --- a/llvm/lib/Transforms/Vectorize/VPlanValue.h +++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h @@ -75,10 +75,6 @@ // for multiple underlying IRs (Polly?) by providing a new VPlan front-end, // back-end and analysis information for the new IR. - /// Return the underlying Value attached to this VPValue. - Value *getUnderlyingValue() { return UnderlyingVal; } - const Value *getUnderlyingValue() const { return UnderlyingVal; } - // Set \p Val as the underlying Value of this VPValue. void setUnderlyingValue(Value *Val) { assert(!UnderlyingVal && "Underlying Value is already set."); @@ -86,6 +82,10 @@ } public: + /// Return the underlying Value attached to this VPValue. + Value *getUnderlyingValue() { return UnderlyingVal; } + const Value *getUnderlyingValue() const { return UnderlyingVal; } + /// An enumeration for keeping track of the concrete subclass of VPValue that /// are actually instantiated. Values of this enumeration are kept in the /// SubclassID field of the VPValue objects. They are used for concrete