Skip to content

Commit 02f8262

Browse files
committed
Support WidenFFLoad in early-exit loop
1 parent 2be906b commit 02f8262

File tree

9 files changed

+481
-5
lines changed

9 files changed

+481
-5
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,12 @@ static cl::opt<bool> EnableEarlyExitVectorization(
393393
cl::desc(
394394
"Enable vectorization of early exit loops with uncountable exits."));
395395

396+
static cl::opt<bool>
397+
EnableEarlyExitWithFFLoads("enable-early-exit-with-ffload", cl::init(false),
398+
cl::Hidden,
399+
cl::desc("Enable vectorization of early-exit "
400+
"loops with fault-only-first loads."));
401+
396402
static cl::opt<bool> ConsiderRegPressure(
397403
"vectorizer-consider-reg-pressure", cl::init(false), cl::Hidden,
398404
cl::desc("Discard VFs if their register pressure is too high."));
@@ -3485,6 +3491,15 @@ LoopVectorizationCostModel::computeMaxVF(ElementCount UserVF, unsigned UserIC) {
34853491
return FixedScalableVFPair::getNone();
34863492
}
34873493

3494+
if (!Legal->getPotentiallyFaultingLoads().empty() && UserIC > 1) {
3495+
reportVectorizationFailure("Auto-vectorization of loops with potentially "
3496+
"faulting loads is not supported when the "
3497+
"interleave count is more than 1",
3498+
"CantInterleaveLoopWithPotentiallyFaultingLoads",
3499+
ORE, TheLoop);
3500+
return FixedScalableVFPair::getNone();
3501+
}
3502+
34883503
ScalarEvolution *SE = PSE.getSE();
34893504
ElementCount TC = getSmallConstantTripCount(SE, TheLoop);
34903505
unsigned MaxTC = PSE.getSmallConstantMaxTripCount();
@@ -4054,6 +4069,7 @@ static bool willGenerateVectors(VPlan &Plan, ElementCount VF,
40544069
case VPDef::VPReductionPHISC:
40554070
case VPDef::VPInterleaveEVLSC:
40564071
case VPDef::VPInterleaveSC:
4072+
case VPDef::VPWidenFFLoadSC:
40574073
case VPDef::VPWidenLoadEVLSC:
40584074
case VPDef::VPWidenLoadSC:
40594075
case VPDef::VPWidenStoreEVLSC:
@@ -4528,6 +4544,10 @@ LoopVectorizationPlanner::selectInterleaveCount(VPlan &Plan, ElementCount VF,
45284544
if (!Legal->isSafeForAnyVectorWidth())
45294545
return 1;
45304546

4547+
// No interleaving for potentially faulting loads.
4548+
if (!Legal->getPotentiallyFaultingLoads().empty())
4549+
return 1;
4550+
45314551
// We don't attempt to perform interleaving for loops with uncountable early
45324552
// exits because the VPInstruction::AnyOf code cannot currently handle
45334553
// multiple parts.
@@ -7213,6 +7233,9 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
72137233
// Regions are dissolved after optimizing for VF and UF, which completely
72147234
// removes unneeded loop regions first.
72157235
VPlanTransforms::dissolveLoopRegions(BestVPlan);
7236+
7237+
VPlanTransforms::convertFFLoadEarlyExitToVLStepping(BestVPlan);
7238+
72167239
// Canonicalize EVL loops after regions are dissolved.
72177240
VPlanTransforms::canonicalizeEVLLoops(BestVPlan);
72187241
VPlanTransforms::materializeBackedgeTakenCount(BestVPlan, VectorPH);
@@ -7500,6 +7523,10 @@ VPRecipeBuilder::tryToWidenMemory(Instruction *I, ArrayRef<VPValue *> Operands,
75007523
Builder.insert(VectorPtr);
75017524
Ptr = VectorPtr;
75027525
}
7526+
if (Legal->getPotentiallyFaultingLoads().contains(I))
7527+
return new VPWidenFFLoadRecipe(*cast<LoadInst>(I), Ptr, &Plan.getVF(), Mask,
7528+
VPIRMetadata(*I, LVer), I->getDebugLoc());
7529+
75037530
if (LoadInst *Load = dyn_cast<LoadInst>(I))
75047531
return new VPWidenLoadRecipe(*Load, Ptr, Mask, Consecutive, Reverse,
75057532
VPIRMetadata(*Load, LVer), I->getDebugLoc());
@@ -8538,6 +8565,10 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
85388565
if (Recipe->getNumDefinedValues() == 1) {
85398566
SingleDef->replaceAllUsesWith(Recipe->getVPSingleValue());
85408567
Old2New[SingleDef] = Recipe->getVPSingleValue();
8568+
} else if (isa<VPWidenFFLoadRecipe>(Recipe)) {
8569+
VPValue *Data = Recipe->getVPValue(0);
8570+
SingleDef->replaceAllUsesWith(Data);
8571+
Old2New[SingleDef] = Data;
85418572
} else {
85428573
assert(Recipe->getNumDefinedValues() == 0 &&
85438574
"Unexpected multidef recipe");
@@ -8585,6 +8616,8 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
85858616
// Adjust the recipes for any inloop reductions.
85868617
adjustRecipesForReductions(Plan, RecipeBuilder, Range.Start);
85878618

8619+
VPlanTransforms::adjustFFLoadEarlyExitForPoisonSafety(*Plan);
8620+
85888621
// Apply mandatory transformation to handle FP maxnum/minnum reduction with
85898622
// NaNs if possible, bail out otherwise.
85908623
if (!VPlanTransforms::runPass(VPlanTransforms::handleMaxMinNumReductions,
@@ -9893,7 +9926,14 @@ bool LoopVectorizePass::processLoop(Loop *L) {
98939926
return false;
98949927
}
98959928

9896-
if (!LVL.getPotentiallyFaultingLoads().empty()) {
9929+
if (EnableEarlyExitWithFFLoads) {
9930+
if (LVL.getPotentiallyFaultingLoads().size() > 1) {
9931+
reportVectorizationFailure("Auto-vectorization of loops with more than 1 "
9932+
"potentially faulting load is not enabled",
9933+
"MoreThanOnePotentiallyFaultingLoad", ORE, L);
9934+
return false;
9935+
}
9936+
} else if (!LVL.getPotentiallyFaultingLoads().empty()) {
98979937
reportVectorizationFailure("Auto-vectorization of loops with potentially "
98989938
"faulting load is not supported",
98999939
"PotentiallyFaultingLoadsNotSupported", ORE, L);

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPValue {
563563
case VPRecipeBase::VPInterleaveEVLSC:
564564
case VPRecipeBase::VPInterleaveSC:
565565
case VPRecipeBase::VPIRInstructionSC:
566+
case VPRecipeBase::VPWidenFFLoadSC:
566567
case VPRecipeBase::VPWidenLoadEVLSC:
567568
case VPRecipeBase::VPWidenLoadSC:
568569
case VPRecipeBase::VPWidenStoreEVLSC:
@@ -2820,6 +2821,13 @@ class LLVM_ABI_FOR_TEST VPReductionEVLRecipe : public VPReductionRecipe {
28202821
ArrayRef<VPValue *>({R.getChainOp(), R.getVecOp(), &EVL}), CondOp,
28212822
R.isOrdered(), DL) {}
28222823

2824+
VPReductionEVLRecipe(RecurKind RdxKind, FastMathFlags FMFs, VPValue *ChainOp,
2825+
VPValue *VecOp, VPValue &EVL, VPValue *CondOp,
2826+
bool IsOrdered, DebugLoc DL = DebugLoc::getUnknown())
2827+
: VPReductionRecipe(VPDef::VPReductionEVLSC, RdxKind, FMFs, nullptr,
2828+
ArrayRef<VPValue *>({ChainOp, VecOp, &EVL}), CondOp,
2829+
IsOrdered, DL) {}
2830+
28232831
~VPReductionEVLRecipe() override = default;
28242832

28252833
VPReductionEVLRecipe *clone() override {
@@ -3168,6 +3176,7 @@ class LLVM_ABI_FOR_TEST VPWidenMemoryRecipe : public VPRecipeBase,
31683176
static inline bool classof(const VPRecipeBase *R) {
31693177
return R->getVPDefID() == VPRecipeBase::VPWidenLoadSC ||
31703178
R->getVPDefID() == VPRecipeBase::VPWidenStoreSC ||
3179+
R->getVPDefID() == VPRecipeBase::VPWidenFFLoadSC ||
31713180
R->getVPDefID() == VPRecipeBase::VPWidenLoadEVLSC ||
31723181
R->getVPDefID() == VPRecipeBase::VPWidenStoreEVLSC;
31733182
}
@@ -3249,6 +3258,42 @@ struct LLVM_ABI_FOR_TEST VPWidenLoadRecipe final : public VPWidenMemoryRecipe,
32493258
}
32503259
};
32513260

3261+
/// A recipe for widening loads using fault-only-first intrinsics.
3262+
/// Produces two results: (1) the loaded data, and (2) the index of the first
3263+
/// non-dereferenceable lane, or VF if all lanes are successfully read.
3264+
struct VPWidenFFLoadRecipe final : public VPWidenMemoryRecipe, public VPValue {
3265+
VPWidenFFLoadRecipe(LoadInst &Load, VPValue *Addr, VPValue *VF, VPValue *Mask,
3266+
const VPIRMetadata &Metadata, DebugLoc DL)
3267+
: VPWidenMemoryRecipe(VPDef::VPWidenFFLoadSC, Load, {Addr, VF},
3268+
/*Consecutive*/ true, /*Reverse*/ false, Metadata,
3269+
DL),
3270+
VPValue(this, &Load) {
3271+
new VPValue(nullptr, this); // Index of the first lane that faults.
3272+
setMask(Mask);
3273+
}
3274+
3275+
VP_CLASSOF_IMPL(VPDef::VPWidenFFLoadSC);
3276+
3277+
/// Return the VF operand.
3278+
VPValue *getVF() const { return getOperand(1); }
3279+
void setVF(VPValue *V) { setOperand(1, V); }
3280+
3281+
void execute(VPTransformState &State) override;
3282+
3283+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3284+
/// Print the recipe.
3285+
void print(raw_ostream &O, const Twine &Indent,
3286+
VPSlotTracker &SlotTracker) const override;
3287+
#endif
3288+
3289+
/// Returns true if the recipe only uses the first lane of operand \p Op.
3290+
bool onlyFirstLaneUsed(const VPValue *Op) const override {
3291+
assert(is_contained(operands(), Op) &&
3292+
"Op must be an operand of the recipe");
3293+
return Op == getVF() || Op == getAddr();
3294+
}
3295+
};
3296+
32523297
/// A recipe for widening load operations with vector-predication intrinsics,
32533298
/// using the address to load from, the explicit vector length and an optional
32543299
/// mask.

llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenCallRecipe *R) {
188188
}
189189

190190
Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenMemoryRecipe *R) {
191-
assert((isa<VPWidenLoadRecipe, VPWidenLoadEVLRecipe>(R)) &&
192-
"Store recipes should not define any values");
191+
assert(
192+
(isa<VPWidenLoadRecipe, VPWidenFFLoadRecipe, VPWidenLoadEVLRecipe>(R)) &&
193+
"Store recipes should not define any values");
193194
return cast<LoadInst>(&R->getIngredient())->getType();
194195
}
195196

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ bool VPRecipeBase::mayWriteToMemory() const {
7373
case VPReductionPHISC:
7474
case VPScalarIVStepsSC:
7575
case VPPredInstPHISC:
76+
case VPWidenFFLoadSC:
7677
return false;
7778
case VPBlendSC:
7879
case VPReductionEVLSC:
@@ -107,6 +108,7 @@ bool VPRecipeBase::mayReadFromMemory() const {
107108
return cast<VPInstruction>(this)->opcodeMayReadOrWriteFromMemory();
108109
case VPWidenLoadEVLSC:
109110
case VPWidenLoadSC:
111+
case VPWidenFFLoadSC:
110112
return true;
111113
case VPReplicateSC:
112114
return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
@@ -3413,6 +3415,47 @@ void VPWidenLoadRecipe::print(raw_ostream &O, const Twine &Indent,
34133415
}
34143416
#endif
34153417

3418+
void VPWidenFFLoadRecipe::execute(VPTransformState &State) {
3419+
Type *ScalarDataTy = getLoadStoreType(&Ingredient);
3420+
auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
3421+
const Align Alignment = getLoadStoreAlignment(&Ingredient);
3422+
3423+
auto &Builder = State.Builder;
3424+
State.setDebugLocFrom(getDebugLoc());
3425+
3426+
Value *VL = State.get(getVF(), VPLane(0));
3427+
Type *I32Ty = Builder.getInt32Ty();
3428+
VL = Builder.CreateZExtOrTrunc(VL, I32Ty);
3429+
Value *Addr = State.get(getAddr(), true);
3430+
Value *Mask = nullptr;
3431+
if (VPValue *VPMask = getMask())
3432+
Mask = State.get(VPMask);
3433+
else
3434+
Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
3435+
CallInst *NewLI =
3436+
Builder.CreateIntrinsic(Intrinsic::vp_load_ff, {DataTy, Addr->getType()},
3437+
{Addr, Mask, VL}, nullptr, "vp.op.load.ff");
3438+
NewLI->addParamAttr(
3439+
0, Attribute::getWithAlignment(NewLI->getContext(), Alignment));
3440+
applyMetadata(*NewLI);
3441+
Value *V = cast<Instruction>(Builder.CreateExtractValue(NewLI, 0));
3442+
Value *NewVL = Builder.CreateExtractValue(NewLI, 1);
3443+
State.set(getVPValue(0), V);
3444+
State.set(getVPValue(1), NewVL, /*NeedsScalar=*/true);
3445+
}
3446+
3447+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3448+
void VPWidenFFLoadRecipe::print(raw_ostream &O, const Twine &Indent,
3449+
VPSlotTracker &SlotTracker) const {
3450+
O << Indent << "WIDEN ";
3451+
printAsOperand(O, SlotTracker);
3452+
O << ", ";
3453+
getVPValue(1)->printAsOperand(O, SlotTracker);
3454+
O << " = vp.load.ff ";
3455+
printOperands(O, SlotTracker);
3456+
}
3457+
#endif
3458+
34163459
/// Use all-true mask for reverse rather than actual mask, as it avoids a
34173460
/// dependence w/o affecting the result.
34183461
static Instruction *createReverseEVL(IRBuilderBase &Builder, Value *Operand,

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2762,6 +2762,103 @@ void VPlanTransforms::addExplicitVectorLength(
27622762
Plan.setUF(1);
27632763
}
27642764

2765+
void VPlanTransforms::adjustFFLoadEarlyExitForPoisonSafety(VPlan &Plan) {
2766+
VPBasicBlock *Header = Plan.getVectorLoopRegion()->getEntryBasicBlock();
2767+
VPWidenFFLoadRecipe *LastFFLoad = nullptr;
2768+
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
2769+
vp_depth_first_deep(Plan.getVectorLoopRegion())))
2770+
for (VPRecipeBase &R : *VPBB)
2771+
if (auto *Load = dyn_cast<VPWidenFFLoadRecipe>(&R)) {
2772+
assert(!LastFFLoad && "Only one FFLoad is supported");
2773+
LastFFLoad = Load;
2774+
}
2775+
2776+
// Skip if no FFLoad.
2777+
if (!LastFFLoad)
2778+
return;
2779+
2780+
// Ensure FFLoad does not read past the remainder in the last iteration.
2781+
// Set AVL to min(VF, remainder).
2782+
VPBuilder Builder(Header, Header->getFirstNonPhi());
2783+
VPValue *Remainder = Builder.createNaryOp(
2784+
Instruction::Sub, {&Plan.getVectorTripCount(), Plan.getCanonicalIV()});
2785+
VPValue *Cmp =
2786+
Builder.createICmp(CmpInst::ICMP_ULE, &Plan.getVF(), Remainder);
2787+
VPValue *AVL = Builder.createSelect(Cmp, &Plan.getVF(), Remainder);
2788+
LastFFLoad->setVF(AVL);
2789+
2790+
// To prevent branch-on-poison, rewrite the early-exit condition to
2791+
// VPReductionEVLRecipe. Expected pattern here is:
2792+
// EMIT vp<%alt.exit.cond> = AnyOf
2793+
// EMIT vp<%exit.cond> = or vp<%alt.exit.cond>, vp<%main.exit.cond>
2794+
// EMIT branch-on-cond vp<%exit.cond>
2795+
auto *ExitingLatch =
2796+
cast<VPBasicBlock>(Plan.getVectorLoopRegion()->getExiting());
2797+
auto *LatchExitingBr = cast<VPInstruction>(ExitingLatch->getTerminator());
2798+
2799+
VPValue *VPAnyOf = nullptr;
2800+
VPValue *VecOp = nullptr;
2801+
assert(
2802+
match(LatchExitingBr,
2803+
m_BranchOnCond(m_BinaryOr(m_VPValue(VPAnyOf), m_VPValue()))) &&
2804+
match(VPAnyOf, m_VPInstruction<VPInstruction::AnyOf>(m_VPValue(VecOp))) &&
2805+
"unexpected exiting sequence in early exit loop");
2806+
2807+
VPValue *OpVPEVLI32 = LastFFLoad->getVPValue(1);
2808+
VPValue *Mask = LastFFLoad->getMask();
2809+
FastMathFlags FMF;
2810+
auto *I1Ty = Type::getInt1Ty(Plan.getContext());
2811+
VPValue *VPZero = Plan.getOrAddLiveIn(ConstantInt::get(I1Ty, 0));
2812+
DebugLoc DL = VPAnyOf->getDefiningRecipe()->getDebugLoc();
2813+
auto *NewAnyOf =
2814+
new VPReductionEVLRecipe(RecurKind::Or, FMF, VPZero, VecOp, *OpVPEVLI32,
2815+
Mask, /*IsOrdered*/ false, DL);
2816+
NewAnyOf->insertBefore(VPAnyOf->getDefiningRecipe());
2817+
VPAnyOf->replaceAllUsesWith(NewAnyOf);
2818+
2819+
// Using FirstActiveLane in the early-exit block is safe,
2820+
// exiting conditions guarantees at least one valid lane precedes
2821+
// any poisoned lanes.
2822+
}
2823+
2824+
void VPlanTransforms::convertFFLoadEarlyExitToVLStepping(VPlan &Plan) {
2825+
// Find loop header by locating VPWidenFFLoadRecipe.
2826+
VPWidenFFLoadRecipe *LastFFLoad = nullptr;
2827+
2828+
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
2829+
vp_depth_first_shallow(Plan.getEntry())))
2830+
for (VPRecipeBase &R : *VPBB)
2831+
if (auto *Load = dyn_cast<VPWidenFFLoadRecipe>(&R)) {
2832+
assert(!LastFFLoad && "Only one FFLoad is supported");
2833+
LastFFLoad = Load;
2834+
}
2835+
2836+
// Skip if no FFLoad.
2837+
if (!LastFFLoad)
2838+
return;
2839+
2840+
VPBasicBlock *HeaderVPBB = LastFFLoad->getParent();
2841+
// Replace IVStep (VFxUF) with returned VL from FFLoad.
2842+
auto *CanonicalIV = cast<VPPhi>(&*HeaderVPBB->begin());
2843+
VPValue *Backedge = CanonicalIV->getIncomingValue(1);
2844+
assert(match(Backedge, m_c_Add(m_Specific(CanonicalIV),
2845+
m_Specific(&Plan.getVFxUF()))) &&
2846+
"Unexpected canonical iv");
2847+
VPRecipeBase *CanonicalIVIncrement = Backedge->getDefiningRecipe();
2848+
VPValue *OpVPEVLI32 = LastFFLoad->getVPValue(1);
2849+
VPBuilder Builder(HeaderVPBB, HeaderVPBB->getFirstNonPhi());
2850+
Builder.setInsertPoint(CanonicalIVIncrement);
2851+
auto *TC = Plan.getTripCount();
2852+
Type *CanIVTy = TC->isLiveIn()
2853+
? TC->getLiveInIRValue()->getType()
2854+
: cast<VPExpandSCEVRecipe>(TC)->getSCEV()->getType();
2855+
auto *I32Ty = Type::getInt32Ty(Plan.getContext());
2856+
VPValue *OpVPEVL = Builder.createScalarZExtOrTrunc(
2857+
OpVPEVLI32, CanIVTy, I32Ty, CanonicalIVIncrement->getDebugLoc());
2858+
2859+
CanonicalIVIncrement->setOperand(1, OpVPEVL);
2860+
}
2861+
27652862
void VPlanTransforms::canonicalizeEVLLoops(VPlan &Plan) {
27662863
// Find EVL loop entries by locating VPEVLBasedIVPHIRecipe.
27672864
// There should be only one EVL PHI in the entire plan.

llvm/lib/Transforms/Vectorize/VPlanTransforms.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,17 @@ struct VPlanTransforms {
276276
/// (branch-on-cond eq AVLNext, 0)
277277
static void canonicalizeEVLLoops(VPlan &Plan);
278278

279+
/// Applies to early-exit loops that use FFLoad. FFLoad may yield fewer active
280+
/// lanes than VF. To prevent branch-on-poison and over-reads past the vector
281+
/// trip count, use the returned VL for both stepping and exit computation.
282+
/// Implemented by:
283+
/// - adjustFFLoadEarlyExitForPoisonSafety: replace AnyOf with vp.reduce.or
284+
/// over the first VL lanes; set AVL = min(VF, remainder).
285+
/// - convertFFLoadEarlyExitToVLStepping: after region dissolution, convert
286+
/// early-exit loops to variable-length stepping.
287+
static void adjustFFLoadEarlyExitForPoisonSafety(VPlan &Plan);
288+
static void convertFFLoadEarlyExitToVLStepping(VPlan &Plan);
289+
279290
/// Lower abstract recipes to concrete ones, that can be codegen'd.
280291
static void convertToConcreteRecipes(VPlan &Plan);
281292

llvm/lib/Transforms/Vectorize/VPlanValue.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class raw_ostream;
3535
class Value;
3636
class VPDef;
3737
struct VPDoubleValueDef;
38+
struct VPWidenFFLoadRecipe;
3839
class VPSlotTracker;
3940
class VPUser;
4041
class VPRecipeBase;
@@ -48,6 +49,7 @@ class VPPhiAccessors;
4849
class LLVM_ABI_FOR_TEST VPValue {
4950
friend class VPDef;
5051
friend struct VPDoubleValueDef;
52+
friend struct VPWidenFFLoadRecipe;
5153
friend class VPInterleaveBase;
5254
friend class VPlan;
5355
friend class VPExpressionRecipe;
@@ -351,6 +353,7 @@ class VPDef {
351353
VPWidenCastSC,
352354
VPWidenGEPSC,
353355
VPWidenIntrinsicSC,
356+
VPWidenFFLoadSC,
354357
VPWidenLoadEVLSC,
355358
VPWidenLoadSC,
356359
VPWidenStoreEVLSC,

0 commit comments

Comments
 (0)