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 @@ -407,7 +407,11 @@ BasicBlock *createVectorizedLoopSkeleton(); /// Widen a single instruction within the innermost loop. - void widenInstruction(Instruction &I); + void + widenInstruction(Instruction &I, + std::function GetUnderlyingValue, + std::function GetScalarValue, + std::function GetVectorValue); /// Widen a single call instruction within the innermost loop. void widenCallInstruction(CallInst &I); @@ -4225,7 +4229,10 @@ return !CInt || CInt->isZero(); } -void InnerLoopVectorizer::widenInstruction(Instruction &I) { +void InnerLoopVectorizer::widenInstruction( + Instruction &I, std::function GetUnderlyingValue, + std::function GetScalarValue, + std::function GetVectorValue) { switch (I.getOpcode()) { case Instruction::Call: case Instruction::Br: @@ -4256,8 +4263,8 @@ for (unsigned Part = 0; Part < UF; ++Part) { SmallVector Ops; - for (Value *Op : I.operands()) - Ops.push_back(getOrCreateVectorValue(Op, Part)); + for (unsigned Idx = 0; Idx < I.getNumOperands(); Idx++) + Ops.push_back(GetVectorValue(Idx, Part)); Value *V = Builder.CreateNAryOp(I.getOpcode(), Ops); @@ -4277,7 +4284,7 @@ // instruction with a scalar condition. Otherwise, use vector-select. auto *SE = PSE.getSE(); bool InvariantCond = - SE->isLoopInvariant(PSE.getSCEV(I.getOperand(0)), OrigLoop); + SE->isLoopInvariant(PSE.getSCEV(GetUnderlyingValue(0)), OrigLoop); setDebugLocFromInst(Builder, &I); // The condition can be loop invariant but still defined inside the @@ -4285,12 +4292,12 @@ // We have to take the 'vectorized' value and pick the first lane. // Instcombine will make this a no-op. - auto *ScalarCond = getOrCreateScalarValue(I.getOperand(0), {0, 0}); + auto *ScalarCond = GetScalarValue(0, {0, 0}); for (unsigned Part = 0; Part < UF; ++Part) { - Value *Cond = getOrCreateVectorValue(I.getOperand(0), Part); - Value *Op0 = getOrCreateVectorValue(I.getOperand(1), Part); - Value *Op1 = getOrCreateVectorValue(I.getOperand(2), Part); + Value *Cond = GetVectorValue(0, Part); + Value *Op0 = GetVectorValue(1, Part); + Value *Op1 = GetVectorValue(2, Part); Value *Sel = Builder.CreateSelect(InvariantCond ? ScalarCond : Cond, Op0, Op1); VectorLoopValueMap.setVectorValue(&I, Part, Sel); @@ -4307,8 +4314,8 @@ auto *Cmp = cast(&I); setDebugLocFromInst(Builder, Cmp); for (unsigned Part = 0; Part < UF; ++Part) { - Value *A = getOrCreateVectorValue(Cmp->getOperand(0), Part); - Value *B = getOrCreateVectorValue(Cmp->getOperand(1), Part); + Value *A = GetVectorValue(0, Part); + Value *B = GetVectorValue(1, Part); Value *C = nullptr; if (FCmp) { // Propagate fast math flags. @@ -4345,7 +4352,7 @@ (VF == 1) ? CI->getType() : VectorType::get(CI->getType(), VF); for (unsigned Part = 0; Part < UF; ++Part) { - Value *A = getOrCreateVectorValue(CI->getOperand(0), Part); + Value *A = GetVectorValue(0, Part); Value *Cast = Builder.CreateCast(CI->getOpcode(), A, DestTy); VectorLoopValueMap.setVectorValue(&I, Part, Cast); addMetadata(Cast, &I); @@ -6922,7 +6929,8 @@ return new VPWidenCallRecipe(*CI); } -VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, VFRange &Range) { +VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, VFRange &Range, + VPlan &Plan) { bool IsPredicated = LoopVectorizationPlanner::getDecisionAndClampRange( [&](unsigned VF) { return CM.isScalarWithPredication(I, VF); }, Range); @@ -6994,7 +7002,11 @@ return nullptr; // Success: widen this instruction. - return new VPWidenRecipe(*I); + // Create VPValue operands. + auto VPValues = map_range( + I->operands(), [&Plan](Value *Op) { return Plan.getOrAddVPValue(Op); }); + SmallVector Values(VPValues.begin(), VPValues.end()); + return new VPWidenRecipe(*I, Values); } VPBasicBlock *VPRecipeBuilder::handleReplication( @@ -7099,7 +7111,7 @@ // Check if Instr is to be widened by a general VPWidenRecipe, after // having first checked for specific widening recipes. - if ((Recipe = tryToWiden(Instr, Range))) { + if ((Recipe = tryToWiden(Instr, Range, *Plan))) { setRecipe(Instr, Recipe); VPBB->appendRecipe(Recipe); return true; @@ -7394,7 +7406,19 @@ } void VPWidenRecipe::execute(VPTransformState &State) { - State.ILV->widenInstruction(Ingredient); + // Helpers to access VPValue operands. + auto GetUnderlyingValue = [this](unsigned OpIdx) { + return User.getOperand(OpIdx)->getUnderlyingValue(); + }; + auto GetVectorValue = [&State, this](unsigned OpIdx, unsigned Part) { + return State.get(User.getOperand(OpIdx), Part); + }; + auto GetScalarValue = [&State, this](unsigned OpIdx, VPIteration Instance) { + return State.get(User.getOperand(OpIdx), Instance); + }; + + State.ILV->widenInstruction(Ingredient, GetUnderlyingValue, GetScalarValue, + GetVectorValue); } void VPWidenGEPRecipe::execute(VPTransformState &State) { diff --git a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h --- a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h +++ b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h @@ -116,7 +116,7 @@ /// widened for \p Range.Start, build a new VPWidenRecipe and return it. /// Range.End may be decreased to ensure same decision from \p Range.Start to /// \p Range.End. - VPWidenRecipe *tryToWiden(Instruction *I, VFRange &Range); + VPWidenRecipe *tryToWiden(Instruction *I, VFRange &Range, VPlan &Plan); /// Create a replicating region for instruction \p I that requires /// predication. \p PredRecipe is a VPReplicateRecipe holding \p I. 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 @@ -766,8 +766,11 @@ /// Hold the instruction to be widened. Instruction &Ingredient; + VPUser User; + public: - VPWidenRecipe(Instruction &I) : VPRecipeBase(VPWidenSC), Ingredient(I) {} + VPWidenRecipe(Instruction &I, ArrayRef Operands) + : VPRecipeBase(VPWidenSC), Ingredient(I), User(Operands) {} ~VPWidenRecipe() override = default; diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -71,8 +71,14 @@ NewRecipe = new VPWidenPHIRecipe(Phi); } else if (GetElementPtrInst *GEP = dyn_cast(Inst)) { NewRecipe = new VPWidenGEPRecipe(GEP, OrigLoop); - } else - NewRecipe = new VPWidenRecipe(*Inst); + } else { + // Create VPValue operands. + auto VPValues = map_range(Inst->operands(), [&Plan](Value *Op) { + return Plan->getOrAddVPValue(Op); + }); + SmallVector Values(VPValues.begin(), VPValues.end()); + NewRecipe = new VPWidenRecipe(*Inst, Values); + } NewRecipe->insertBefore(Ingredient); Ingredient->eraseFromParent(); 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 @@ -43,6 +43,7 @@ friend class VPBasicBlock; friend class VPInterleavedAccessInfo; friend class VPSlotTracker; + friend class VPWidenRecipe; private: const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast).