@@ -8130,34 +8130,6 @@ VPHeaderPHIRecipe *VPRecipeBuilder::tryToOptimizeInductionPHI(
8130
8130
return nullptr ;
8131
8131
}
8132
8132
8133
- VPWidenIntOrFpInductionRecipe *VPRecipeBuilder::tryToOptimizeInductionTruncate (
8134
- TruncInst *I, ArrayRef<VPValue *> Operands, VFRange &Range, VPlan &Plan) {
8135
- // Optimize the special case where the source is a constant integer
8136
- // induction variable. Notice that we can only optimize the 'trunc' case
8137
- // because (a) FP conversions lose precision, (b) sext/zext may wrap, and
8138
- // (c) other casts depend on pointer size.
8139
-
8140
- // Determine whether \p K is a truncation based on an induction variable that
8141
- // can be optimized.
8142
- auto isOptimizableIVTruncate =
8143
- [&](Instruction *K) -> std::function<bool (ElementCount)> {
8144
- return [=](ElementCount VF) -> bool {
8145
- return CM.isOptimizableIVTruncate (K, VF);
8146
- };
8147
- };
8148
-
8149
- if (LoopVectorizationPlanner::getDecisionAndClampRange (
8150
- isOptimizableIVTruncate (I), Range)) {
8151
-
8152
- auto *Phi = cast<PHINode>(I->getOperand (0 ));
8153
- const InductionDescriptor &II = *Legal->getIntOrFpInductionDescriptor (Phi);
8154
- VPValue *Start = Plan.getVPValueOrAddLiveIn (II.getStartValue ());
8155
- return createWidenInductionRecipes (Phi, I, Start, II, Plan, *PSE.getSE (),
8156
- *OrigLoop, Range);
8157
- }
8158
- return nullptr ;
8159
- }
8160
-
8161
8133
VPBlendRecipe *VPRecipeBuilder::tryToBlend (PHINode *Phi,
8162
8134
ArrayRef<VPValue *> Operands,
8163
8135
VPlanPtr &Plan) {
@@ -8291,6 +8263,70 @@ bool VPRecipeBuilder::shouldWiden(Instruction *I, VFRange &Range) const {
8291
8263
Range);
8292
8264
}
8293
8265
8266
+ VPWidenCastRecipe *VPRecipeBuilder::createCast (VPValue *V, Type *From,
8267
+ Type *To) {
8268
+ if (From == To)
8269
+ return nullptr ;
8270
+ Instruction::CastOps CastOpcode;
8271
+ if (To->isIntegerTy () && From->isIntegerTy ())
8272
+ CastOpcode = To->getPrimitiveSizeInBits () < From->getPrimitiveSizeInBits ()
8273
+ ? Instruction::Trunc
8274
+ : Instruction::ZExt;
8275
+ else if (To->isIntegerTy ())
8276
+ CastOpcode = Instruction::FPToUI;
8277
+ else
8278
+ CastOpcode = Instruction::UIToFP;
8279
+
8280
+ return new VPWidenCastRecipe (CastOpcode, V, To);
8281
+ }
8282
+
8283
+ VPRecipeBase *
8284
+ VPRecipeBuilder::createWidenStep (VPWidenIntOrFpInductionRecipe &WIV,
8285
+ ScalarEvolution &SE, VPlan &Plan,
8286
+ DenseSet<VPRecipeBase *> *CreatedRecipes) {
8287
+ PHINode *PN = WIV.getPHINode ();
8288
+ const InductionDescriptor &IndDesc = WIV.getInductionDescriptor ();
8289
+ VPValue *ScalarStep =
8290
+ vputils::getOrCreateVPValueForSCEVExpr (Plan, IndDesc.getStep (), SE);
8291
+ Type *VFxUFTy = Plan.getVFxUF ().getElementType ();
8292
+ Type *StepTy = IndDesc.getStep ()->getType ();
8293
+ VPValue *WidenVFxUF = &Plan.getWidenVFxUF ();
8294
+ VPBasicBlock *LatchVPBB = Plan.getVectorLoopRegion ()->getExitingBasicBlock ();
8295
+ if (VPWidenCastRecipe *WidenVFxUFCast =
8296
+ createCast (&Plan.getWidenVFxUF (), VFxUFTy, StepTy)) {
8297
+ WidenVFxUFCast->insertBefore (LatchVPBB->getTerminator ());
8298
+ if (CreatedRecipes)
8299
+ CreatedRecipes->insert (WidenVFxUFCast);
8300
+ WidenVFxUF = WidenVFxUFCast->getVPSingleValue ();
8301
+ }
8302
+ const Instruction::BinaryOps UpdateOp =
8303
+ IndDesc.getInductionOpcode () != Instruction::BinaryOpsEnd
8304
+ ? IndDesc.getInductionOpcode ()
8305
+ : Instruction::Add;
8306
+ VPInstruction *Update;
8307
+ if (StepTy->isIntegerTy ()) {
8308
+ VPInstruction *Mul = new VPInstruction (
8309
+ Instruction::Mul, {WidenVFxUF, ScalarStep}, PN->getDebugLoc ());
8310
+ Mul->insertBefore (LatchVPBB->getTerminator ());
8311
+ if (CreatedRecipes)
8312
+ CreatedRecipes->insert (Mul);
8313
+ Update = new VPInstruction (UpdateOp, {&WIV, Mul}, PN->getDebugLoc ());
8314
+ Update->insertBefore (LatchVPBB->getTerminator ());
8315
+ } else {
8316
+ FastMathFlags FMF = IndDesc.getExactFPMathInst ()
8317
+ ? IndDesc.getExactFPMathInst ()->getFastMathFlags ()
8318
+ : FastMathFlags ();
8319
+ VPInstruction *Mul = new VPInstruction (
8320
+ Instruction::FMul, {WidenVFxUF, ScalarStep}, FMF, PN->getDebugLoc ());
8321
+ Mul->insertBefore (LatchVPBB->getTerminator ());
8322
+ Update = new VPInstruction (UpdateOp, {&WIV, Mul}, FMF, PN->getDebugLoc ());
8323
+ Update->insertBefore (LatchVPBB->getTerminator ());
8324
+ }
8325
+ if (CreatedRecipes)
8326
+ CreatedRecipes->insert (Update);
8327
+ return Update;
8328
+ }
8329
+
8294
8330
VPWidenRecipe *VPRecipeBuilder::tryToWiden (Instruction *I,
8295
8331
ArrayRef<VPValue *> Operands,
8296
8332
VPBasicBlock *VPBB, VPlanPtr &Plan) {
@@ -8340,10 +8376,15 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I,
8340
8376
};
8341
8377
}
8342
8378
8343
- void VPRecipeBuilder::fixHeaderPhis () {
8379
+ void VPRecipeBuilder::fixHeaderPhis (VPlan &Plan ) {
8344
8380
BasicBlock *OrigLatch = OrigLoop->getLoopLatch ();
8345
8381
for (VPHeaderPHIRecipe *R : PhisToFix) {
8346
- auto *PN = cast<PHINode>(R->getUnderlyingValue ());
8382
+ if (auto *VPWIFR = dyn_cast<VPWidenIntOrFpInductionRecipe>(R)) {
8383
+ VPWIFR->addOperand (
8384
+ createWidenStep (*VPWIFR, *PSE.getSE (), Plan)->getVPSingleValue ());
8385
+ continue ;
8386
+ }
8387
+ PHINode *PN = cast<PHINode>(R->getUnderlyingValue ());
8347
8388
VPRecipeBase *IncR =
8348
8389
getRecipe (cast<Instruction>(PN->getIncomingValueForBlock (OrigLatch)));
8349
8390
R->addOperand (IncR->getVPSingleValue ());
@@ -8421,8 +8462,12 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe(
8421
8462
// can have earlier phis as incoming values.
8422
8463
recordRecipeOf (Phi);
8423
8464
8424
- if ((Recipe = tryToOptimizeInductionPHI (Phi, Operands, *Plan, Range)))
8465
+ if ((Recipe = tryToOptimizeInductionPHI (Phi, Operands, *Plan, Range))) {
8466
+ if (isa<VPWidenPointerInductionRecipe>(Recipe))
8467
+ return Recipe;
8468
+ PhisToFix.push_back (cast<VPWidenIntOrFpInductionRecipe>(Recipe));
8425
8469
return Recipe;
8470
+ }
8426
8471
8427
8472
VPHeaderPHIRecipe *PhiRecipe = nullptr ;
8428
8473
assert ((Legal->isReductionVariable (Phi) ||
@@ -8457,10 +8502,17 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe(
8457
8502
return PhiRecipe;
8458
8503
}
8459
8504
8460
- if (isa<TruncInst>(Instr) &&
8461
- (Recipe = tryToOptimizeInductionTruncate (cast<TruncInst>(Instr), Operands,
8462
- Range, *Plan)))
8463
- return Recipe;
8505
+ if (isa<TruncInst>(Instr)) {
8506
+ auto IsOptimizableIVTruncate =
8507
+ [&](Instruction *K) -> std::function<bool (ElementCount)> {
8508
+ return [=](ElementCount VF) -> bool {
8509
+ return CM.isOptimizableIVTruncate (K, VF);
8510
+ };
8511
+ };
8512
+
8513
+ LoopVectorizationPlanner::getDecisionAndClampRange (
8514
+ IsOptimizableIVTruncate (Instr), Range);
8515
+ }
8464
8516
8465
8517
// All widen recipes below deal only with VF > 1.
8466
8518
if (LoopVectorizationPlanner::getDecisionAndClampRange (
@@ -8718,7 +8770,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
8718
8770
!Plan->getVectorLoopRegion ()->getEntryBasicBlock ()->empty () &&
8719
8771
" entry block must be set to a VPRegionBlock having a non-empty entry "
8720
8772
" VPBasicBlock" );
8721
- RecipeBuilder.fixHeaderPhis ();
8773
+ RecipeBuilder.fixHeaderPhis (*Plan );
8722
8774
8723
8775
// ---------------------------------------------------------------------------
8724
8776
// Transform initial VPlan: Apply previously taken decisions, in order, to
0 commit comments