[libc-commits] [libc] [llvm] [LLVM][libc] Defer lowering of constant intrinsics in full LTO (PR #221505)
Joseph Huber via libc-commits
libc-commits at lists.llvm.org
Sun Sep 6 05:50:58 PDT 2026
https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/221505
>From 6c5e3589f0a35933f605185a0f3a252983c6254e Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Sat, 5 Sep 2026 19:10:55 -0500
Subject: [PATCH 1/2] [LLVM][libc] Defer lowering of constant intrinsics in
full LTO
Summary:
This PR defers the lowering of the constant intrinsics. Currently it was
inheriting the default module pipeline and being done pessimistically in
the pre-link LTO phase. This means that some objects which would become
known constants were returned as failures. Doing this in the post-link
phase is more optimistic.
I included the `libc` change that justifies this in the PR, but it can
be split out if needed. The observation is that the ExpandVariadics pass
will lower most variadic calls on the GPU to an alloca of known size.
Using this opportunistically saves us a spill to stack ordinarily needed
to copy back the size from the GPU. Without this, every use of GPU
printf resulted in a spill to stack memory.
Hopefully this is benign enough.
---
libc/src/stdio/gpu/vfprintf_utils.h | 4 ++++
llvm/lib/Passes/PassBuilderPipelines.cpp | 9 ++++++++-
llvm/test/Other/new-pm-defaults.ll | 2 +-
llvm/test/Other/new-pm-lto-defaults.ll | 2 ++
4 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/libc/src/stdio/gpu/vfprintf_utils.h b/libc/src/stdio/gpu/vfprintf_utils.h
index 70eb98c838bec..3f540f01f48f5 100644
--- a/libc/src/stdio/gpu/vfprintf_utils.h
+++ b/libc/src/stdio/gpu/vfprintf_utils.h
@@ -34,6 +34,10 @@ LIBC_INLINE int vfprintf_impl(::FILE *__restrict file,
port.recv([&](rpc::Buffer *buffer, uint32_t) {
args_size = static_cast<size_t>(buffer->data[0]);
});
+ // Use the vlist's static alloca size when it is exact and known.
+ if (size_t n = __builtin_object_size(vlist, /*max=*/0);
+ n == __builtin_object_size(vlist, /*min=*/2))
+ args_size = n;
port.send_n(vlist, args_size);
uint32_t ret = 0;
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 901250fdd787e..d67e4f6d6a90b 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1582,7 +1582,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
}
OptimizePM.addPass(Float2IntPass());
- OptimizePM.addPass(LowerConstantIntrinsicsPass());
+ // Defer until LTO post-link where some constants may become known.
+ if (!isLTOPreLink(LTOPhase))
+ OptimizePM.addPass(LowerConstantIntrinsicsPass());
if (EnableMatrix) {
OptimizePM.addPass(LowerMatrixIntrinsicsPass());
@@ -2122,6 +2124,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
MPM.addPass(NoRecurseLTOInferencePass());
// Stop here at -O1.
if (Level == OptimizationLevel::O1) {
+ MPM.addPass(createModuleToFunctionPassAdaptor(
+ LowerConstantIntrinsicsPass(), PTO.EagerlyInvalidateAnalyses));
+
// The LowerTypeTestsPass needs to run to lower type metadata and the
// type.test intrinsics. The pass does nothing if CFI is disabled.
MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr));
@@ -2288,6 +2293,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
MainFPM.addPass(MoveAutoInitPass());
MainFPM.addPass(MergedLoadStoreMotionPass());
+ MainFPM.addPass(LowerConstantIntrinsicsPass());
+
invokeVectorizerStartEPCallbacks(MainFPM, Level);
LoopPassManager LPM;
diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index 2c1a57e00c9f1..0eb201432132c 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -229,7 +229,7 @@
; CHECK-EP-OPTIMIZER-EARLY: Running pass: NoOpModulePass
; CHECK-DEFAULT-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: Float2IntPass
-; CHECK-O-NEXT: Running pass: LowerConstantIntrinsicsPass on foo
+; CHECK-DEFAULT-NEXT: Running pass: LowerConstantIntrinsicsPass on foo
; CHECK-MATRIX: Running pass: LowerMatrixIntrinsicsPass on f
; CHECK-MATRIX-NEXT: Running pass: EarlyCSEPass on f
; CHECK-O3-NEXT: Running pass: ControlHeightReductionPass
diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll
index 14f189194d0e3..97bc3e5ce758a 100644
--- a/llvm/test/Other/new-pm-lto-defaults.ll
+++ b/llvm/test/Other/new-pm-lto-defaults.ll
@@ -66,6 +66,7 @@
; CHECK-O-NEXT: Running pass: WholeProgramDevirtPass
; CHECK-O-NEXT: Running pass: NoRecurseLTOInferencePass
; CHECK-O23-NEXT: Running pass: CoroEarlyPass
+; CHECK-O1-NEXT: Running pass: LowerConstantIntrinsicsPass on foo
; CHECK-O1-NEXT: Running pass: LowerTypeTestsPass
; CHECK-O23-NEXT: Running pass: GlobalOptPass
; CHECK-O23-NEXT: Running pass: PromotePass
@@ -118,6 +119,7 @@
; CHECK-O23-NEXT: Running analysis: CycleAnalysis
; CHECK-O23-NEXT: Running pass: MoveAutoInitPass on foo
; CHECK-O23-NEXT: Running pass: MergedLoadStoreMotionPass on foo
+; CHECK-O23-NEXT: Running pass: LowerConstantIntrinsicsPass on foo
; CHECK-EP-VECTORIZER-START-NEXT: Running pass: NoOpFunctionPass on foo
; CHECK-O23-NEXT: Running pass: LoopSimplifyPass on foo
; CHECK-O23-NEXT: Running pass: LCSSAPass on foo
>From f7edc60169ccd5e24378d88e4864930abb169ac6 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Sun, 6 Sep 2026 07:15:03 -0500
Subject: [PATCH 2/2] Update vfprintf_utils.h
---
libc/src/stdio/gpu/vfprintf_utils.h | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libc/src/stdio/gpu/vfprintf_utils.h b/libc/src/stdio/gpu/vfprintf_utils.h
index 3f540f01f48f5..70eb98c838bec 100644
--- a/libc/src/stdio/gpu/vfprintf_utils.h
+++ b/libc/src/stdio/gpu/vfprintf_utils.h
@@ -34,10 +34,6 @@ LIBC_INLINE int vfprintf_impl(::FILE *__restrict file,
port.recv([&](rpc::Buffer *buffer, uint32_t) {
args_size = static_cast<size_t>(buffer->data[0]);
});
- // Use the vlist's static alloca size when it is exact and known.
- if (size_t n = __builtin_object_size(vlist, /*max=*/0);
- n == __builtin_object_size(vlist, /*min=*/2))
- args_size = n;
port.send_n(vlist, args_size);
uint32_t ret = 0;
More information about the libc-commits
mailing list