Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,10 +329,6 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
for (const auto &[Name, Info] : make_early_inc_range(ForwardRefVals)) {
if (StringRef(Name).starts_with("llvm.")) {
Intrinsic::ID IID = Intrinsic::lookupIntrinsicID(Name);
if (IID == Intrinsic::not_intrinsic)
// Don't do anything for unknown intrinsics.
continue;

// Automatically create declarations for intrinsics. Intrinsics can only
// be called directly, so the call function type directly determines the
// declaration function type.
Expand All @@ -346,11 +342,26 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
return error(Info.second, "intrinsic can only be used as callee");

SmallVector<Type *> OverloadTys;
if (!Intrinsic::getIntrinsicSignature(IID, CB->getFunctionType(),
OverloadTys))
return error(Info.second, "invalid intrinsic signature");

U.set(Intrinsic::getOrInsertDeclaration(M, IID, OverloadTys));
if (IID != Intrinsic::not_intrinsic &&
Intrinsic::getIntrinsicSignature(IID, CB->getFunctionType(),
OverloadTys)) {
U.set(Intrinsic::getOrInsertDeclaration(M, IID, OverloadTys));
} else {
// Try to upgrade the intrinsic.
Function *TmpF = Function::Create(CB->getFunctionType(),
Function::ExternalLinkage, Name, M);
Function *NewF = nullptr;
if (!UpgradeIntrinsicFunction(TmpF, NewF)) {
if (IID == Intrinsic::not_intrinsic)
return error(Info.second, "unknown intrinsic '" + Name + "'");
return error(Info.second, "invalid intrinsic signature");
}

U.set(TmpF);
UpgradeIntrinsicCall(CB, NewF);
if (TmpF->use_empty())
TmpF->eraseFromParent();
}
}

Info.first->eraseFromParent();
Expand Down
39 changes: 39 additions & 0 deletions llvm/test/Assembler/autoupgrade-lifetime-intrinsics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,45 @@ define void @remove_unanalyzable(ptr %p) {
ret void
}

define void @no_declaration() {
; CHECK-LABEL: define void @no_declaration() {
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1, addrspace(2)
; CHECK-NEXT: call void @llvm.lifetime.start.p2(ptr addrspace(2) [[A]])
; CHECK-NEXT: call void @llvm.lifetime.end.p2(ptr addrspace(2) [[A]])
; CHECK-NEXT: ret void
;
%a = alloca i8, addrspace(2)
call void @llvm.lifetime.start.p2(i64 1, ptr addrspace(2) %a)
call void @llvm.lifetime.end.p2(i64 1, ptr addrspace(2) %a)
ret void
}

define void @no_suffix1() {
; CHECK-LABEL: define void @no_suffix1() {
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1, addrspace(3)
; CHECK-NEXT: call void @llvm.lifetime.start.p3(ptr addrspace(3) [[A]])
; CHECK-NEXT: call void @llvm.lifetime.end.p3(ptr addrspace(3) [[A]])
; CHECK-NEXT: ret void
;
%a = alloca i8, addrspace(3)
call void @llvm.lifetime.start(i64 1, ptr addrspace(3) %a)
call void @llvm.lifetime.end(i64 1, ptr addrspace(3) %a)
ret void
}

define void @no_suffix2() {
Copy link
Contributor

@antoniofrighetto antoniofrighetto Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is convenient for extra coverage, but the intrinsic declaration is not really differing from no_suffix1() (just passing a different pointer), correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. The purpose of this test is to check that even though no_suffix1 and no_suffix2 both call @llvm.lifetime.start, they get upgraded to two different intrinsics, depending on address space.

; CHECK-LABEL: define void @no_suffix2() {
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1, addrspace(4)
; CHECK-NEXT: call void @llvm.lifetime.start.p4(ptr addrspace(4) [[A]])
; CHECK-NEXT: call void @llvm.lifetime.end.p4(ptr addrspace(4) [[A]])
; CHECK-NEXT: ret void
;
%a = alloca i8, addrspace(4)
call void @llvm.lifetime.start(i64 1, ptr addrspace(4) %a)
call void @llvm.lifetime.end(i64 1, ptr addrspace(4) %a)
ret void
}

declare void @llvm.lifetime.start.p0(i64, ptr)
declare void @llvm.lifetime.end.p0(i64, ptr)
declare void @llvm.lifetime.start.p1(i64, ptr addrspace(1))
Expand Down
5 changes: 4 additions & 1 deletion llvm/test/Assembler/autoupgrade-wasm-intrinsics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ define <4 x float> @test_fms(<4 x float> %a, <4 x float> %b, <4 x float> %c) {
ret <4 x float> %res
}

declare <16 x i8> @llvm.wasm.laneselect.v16i8(<16 x i8>, <16 x i8>, <16 x i8>)
; This declaration is intentionally omitted to check that intrinsic upgrade
; also works without a declaration.
; declare <16 x i8> @llvm.wasm.laneselect.v16i8(<16 x i8>, <16 x i8>, <16 x i8>)

declare <8 x i16> @llvm.wasm.dot.i8x16.i7x16.signed(<16 x i8>, <16 x i8>)
declare <4 x i32> @llvm.wasm.dot.i8x16.i7x16.add.signed(<16 x i8>, <16 x i8>, <4 x i32>)
declare <4 x float> @llvm.wasm.fma.v4f32(<4 x float>, <4 x float>, <4 x float>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

; Use of unknown intrinsic without declaration should be rejected.

; CHECK: error: use of undefined value '@llvm.foobar'
; CHECK: error: unknown intrinsic 'llvm.foobar'
define void @test() {
call i8 @llvm.foobar(i8 0, i16 1)
ret void
Expand Down