https://github.com/gbossu updated https://github.com/llvm/llvm-project/pull/213987
From 3a0c646b09d070431218e1a30312dbfbfecaa3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Bossu?= <[email protected]> Date: Tue, 4 Aug 2026 15:01:21 +0000 Subject: [PATCH] [LV][REVEC] Correctly compute register usage For REVEC, the initial types might already be vectors, so make sure the right register class is picked. --- .../Transforms/Vectorize/VPlanAnalysis.cpp | 29 ++++++++------ .../LoopVectorize/revec-reg-usage.ll | 39 +++++++++++++++++++ 2 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 llvm/test/Transforms/LoopVectorize/revec-reg-usage.ll diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp index af35704ed56427..c2b9dde6f2d49d 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp @@ -187,11 +187,12 @@ llvm::calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef<ElementCount> VFs, const auto &TTICapture = TTI; auto GetRegUsage = [&TTICapture](Type *Ty, ElementCount VF) -> unsigned { - if (Ty->isTokenTy() || !VectorType::isValidElementType(Ty) || + Type *EltTy = Ty->getScalarType(); + if (Ty->isTokenTy() || !VectorType::isValidElementType(EltTy) || (VF.isScalable() && - !TTICapture.isElementTypeLegalForScalableVector(Ty))) + !TTICapture.isElementTypeLegalForScalableVector(EltTy))) return 0; - return TTICapture.getRegUsageForType(VectorType::get(Ty, VF)); + return TTICapture.getRegUsageForType(toVectorTy(Ty, VF)); }; VPValue *CanIV = LoopRegion->getCanonicalIV(); @@ -244,6 +245,10 @@ llvm::calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef<ElementCount> VFs, match(VPV, m_ExtractLastPart(m_VPValue()))) continue; + // For REVEC, the initial type might be a vector. + Type *InitialTy = VPV->getScalarType(); + Type *EltTy = InitialTy->getScalarType(); + if (VFs[J].isScalar() || VPV == CanIV || isa<VPReplicateRecipe, VPDerivedIVRecipe, VPCurrentIterationPHIRecipe, VPScalarIVStepsRecipe>(VPV) || @@ -251,7 +256,7 @@ llvm::calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef<ElementCount> VFs, (isa<VPReductionPHIRecipe>(VPV) && (cast<VPReductionPHIRecipe>(VPV))->isInLoop())) { unsigned ClassID = - TTI.getRegisterClassForType(false, VPV->getScalarType()); + TTI.getRegisterClassForType(InitialTy->isVectorTy(), EltTy); // FIXME: The target might use more than one register for the type // even in the scalar case. RegUsage[ClassID] += 1; @@ -267,9 +272,8 @@ llvm::calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef<ElementCount> VFs, << " to " << VF << " for " << *R << "\n";); } - Type *ScalarTy = VPV->getScalarType(); - unsigned ClassID = TTI.getRegisterClassForType(true, ScalarTy); - RegUsage[ClassID] += GetRegUsage(ScalarTy, VF); + unsigned ClassID = TTI.getRegisterClassForType(true, EltTy); + RegUsage[ClassID] += GetRegUsage(InitialTy, VF); } } @@ -303,12 +307,13 @@ llvm::calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef<ElementCount> VFs, for (auto *In : LoopInvariants) { // FIXME: The target might use more than one register for the type // even in the scalar case. - bool IsScalar = vputils::onlyScalarValuesUsed(In); + bool OnlyFirstLane = vputils::onlyScalarValuesUsed(In); + Type *InitialTy = In->getScalarType(); - ElementCount VF = IsScalar ? ElementCount::getFixed(1) : VFs[Idx]; - unsigned ClassID = - TTI.getRegisterClassForType(VF.isVector(), In->getScalarType()); - Invariant[ClassID] += GetRegUsage(In->getScalarType(), VF); + ElementCount VF = OnlyFirstLane ? ElementCount::getFixed(1) : VFs[Idx]; + unsigned ClassID = TTI.getRegisterClassForType( + VF.isVector() || InitialTy->isVectorTy(), InitialTy->getScalarType()); + Invariant[ClassID] += GetRegUsage(InitialTy, VF); } LLVM_DEBUG({ diff --git a/llvm/test/Transforms/LoopVectorize/revec-reg-usage.ll b/llvm/test/Transforms/LoopVectorize/revec-reg-usage.ll new file mode 100644 index 00000000000000..89f6c3969bf3c6 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/revec-reg-usage.ll @@ -0,0 +1,39 @@ +; REQUIRES: asserts +; RUN: opt -disable-output -passes=loop-vectorize -vectorize-vector-loops \ +; RUN: -force-vector-width=1 -debug-only=vplan < %s 2>&1 \ +; RUN: | FileCheck %s +; RUN: opt -disable-output -passes=loop-vectorize -vectorize-vector-loops \ +; RUN: -force-vector-width="vscale x 1" -debug-only=vplan < %s 2>&1 \ +; RUN: | FileCheck %s + +; When re-vectorising with VF = vscale x 1, the number of used registers is +; expected to remain the same, as we are turning fixed vectors into scalable +; ones and they belong to the same class according to the generic getRegisterClassForType. + +; CHECK: LV(REG): Found max usage: 2 item +; CHECK-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 3 registers +; CHECK-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 2 registers +; CHECK-NEXT: LV(REG): Found invariant usage: 2 item +; CHECK-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 1 registers +; CHECK-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 1 registers +define void @register_usage(ptr noalias %dst, ptr noalias %src, + ptr noalias %threshold.ptr, i64 %n) { +entry: + %threshold = load <4 x i32>, ptr %threshold.ptr, align 16 + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %src.gep = getelementptr inbounds <4 x i32>, ptr %src, i64 %iv + %dst.gep = getelementptr inbounds <4 x i32>, ptr %dst, i64 %iv + %v = load <4 x i32>, ptr %src.gep, align 16 + %cmp = icmp sgt <4 x i32> %v, %threshold + %sel = select <4 x i1> %cmp, <4 x i32> %v, <4 x i32> %threshold + store <4 x i32> %sel, ptr %dst.gep, align 16 + %iv.next = add nuw i64 %iv, 1 + %done = icmp eq i64 %iv.next, %n + br i1 %done, label %exit, label %loop + +exit: + ret void +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
