[llvm] e2efa2e - [SLP] Gather wide PHI bundles to avoid compile-time blow-up
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 04:05:53 PDT 2026
Author: Alexey Bataev
Date: 2026-06-03T07:05:48-04:00
New Revision: e2efa2e958270e0f21d9db2aa9a393006c9d6d0b
URL: https://github.com/llvm/llvm-project/commit/e2efa2e958270e0f21d9db2aa9a393006c9d6d0b
DIFF: https://github.com/llvm/llvm-project/commit/e2efa2e958270e0f21d9db2aa9a393006c9d6d0b.diff
LOG: [SLP] Gather wide PHI bundles to avoid compile-time blow-up
Vectorizing a PHI bundle recurses into one operand bundle per incoming
value, so the analysis cost grows with bundle_size * num_incoming_values.
With revectorization, very wide PHIs from jump threading make
opt -O3 hang for minutes/hours. Such PHIs are not profitable to vectorize,
so gather the bundle once that product exceeds a budget (new hidden option
-slp-phi-vectorization-budget, default 1024).
Fixes #201181
Reviewers: hiraditya, bababuck, RKSimon
Pull Request: https://github.com/llvm/llvm-project/pull/201227
Added:
llvm/test/Transforms/SLPVectorizer/X86/phi-vectorization-budget.ll
Modified:
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index a488fdca64074..99ed09cc684b9 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -179,6 +179,12 @@ static cl::opt<unsigned> MinTreeSize(
"slp-min-tree-size", cl::init(3), cl::Hidden,
cl::desc("Only vectorize small trees if they are fully vectorizable"));
+static cl::opt<unsigned> PHINodeVectorizationBudget(
+ "slp-phi-vectorization-budget", cl::init(1024), cl::Hidden,
+ cl::desc("Do not vectorize a bundle of PHI nodes if the product of the "
+ "bundle size and the number of incoming values exceeds this "
+ "value, to limit the compile time spent on wide PHIs"));
+
// The maximum depth that the look-ahead score heuristic will explore.
// The higher this value, the higher the compilation time overhead.
static cl::opt<int> LookAheadMaxDepth(
@@ -12610,6 +12616,21 @@ BoUpSLP::getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
}
assert(S && "Must be valid.");
+ // Gather very wide PHI bundles. Wide PHIs (e.g. produced by
+ // jump threading) are not profitable to vectorize and make this analysis
+ // explode, so gather them to keep the compile time bounded.
+ if (S.getOpcode() == Instruction::PHI) {
+ unsigned NumIncomingValues =
+ cast<PHINode>(S.getMainOp())->getNumIncomingValues();
+ if (static_cast<uint64_t>(VL.size()) * NumIncomingValues >
+ PHINodeVectorizationBudget) {
+ LLVM_DEBUG(dbgs() << "SLP: Gathering due to wide PHI operand fan-out ("
+ << VL.size() << " lanes x " << NumIncomingValues
+ << " incoming values).\n");
+ return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
+ }
+ }
+
// Don't handle vectors.
if (!SLPReVec && getValueType(VL.front())->isVectorTy()) {
LLVM_DEBUG(dbgs() << "SLP: Gathering due to vector type.\n");
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-vectorization-budget.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-vectorization-budget.ll
new file mode 100644
index 0000000000000..3534498ec5c87
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-vectorization-budget.ll
@@ -0,0 +1,55 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=slp-vectorizer -slp-threshold=-100 -mtriple=x86_64-unknown-linux-gnu -S < %s | FileCheck %s --check-prefixes=VEC
+; RUN: opt -passes=slp-vectorizer -slp-threshold=-100 -slp-phi-vectorization-budget=3 -mtriple=x86_64-unknown-linux-gnu -S < %s | FileCheck %s --check-prefixes=BUDGET
+
+define void @phi_bundle(ptr %A, i32 %k) {
+; VEC-LABEL: @phi_bundle(
+; VEC-NEXT: entry:
+; VEC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[K:%.*]], 0
+; VEC-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
+; VEC: if.else:
+; VEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[A:%.*]], i64 10
+; VEC-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 8
+; VEC-NEXT: br label [[IF_END]]
+; VEC: if.end:
+; VEC-NEXT: [[TMP1:%.*]] = phi <2 x double> [ [[TMP0]], [[IF_ELSE]] ], [ <double 3.000000e+00, double 5.000000e+00>, [[ENTRY:%.*]] ]
+; VEC-NEXT: store <2 x double> [[TMP1]], ptr [[A]], align 8
+; VEC-NEXT: ret void
+;
+; BUDGET-LABEL: @phi_bundle(
+; BUDGET-NEXT: entry:
+; BUDGET-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[K:%.*]], 0
+; BUDGET-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
+; BUDGET: if.else:
+; BUDGET-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[A:%.*]], i64 10
+; BUDGET-NEXT: [[TMP0:%.*]] = load double, ptr [[ARRAYIDX]], align 8
+; BUDGET-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, ptr [[A]], i64 11
+; BUDGET-NEXT: [[TMP1:%.*]] = load double, ptr [[ARRAYIDX1]], align 8
+; BUDGET-NEXT: br label [[IF_END]]
+; BUDGET: if.end:
+; BUDGET-NEXT: [[A0_0:%.*]] = phi double [ [[TMP0]], [[IF_ELSE]] ], [ 3.000000e+00, [[ENTRY:%.*]] ]
+; BUDGET-NEXT: [[A1_0:%.*]] = phi double [ [[TMP1]], [[IF_ELSE]] ], [ 5.000000e+00, [[ENTRY]] ]
+; BUDGET-NEXT: store double [[A0_0]], ptr [[A]], align 8
+; BUDGET-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, ptr [[A]], i64 1
+; BUDGET-NEXT: store double [[A1_0]], ptr [[ARRAYIDX3]], align 8
+; BUDGET-NEXT: ret void
+;
+entry:
+ %tobool = icmp eq i32 %k, 0
+ br i1 %tobool, label %if.else, label %if.end
+
+if.else:
+ %arrayidx = getelementptr inbounds double, ptr %A, i64 10
+ %0 = load double, ptr %arrayidx, align 8
+ %arrayidx1 = getelementptr inbounds double, ptr %A, i64 11
+ %1 = load double, ptr %arrayidx1, align 8
+ br label %if.end
+
+if.end:
+ %A0.0 = phi double [ %0, %if.else ], [ 3.000000e+00, %entry ]
+ %A1.0 = phi double [ %1, %if.else ], [ 5.000000e+00, %entry ]
+ store double %A0.0, ptr %A, align 8
+ %arrayidx3 = getelementptr inbounds double, ptr %A, i64 1
+ store double %A1.0, ptr %arrayidx3, align 8
+ ret void
+}
More information about the llvm-commits
mailing list