[llvm] [VPlan] Split simplifyRecipes into simplifyRecipes and combineRecipes (PR #221924)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 02:02:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Luke Lau (lukel97)
<details>
<summary>Changes</summary>
Bringing it in line with InstSimplify and InstCombine, split up simplifyRecipe into a function that modifies and creates recipes (combineRecipe), and one that is analysis-only (simplifyRecipe).
This allows us to avoid adding simplficiation only folds to the worklist in #<!-- -->213899.
The funclet.ll test no longer erases the constant-folded intrinsic call because vputils::isDeadRecipe returns false.
---
<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
---
Patch is 33.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/221924.diff
7 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+4-4)
- (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp (+222-207)
- (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.h (+1-1)
- (modified) llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll (+1-1)
- (modified) llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-before-after-all.ll (+5-5)
- (modified) llvm/test/Transforms/LoopVectorize/X86/funclet.ll (+9-6)
- (modified) llvm/test/Transforms/LoopVectorize/vplan-print-before-after.ll (+4-4)
``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index e027dfa834759..10a58f4d40da7 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -5719,7 +5719,7 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
BestVF, BestUF, PSE);
RUN_VPLAN_PASS(VPlanTransforms::optimizeForVFAndUF, BestVPlan, BestVF, BestUF,
PSE);
- RUN_VPLAN_PASS(VPlanTransforms::simplifyRecipes, BestVPlan);
+ RUN_VPLAN_PASS(VPlanTransforms::combineRecipes, BestVPlan);
// Check if scalar epilogue is required, before simplifying constant branches.
const bool RequiresScalarEpilogue = BestVPlan.requiresScalarEpilogue();
if (EpilogueVecKind == EpilogueVectorizationKind::None)
@@ -5776,13 +5776,13 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
RUN_VPLAN_PASS(VPlanTransforms::expandSCEVsToVPInstructions, BestVPlan,
*PSE.getSE());
RUN_VPLAN_PASS(VPlanTransforms::cse, BestVPlan);
- RUN_VPLAN_PASS(VPlanTransforms::simplifyRecipes, BestVPlan);
+ RUN_VPLAN_PASS(VPlanTransforms::combineRecipes, BestVPlan);
// Removing branches and incoming values may expose additional simplification
// opportunities.
if (RUN_VPLAN_PASS(VPlanTransforms::removeBranchOnConst, BestVPlan,
/*OnlyLatches=*/EpilogueVecKind !=
EpilogueVectorizationKind::None))
- RUN_VPLAN_PASS(VPlanTransforms::simplifyRecipes, BestVPlan);
+ RUN_VPLAN_PASS(VPlanTransforms::combineRecipes, BestVPlan);
RUN_VPLAN_PASS(VPlanTransforms::simplifyKnownEVL, BestVPlan, BestVF, PSE);
// 0. Generate SCEV-dependent code in the entry, including TripCount, before
@@ -6387,7 +6387,7 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan1() {
if (const LoopAccessInfo *LAI = Legal->getLAI())
RUN_VPLAN_PASS(VPlanTransforms::replaceSymbolicStrides, *VPlan0, PSE,
LAI->getSymbolicStrides(), VPDT);
- RUN_VPLAN_PASS(VPlanTransforms::simplifyRecipes, *VPlan0);
+ RUN_VPLAN_PASS(VPlanTransforms::combineRecipes, *VPlan0);
RUN_VPLAN_PASS(VPlanTransforms::removeDeadRecipes, *VPlan0);
// Create recipes for header phis. For outer loops, reductions, recurrences
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 25a78bc13644f..2de2fc24567a6 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -1170,14 +1170,12 @@ static void removeRedundantExpandSCEVRecipes(VPlan &Plan) {
}
/// Try to simplify logical and bitwise recipes in \p Def.
-static VPValue *simplifyLogicalRecipe(VPlan &Plan, VPSingleDefRecipe *Def,
- VPBuilder &Builder,
- bool CanCreateNewRecipe) {
+static VPValue *simplifyLogicalRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
// Simplify (X && Y) | (X && !Y) -> X.
// TODO: Split up into simpler, modular combines: (X && Y) | (X && Z) into X
// && (Y | Z) and (X | !X) into true. This requires queuing newly created
// recipes to be visited during simplification.
- VPValue *X, *Y, *Z;
+ VPValue *X, *Y;
if (match(Def,
m_c_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)),
m_LogicalAnd(m_Deferred(X), m_Not(m_Deferred(Y))))))
@@ -1211,26 +1209,11 @@ static VPValue *simplifyLogicalRecipe(VPlan &Plan, VPSingleDefRecipe *Def,
if (match(Def, m_c_LogicalAnd(m_VPValue(X), m_True())))
return X;
- // (x && y) | (x && z) -> x && (y | z)
- if (CanCreateNewRecipe &&
- match(Def, m_c_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)),
- m_LogicalAnd(m_Deferred(X), m_VPValue(Z)))) &&
- // Simplify only if one of the operands has one use to avoid creating an
- // extra recipe.
- (!Def->getOperand(0)->hasMoreThanOneUniqueUser() ||
- !Def->getOperand(1)->hasMoreThanOneUniqueUser()))
- return Builder.createLogicalAnd(X, Builder.createOr(Y, Z));
-
// x && (x && y) -> x && y
if (match(Def, m_LogicalAnd(m_VPValue(X),
m_LogicalAnd(m_Deferred(X), m_VPValue()))))
return Def->getOperand(1);
- // x && (y && x) -> x && y
- if (match(Def, m_LogicalAnd(m_VPValue(X),
- m_LogicalAnd(m_VPValue(Y), m_Deferred(X)))))
- return Builder.createLogicalAnd(X, Y);
-
// x && !x -> 0
if (match(Def, m_LogicalAnd(m_VPValue(X), m_Not(m_Deferred(X)))))
return Plan.getFalse();
@@ -1238,52 +1221,11 @@ static VPValue *simplifyLogicalRecipe(VPlan &Plan, VPSingleDefRecipe *Def,
if (match(Def, m_Select(m_VPValue(), m_VPValue(X), m_Deferred(X))))
return X;
- // (x && y) | !x -> !x || y
- if (CanCreateNewRecipe &&
- match(Def,
- m_c_BinaryOr(m_OneUse(m_LogicalAnd(m_VPValue(X), m_VPValue(Y))),
- m_VPValue(Z, m_Not(m_Deferred(X))))))
- return Builder.createLogicalOr(Z, Y);
-
- // select c, false, true -> not c
- VPValue *C;
- if (CanCreateNewRecipe &&
- match(Def, m_Select(m_VPValue(C), m_False(), m_True())))
- return Builder.createNot(C);
-
- // select !c, x, y -> select c, y, x
- if (match(Def, m_Select(m_Not(m_VPValue(C)), m_VPValue(X), m_VPValue(Y)))) {
- Def->setOperand(0, C);
- Def->setOperand(1, Y);
- Def->setOperand(2, X);
- return Def;
- }
-
- // select x, (i1 y | z), y -> y | (x && z)
- if (CanCreateNewRecipe &&
- match(Def, m_Select(m_VPValue(X),
- m_OneUse(m_c_BinaryOr(m_VPValue(Y), m_VPValue(Z))),
- m_Deferred(Y))) &&
- Y->getScalarType()->isIntegerTy(1))
- return Builder.createOr(Y, Builder.createLogicalAnd(X, Z));
-
- // select %M0, (select %M1, %X, %Y), %Y -> select (%M0 && %M1), %X, %Y
- VPValue *Mask0, *Mask1;
- if (CanCreateNewRecipe &&
- match(Def,
- m_SelectLike(m_VPValue(Mask0),
- m_OneUse(m_SelectLike(m_VPValue(Mask1), m_VPValue(X),
- m_VPValue(Y))),
- m_Deferred(Y))))
- return Builder.createSelect(Builder.createLogicalAnd(Mask0, Mask1), X, Y,
- Def->getDebugLoc());
-
return nullptr;
}
-/// Try to simplify VPSingleDefRecipe \p Def. Returns a new recipe if it should
-/// be replaced, or the existing recipe if it was modified. Returns nullptr if
-/// nothing was simplified.
+/// Return a simpler value for VPSingleDefRecipe \p Def if possible. This must
+/// not create or modify recipes.
static VPValue *simplifyRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
// Simplification of live-in IR values for SingleDef recipes using
// InstSimplifyFolder.
@@ -1298,6 +1240,140 @@ static VPValue *simplifyRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
return Op;
}
+ if (VPValue *V = simplifyLogicalRecipe(Plan, Def))
+ return V;
+
+ VPValue *A, *B;
+
+ if (match(Def, m_c_Add(m_VPValue(A), m_ZeroInt())))
+ return A;
+
+ if (match(Def, m_c_Mul(m_VPValue(A), m_One())))
+ return A;
+
+ if (match(Def, m_c_Mul(m_VPValue(), m_ZeroInt())))
+ return Plan.getZero(Def->getScalarType());
+
+ // A bitcast to the same type is a no-op.
+ if (match(Def, m_BitCast(m_VPValue(A))) &&
+ Def->getScalarType() == A->getScalarType())
+ return A;
+
+ if (match(Def, m_Trunc(m_ZExtOrSExt(m_VPValue(A)))))
+ if (Def->getScalarType() == A->getScalarType())
+ return A;
+
+ if (match(Def, m_Not(m_Not(m_VPValue(A)))))
+ return A;
+
+ // Remove redundant DerviedIVs, that is 0 + A * 1 -> A and 0 + 0 * x -> 0.
+ if ((match(Def, m_DerivedIV(m_ZeroInt(), m_VPValue(A), m_One())) ||
+ match(Def, m_DerivedIV(m_ZeroInt(), m_VPValue(A, m_ZeroInt()),
+ m_VPValue()))) &&
+ A->getScalarType() == Def->getScalarType())
+ return A;
+
+ // Simplify MaskedCond with no block mask to its single operand.
+ if (match(Def, m_VPInstruction<VPInstruction::MaskedCond>()) &&
+ !cast<VPInstruction>(Def)->isMasked())
+ return Def->getOperand(0);
+
+ // Look through ExtractLastLane.
+ if (match(Def, m_ExtractLastLane(m_VPValue(A)))) {
+ if (match(A, m_BuildVector())) {
+ auto *BuildVector = cast<VPInstruction>(A);
+ return BuildVector->getOperand(BuildVector->getNumOperands() - 1);
+ }
+
+ if (match(A, m_Broadcast(m_VPValue(B))))
+ return B;
+
+ if (isa<VPInstruction, VPReplicateRecipe>(A) && vputils::isSingleScalar(A))
+ return A;
+
+ if (Plan.hasScalarVFOnly())
+ return A;
+ }
+
+ // Look through ExtractPenultimateElement (BuildVector ....).
+ if (match(Def, m_ExtractPenultimateElement(m_BuildVector()))) {
+ auto *BuildVector = cast<VPInstruction>(Def->getOperand(0));
+ return BuildVector->getOperand(BuildVector->getNumOperands() - 2);
+ }
+
+ uint64_t Idx;
+ if (match(Def, m_ExtractElement(m_BuildVector(), m_ConstantInt(Idx)))) {
+ auto *BuildVector = cast<VPInstruction>(Def->getOperand(0));
+ return BuildVector->getOperand(Idx);
+ }
+
+ if (isa<VPPhi, VPWidenPHIRecipe, VPHeaderPHIRecipe>(Def)) {
+ if (Def->getNumOperands() == 1) {
+ return Def->getOperand(0);
+ }
+ if (auto *Phi = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(Def)) {
+ if (all_equal(Phi->incoming_values()))
+ return Phi->getOperand(0);
+ }
+ return nullptr;
+ }
+
+ VPIRValue *IRV;
+ if (Def->getNumOperands() == 1 &&
+ match(Def, m_ComputeReductionResult(m_VPIRValue(IRV))))
+ return IRV;
+
+ if (match(Def, m_VPInstruction<VPInstruction::WideIVStep>(m_VPValue(A),
+ m_One())) &&
+ A->getScalarType() == Def->getScalarType())
+ return A;
+
+ // Some simplifications can only be applied after unrolling. Perform them
+ // below.
+ if (!Plan.isUnrolled())
+ return nullptr;
+
+ // After unrolling, extract-lane may be used to extract values from multiple
+ // scalar sources. Only simplify when extracting from a single scalar source.
+ VPValue *LaneToExtract;
+ if (match(Def, m_ExtractLane(m_VPValue(LaneToExtract), m_VPValue(A)))) {
+ // Simplify extract-lane(%lane_num, %scalar_val) -> %scalar_val.
+ if (vputils::isSingleScalar(A))
+ return A;
+
+ // Replace extract-lane(0, canonical-WIDEN-INDUCTION) with the region's
+ // scalar canonical IV.
+ VPWidenIntOrFpInductionRecipe *WidenIV;
+ if (match(LaneToExtract, m_ZeroInt()) &&
+ match(A, m_CanonicalWidenIV(WidenIV)))
+ return WidenIV->getRegion()->getCanonicalIV();
+ }
+
+ // Simplify unrolled VectorPointer without offset, or with zero offset, to
+ // just the pointer operand.
+ if (auto *VPR = dyn_cast<VPVectorPointerRecipe>(Def))
+ if (!VPR->getVFxPart() || match(VPR->getVFxPart(), m_ZeroInt()))
+ return VPR->getOperand(0);
+
+ // VPScalarIVSteps after unrolling can be replaced by their start value, if
+ // the start index is zero and only the first lane 0 is demanded.
+ if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(Def))
+ if (!Steps->getStartIndex() && vputils::onlyFirstLaneUsed(Steps))
+ return Steps->getOperand(0);
+
+ if (Plan.getConcreteUF() == 1 && match(Def, m_ExtractLastPart(m_VPValue(A))))
+ return A;
+
+ return nullptr;
+}
+
+/// Combine \p Def into a simpler recipe. May modify or create new recipes.
+static VPSingleDefRecipe *combineRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
+ if (auto *V = simplifyRecipe(Plan, Def)) {
+ Def->replaceAllUsesWith(V);
+ return Def;
+ }
+
// Drop the mask of a predicated store masked by the header mask (which is
// guaranteed to be true at least for the first lane) and both the stored
// value and the address are uniform across VF and UF. The header mask is
@@ -1327,54 +1403,87 @@ static VPValue *simplifyRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
bool CanCreateNewRecipe =
!isa<VPInstruction>(Def) || !Def->getUnderlyingValue();
- VPValue *A, *Z;
+ VPValue *A, *X, *Y, *Z;
- // A bitcast to the same type is a no-op.
- if (match(Def, m_BitCast(m_VPValue(A))) &&
- Def->getScalarType() == A->getScalarType())
- return A;
+ // x && (y && x) -> x && y
+ if (CanCreateNewRecipe &&
+ match(Def, m_LogicalAnd(m_VPValue(X),
+ m_LogicalAnd(m_VPValue(Y), m_Deferred(X)))))
+ return Builder.createLogicalAnd(X, Y);
+
+ // (x && y) | (x && z) -> x && (y | z)
+ if (CanCreateNewRecipe &&
+ match(Def, m_c_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)),
+ m_LogicalAnd(m_Deferred(X), m_VPValue(Z)))) &&
+ // Simplify only if one of the operands has one use to avoid creating an
+ // extra recipe.
+ (!Def->getOperand(0)->hasMoreThanOneUniqueUser() ||
+ !Def->getOperand(1)->hasMoreThanOneUniqueUser()))
+ return Builder.createLogicalAnd(X, Builder.createOr(Y, Z));
+
+ // (x && y) | !x -> !x || y
+ if (CanCreateNewRecipe &&
+ match(Def,
+ m_c_BinaryOr(m_OneUse(m_LogicalAnd(m_VPValue(X), m_VPValue(Y))),
+ m_VPValue(Z, m_Not(m_Deferred(X))))))
+ return Builder.createLogicalOr(Z, Y);
+
+ // select c, false, true -> not c
+ VPValue *C;
+ if (CanCreateNewRecipe &&
+ match(Def, m_Select(m_VPValue(C), m_False(), m_True())))
+ return Builder.createNot(C);
+
+ // select !c, x, y -> select c, y, x
+ if (match(Def, m_Select(m_Not(m_VPValue(C)), m_VPValue(X), m_VPValue(Y)))) {
+ Def->setOperand(0, C);
+ Def->setOperand(1, Y);
+ Def->setOperand(2, X);
+ return Def;
+ }
+
+ // select x, (i1 y | z), y -> y | (x && z)
+ if (CanCreateNewRecipe &&
+ match(Def, m_Select(m_VPValue(X),
+ m_OneUse(m_c_BinaryOr(m_VPValue(Y), m_VPValue(Z))),
+ m_Deferred(Y))) &&
+ Y->getScalarType()->isIntegerTy(1))
+ return Builder.createOr(Y, Builder.createLogicalAnd(X, Z));
+
+ // select %M0, (select %M1, %X, %Y), %Y -> select (%M0 && %M1), %X, %Y
+ VPValue *Mask0, *Mask1;
+ if (CanCreateNewRecipe &&
+ match(Def,
+ m_SelectLike(m_VPValue(Mask0),
+ m_OneUse(m_SelectLike(m_VPValue(Mask1), m_VPValue(X),
+ m_VPValue(Y))),
+ m_Deferred(Y))))
+ return Builder.createSelect(Builder.createLogicalAnd(Mask0, Mask1), X, Y,
+ Def->getDebugLoc());
if (match(Def, m_Trunc(m_VPValue(Z, m_ZExtOrSExt(m_VPValue(A)))))) {
+ // Don't replace a non-widened cast recipe with a widened cast.
+ if (!isa<VPWidenCastRecipe>(Def))
+ return nullptr;
Type *TruncTy = Def->getScalarType();
Type *ATy = A->getScalarType();
- if (TruncTy == ATy) {
- return A;
- } else {
- // Don't replace a non-widened cast recipe with a widened cast.
- if (!isa<VPWidenCastRecipe>(Def))
- return nullptr;
- if (ATy->getScalarSizeInBits() < TruncTy->getScalarSizeInBits()) {
-
- unsigned ExtOpcode = match(Z, m_SExt(m_VPValue())) ? Instruction::SExt
- : Instruction::ZExt;
- auto *Ext = Builder.createWidenCast(Instruction::CastOps(ExtOpcode), A,
- TruncTy);
- if (auto *UnderlyingExt = Z->getUnderlyingValue()) {
- // UnderlyingExt has distinct return type, used to retain legacy cost.
- Ext->setUnderlyingValue(UnderlyingExt);
- }
- return Ext;
- } else if (ATy->getScalarSizeInBits() > TruncTy->getScalarSizeInBits()) {
- auto *Trunc = Builder.createWidenCast(Instruction::Trunc, A, TruncTy);
- return Trunc;
+ if (ATy->getScalarSizeInBits() < TruncTy->getScalarSizeInBits()) {
+
+ unsigned ExtOpcode =
+ match(Z, m_SExt(m_VPValue())) ? Instruction::SExt : Instruction::ZExt;
+ auto *Ext =
+ Builder.createWidenCast(Instruction::CastOps(ExtOpcode), A, TruncTy);
+ if (auto *UnderlyingExt = Z->getUnderlyingValue()) {
+ // UnderlyingExt has distinct return type, used to retain legacy cost.
+ Ext->setUnderlyingValue(UnderlyingExt);
}
+ return Ext;
+ } else if (ATy->getScalarSizeInBits() > TruncTy->getScalarSizeInBits()) {
+ auto *Trunc = Builder.createWidenCast(Instruction::Trunc, A, TruncTy);
+ return Trunc;
}
}
- if (VPValue *V =
- simplifyLogicalRecipe(Plan, Def, Builder, CanCreateNewRecipe))
- return V;
-
- VPValue *X, *Y;
- if (match(Def, m_c_Add(m_VPValue(A), m_ZeroInt())))
- return A;
-
- if (match(Def, m_c_Mul(m_VPValue(A), m_One())))
- return A;
-
- if (match(Def, m_c_Mul(m_VPValue(A), m_ZeroInt())))
- return Plan.getZero(Def->getScalarType());
-
if (CanCreateNewRecipe && match(Def, m_c_Mul(m_VPValue(A), m_AllOnes()))) {
// Preserve nsw from the Mul on the new Sub.
VPIRFlags::WrapFlagsTy NW = {
@@ -1421,9 +1530,6 @@ static VPValue *simplifyRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
*cast<VPRecipeWithIRFlags>(Def), Def->getDebugLoc());
if (match(Def, m_Not(m_VPValue(A)))) {
- if (match(A, m_Not(m_VPValue(A))))
- return A;
-
// Try to fold Not into compares by adjusting the predicate in-place.
CmpPredicate Pred;
if (match(A, m_Cmp(Pred, m_VPValue(), m_VPValue()))) {
@@ -1481,10 +1587,8 @@ static VPValue *simplifyRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
if (UnpairedCmp)
NewOps.push_back(UnpairedCmp->getVPSingleValue());
- if (NewOps.size() < Def->getNumOperands()) {
- VPValue *NewAnyOf = Builder.createNaryOp(VPInstruction::AnyOf, NewOps);
- return NewAnyOf;
- }
+ if (NewOps.size() < Def->getNumOperands())
+ return Builder.createNaryOp(VPInstruction::AnyOf, NewOps);
}
// Fold (fcmp uno %X, %X) or (fcmp uno %Y, %Y) -> fcmp uno %X, %Y
@@ -1497,20 +1601,10 @@ static VPValue *simplifyRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
m_SpecificCmp(CmpInst::FCMP_UNO, m_VPValue(Y), m_Deferred(Y)))))
return Builder.createFCmp(CmpInst::FCMP_UNO, X, Y);
- // Remove redundant DerviedIVs, that is 0 + A * 1 -> A and 0 + 0 * x -> 0.
- if ((match(Def, m_DerivedIV(m_ZeroInt(), m_VPValue(A), m_One())) ||
- match(Def, m_DerivedIV(m_ZeroInt(), m_VPValue(A, m_ZeroInt()),
- m_VPValue()))) &&
- A->getScalarType() == Def->getScalarType())
- return A;
-
if (match(Def, m_VPInstruction<VPInstruction::WideIVStep>(m_VPValue(X),
- m_One()))) {
- Type *WideStepTy = Def->getScalarType();
- if (X->getScalarType() != WideStepTy)
- X = Builder.createWidenCast(Instruction::Trunc, X, WideStepTy);
- return X;
- }
+ m_One())) &&
+ X->getScalarType() != Def->getScalarType())
+ return Builder.createWidenCast(Instruction::Trunc, X, Def->getScalarType());
// For i1 vp.merges produced by AnyOf reductions:
// vp.merge true, (or x, y), x, evl -> vp.merge y, true, x, evl
@@ -1523,40 +1617,6 @@ static VPValue *simplifyRecipe(VPlan &Plan, VPSingleDefRecipe *Def) {
return Def;
}
- // Simplify MaskedCond with no block mask to its single operand.
- if (match(Def, m_VPInstruction<VPInstruction::MaskedCond>()) &&
- !cast<VPInstruction>(Def)->isMasked())
- return Def->getOperand(0);
-
- // Look through ExtractLastLane.
- if (match(Def, m_ExtractLastLane(m_VPValue(A)))) {
- if (match(A, m_BuildVector())) {
- auto *BuildVector = cast<VPInstruction>(A);
- return BuildVector->getOperand(BuildVector->getNumOperands() - 1);
- }
-
- if (match(A, m_Broadcast(m_VPValue(X))))
- return X;
-
- if (isa<VPInstruction, VPReplicateRecipe>(A) && vputils::isSingleScalar(A))
- return A;
-
- if (Plan.hasScalarVFOnly())
- return A;
- }
-
- // Look through ExtractPenultimateElement (BuildVector ....).
- if (match(Def, m_ExtractPenultimateElement(m_BuildVector()))) {
- auto *BuildVector = cast<VPInstruction>(Def->getOperand(0));
- return BuildVector->getOperand(BuildVector->getNumOperands() - 2);
- }
-
- uint64_t Idx;
- if (match(Def, m_ExtractElement(m_BuildVector(), m_ConstantInt(Idx)))) {
- auto *B...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/221924
More information about the llvm-commits
mailing list