[llvm] [VPlan] Extend cse to eliminate redundant widened loads (PR #212543)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 30 03:59:28 PDT 2026
================
@@ -2304,16 +2308,51 @@ struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
};
} // end anonymous namespace
-/// Perform a common-subexpression-elimination of VPSingleDefRecipes on the \p
-/// Plan.
+/// Perform a common-subexpression-elimination of single-def recipes on the \p
+/// Plan, also eliminating redundant widened loads within a basic block.
void VPlanTransforms::cse(VPlan &Plan) {
VPDominatorTree VPDT(Plan);
DenseMap<VPSingleDefRecipe *, VPSingleDefRecipe *, VPCSEDenseMapInfo> CSEMap;
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
Plan.getEntry());
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
- for (VPRecipeBase &R : *VPBB) {
+ // Widened loads that can be reused within this block, cleared by any
+ // intervening store (see below).
+ SmallVector<VPWidenLoadRecipe *, 4> LoadCandidates;
+ for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
+ // A recipe that may write to memory could alias a candidate load, so
+ // conservatively drop all candidates: a later load must not be CSE'd to a
+ // value read before the write. This avoids needing alias analysis.
+ if (R.mayWriteToMemory())
+ LoadCandidates.clear();
+
+ // Widened loads are not handled by the map-based CSE below; match them
+ // against the per-block candidates instead, reusing an earlier load with
+ // the same address, mask, type and alignment.
+ if (auto *Load = dyn_cast<VPWidenLoadRecipe>(&R)) {
+ VPWidenLoadRecipe *Match = nullptr;
+ for (VPWidenLoadRecipe *C : LoadCandidates) {
+ // Consecutive vs. gather loads have different address operands, so
+ // the operand check below also distinguishes those cases.
+ if (C->getScalarType() != Load->getScalarType() ||
+ C->getAlign() != Load->getAlign() ||
+ !equal(C->operands(), Load->operands()))
+ continue;
+ Match = C;
+ break;
+ }
+ if (Match) {
+ // Keep only metadata common to both loads on the survivor.
+ Match->intersect(*Load);
----------------
fhahn wrote:
I think a test for this is missing
https://github.com/llvm/llvm-project/pull/212543
More information about the llvm-commits
mailing list