[llvm] [LLVM] Autoupgrade invalid lifetime.start/lifetime.end intrinsics (PR #206769)
Rahul Joshi via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 09:52:34 PDT 2026
https://github.com/jurahul created https://github.com/llvm/llvm-project/pull/206769
LLVM's AutoUpgrade used to create invalid and unused `lifetime.start.i64` and `lifetime.end.i64` intrinsics. This was fixed with https://github.com/llvm/llvm-project/pull/204601. However, existing bitcode generated prior to this fix might still have these unused and invalid declarations in them. Adopt Autoupgrade to handle them.
Invalid declaration of these intrinsics will be deleted, and if there exists calls to these invalid intrinsics (not expected to be generated by AutoUpgrade prior to the bug fix, but handling this case just for completeness) these calls will be deleted.
>From dda438285d25663d103811d5c2e94542b7455d9b Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Tue, 30 Jun 2026 09:44:08 -0700
Subject: [PATCH] [LLVM] Autoupgrade invalid lifetime.start/lifetime.end
intrinsics
LLVM's AutoUpgrade used to create invalid and unused
`lifetime.start.i64` and `lifetime.end.i64` intrinsics. This was
fixed with https://github.com/llvm/llvm-project/pull/204601. However,
existing bitcode generated prior to this fix might still have these
unused and invalid declarations in them. Adopt Autoupgrade to handle
them.
Invalid declaration of these intrinsics will be deleted, and if there
exists calls to these invalid intrinsics (not expected to be generated
by AutoUpgrade prior to the bug fix, but handling this case just for
completeness) these calls will be deleted.
---
llvm/lib/IR/AutoUpgrade.cpp | 42 +++++++++++++------
...autoupgrade-lifetime-intrinsics-invalid.ll | 26 ++++++++++++
2 files changed, 55 insertions(+), 13 deletions(-)
create mode 100644 llvm/test/Assembler/autoupgrade-lifetime-intrinsics-invalid.ll
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 3a823f906b012..c6311b667365b 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -1552,21 +1552,34 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn,
return true;
}
break;
- case 'l':
- if ((Name.starts_with("lifetime.start") ||
- Name.starts_with("lifetime.end")) &&
- F->arg_size() == 2) {
- Intrinsic::ID IID = Name.starts_with("lifetime.start")
- ? Intrinsic::lifetime_start
- : Intrinsic::lifetime_end;
- rename(F);
- // Old 2 argument form of these intrinsics have [Size, Ptr] as arguments.
- // Use the Ptr argument to create new declaration.
- NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID,
- F->getArg(1)->getType());
- return true;
+ case 'l': {
+ bool IsLifetimeStart = Name.consume_front("lifetime.start");
+ bool IsLifetimeEnd = !IsLifetimeStart && Name.consume_front("lifetime.end");
+ if (IsLifetimeStart || IsLifetimeEnd) {
+ if (F->arg_size() == 2) {
+ Intrinsic::ID IID = IsLifetimeStart ? Intrinsic::lifetime_start
+ : Intrinsic::lifetime_end;
+ rename(F);
+ // Old 2 argument form of these intrinsics have [Size, Ptr] as
+ // arguments. Use the Ptr argument to create new declaration.
+ NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID,
+ F->getArg(1)->getType());
+ return true;
+ } else if (F->arg_size() == 1 && Name == ".i64") {
+ // Matches @llvm.nvvm/lifetime.{start/end}.i64 which used to be created
+ // by the Autoupgrader prior to
+ // https://github.com/llvm/llvm-project/pull/204601. This is an invalid
+ // intrinsic with no expected calls. To allow auto-upgrade process to
+ // delete such invalid intrinsic declaration, set NewFn = nullptr
+ // and return true here. If there are actual calls to this intrinsics
+ // (which is not expected), auto-upgrade wiill hit an llvm_unreachable()
+ // in UpgradeIntrinsicCall.
+ NewFn = nullptr;
+ return true;
+ }
}
break;
+ }
case 'm': {
// Updating the memory intrinsics (memcpy/memmove/memset) that have an
// alignment parameter to embedding the alignment as an attribute of
@@ -5125,6 +5138,9 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
Rep = upgradeVectorSplice(CI, Builder);
} else if (Name.consume_front("convert.")) {
Rep = upgradeConvertIntrinsicCall(Name, CI, F, Builder);
+ } else if (Name == "lifetime.start.i64" || Name == "lifetime.end.i64") {
+ // Delete calls to invalid lifetime.{start,end}.i64 intrinsics.
+ Rep = nullptr;
} else {
llvm_unreachable("Unknown function for CallBase upgrade.");
}
diff --git a/llvm/test/Assembler/autoupgrade-lifetime-intrinsics-invalid.ll b/llvm/test/Assembler/autoupgrade-lifetime-intrinsics-invalid.ll
new file mode 100644
index 0000000000000..7730d9478c337
--- /dev/null
+++ b/llvm/test/Assembler/autoupgrade-lifetime-intrinsics-invalid.ll
@@ -0,0 +1,26 @@
+; RUN: split-file %s %t
+
+;--- test1.ll
+; Verify that auto-upgrade eliminate the unused invalid declaration of lifetime
+; start and end intrinsics.
+; RUN: llvm-as < %t/test1.ll | llvm-dis | FileCheck %t/test1.ll
+; CHECK-NOT: @llvm.lifetime.start.i64(i64)
+; CHECK-NOT: @llvm.lifetime.end.i64(i64)
+
+declare void @llvm.lifetime.start.i64(i64)
+declare void @llvm.lifetime.end.i64(i64)
+
+;--- test2.ll
+; Verify that if there is an actual call to the invalid lifetime intrinsics,
+; auto-upgrade will fail.
+; RUN: llvm-as < %t/test2.ll | llvm-dis | FileCheck %t/test2.ll
+
+; CHECK-NOT: @llvm.lifetime.start.i64(i64)
+; CHECK-NOT: call void @llvm.lifetime.start.i64(i64 0)
+
+declare void @llvm.lifetime.start.i64(i64)
+
+define void @foo() {
+ call void @llvm.lifetime.start.i64(i64 0)
+ ret void
+}
More information about the llvm-commits
mailing list