[llvm] [SDAG] emit error when `llvm.type.checked.load` is not lowered (PR #208058)
Folkert de Vries via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 9 03:56:03 PDT 2026
https://github.com/folkertdev updated https://github.com/llvm/llvm-project/pull/208058
>From 0c082918a022ab2b6a7e2d38139d8e22d3f539b7 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Tue, 7 Jul 2026 19:50:41 +0200
Subject: [PATCH 1/4] [SDAG] emit error when `llvm.type.checked.load` is not
lowered
---
.../SelectionDAG/SelectionDAGBuilder.cpp | 10 +++++++++
.../CodeGen/X86/typed-load-must-be-lowered.ll | 21 +++++++++++++++++++
2 files changed, 31 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/typed-load-must-be-lowered.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index ba79b83f4cd54..92034f4a9c78a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7731,6 +7731,16 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
"LowerTypeTests pass before code generation");
return;
+ case Intrinsic::type_checked_load:
+ case Intrinsic::type_checked_load_relative:
+ // This likely indicates a misconfiguration where LowerTypeTests did not
+ // run but should have, for instance when devirtualization is enabled
+ // but LTO does not actually run.
+ reportFatalUsageError(
+ "llvm.type.checked.load intrinsic must be lowered by the "
+ "LowerTypeTests pass before code generation");
+ return;
+
case Intrinsic::assume:
case Intrinsic::experimental_noalias_scope_decl:
case Intrinsic::var_annotation:
diff --git a/llvm/test/CodeGen/X86/typed-load-must-be-lowered.ll b/llvm/test/CodeGen/X86/typed-load-must-be-lowered.ll
new file mode 100644
index 0000000000000..314851d946524
--- /dev/null
+++ b/llvm/test/CodeGen/X86/typed-load-must-be-lowered.ll
@@ -0,0 +1,21 @@
+; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
+; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
+
+; llvm.type.checked.load is expected to be lowered by the LowerTypeTests
+; pass before code generation.
+;
+; If it survives, emit a clean diagnostic instead of crashing (see issue #164663).
+
+; CHECK: llvm.type.checked.load intrinsic must be lowered by the LowerTypeTests pass
+
+define i1 @type_checked_load(ptr %vtable) {
+ %pair = call { ptr, i1 } @llvm.type.checked.load(ptr %vtable, i32 4, metadata !"typeid")
+ %ok = extractvalue { ptr, i1 } %pair, 1
+ ret i1 %ok
+}
+
+define i1 @type_checked_load_relative(ptr %vtable) {
+ %pair = call { ptr, i1 } @llvm.type.checked.load.relative(ptr %vtable, i32 4, metadata !"typeid")
+ %ok = extractvalue { ptr, i1 } %pair, 1
+ ret i1 %ok
+}
>From 2788aea34e2fd321c8913b33904f44fe99a6fdb5 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Thu, 9 Jul 2026 00:07:46 +0200
Subject: [PATCH 2/4] split out test files
---
.../X86/public-type-test-must-be-lowered.ll | 20 +++++++++++++++++++
...l => type-checked-load-must-be-lowered.ll} | 6 ------
...e-checked-load-relative-must-be-lowered.ll | 15 ++++++++++++++
...142937.ll => type-test-must-be-lowered.ll} | 20 +++++--------------
4 files changed, 40 insertions(+), 21 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
rename llvm/test/CodeGen/X86/{typed-load-must-be-lowered.ll => type-checked-load-must-be-lowered.ll} (74%)
create mode 100644 llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll
rename llvm/test/CodeGen/X86/{pr142937.ll => type-test-must-be-lowered.ll} (59%)
diff --git a/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll b/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
new file mode 100644
index 0000000000000..54e92fa554957
--- /dev/null
+++ b/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
+; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
+
+; llvm.public.type.test is expected to be lowered by the LowerTypeTests
+; pass before code generation.
+;
+; If it survives, emit a clean diagnostic instead of crashing (see issue #142937).
+
+; CHECK: must be lowered by the LowerTypeTests pass
+
+define void @public_type_test() {
+bb:
+ %call = call i1 @llvm.public.type.test(ptr null, metadata !"typeinfo")
+ br label %bb1
+
+bb1:
+ call void @llvm.assume(i1 %call)
+ ret void
+}
diff --git a/llvm/test/CodeGen/X86/typed-load-must-be-lowered.ll b/llvm/test/CodeGen/X86/type-checked-load-must-be-lowered.ll
similarity index 74%
rename from llvm/test/CodeGen/X86/typed-load-must-be-lowered.ll
rename to llvm/test/CodeGen/X86/type-checked-load-must-be-lowered.ll
index 314851d946524..57e3aa71e5025 100644
--- a/llvm/test/CodeGen/X86/typed-load-must-be-lowered.ll
+++ b/llvm/test/CodeGen/X86/type-checked-load-must-be-lowered.ll
@@ -13,9 +13,3 @@ define i1 @type_checked_load(ptr %vtable) {
%ok = extractvalue { ptr, i1 } %pair, 1
ret i1 %ok
}
-
-define i1 @type_checked_load_relative(ptr %vtable) {
- %pair = call { ptr, i1 } @llvm.type.checked.load.relative(ptr %vtable, i32 4, metadata !"typeid")
- %ok = extractvalue { ptr, i1 } %pair, 1
- ret i1 %ok
-}
diff --git a/llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll b/llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll
new file mode 100644
index 0000000000000..5eded3979f6bf
--- /dev/null
+++ b/llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll
@@ -0,0 +1,15 @@
+; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
+; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
+
+; llvm.type.checked.load.relative is expected to be lowered by the
+; LowerTypeTests pass before code generation.
+;
+; If it survives, emit a clean diagnostic instead of crashing (see issue #164663).
+
+; CHECK: llvm.type.checked.load intrinsic must be lowered by the LowerTypeTests pass
+
+define i1 @type_checked_load_relative(ptr %vtable) {
+ %pair = call { ptr, i1 } @llvm.type.checked.load.relative(ptr %vtable, i32 4, metadata !"typeid")
+ %ok = extractvalue { ptr, i1 } %pair, 1
+ ret i1 %ok
+}
diff --git a/llvm/test/CodeGen/X86/pr142937.ll b/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
similarity index 59%
rename from llvm/test/CodeGen/X86/pr142937.ll
rename to llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
index 675bb9ea52189..9ea77da7f1a7c 100644
--- a/llvm/test/CodeGen/X86/pr142937.ll
+++ b/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
@@ -2,17 +2,12 @@
; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
-; CHECK: must be lowered by the LowerTypeTests pass
-
-define void @public_type_test() {
-bb:
- %call = call i1 @llvm.public.type.test(ptr null, metadata !"typeinfo")
- br label %bb1
+; llvm.type.test is expected to be lowered by the LowerTypeTests
+; pass before code generation.
+;
+; If it survives, emit a clean diagnostic instead of crashing (see issue #142937).
-bb1:
- call void @llvm.assume(i1 %call)
- ret void
-}
+; CHECK: must be lowered by the LowerTypeTests pass
define void @type_test() {
bb:
@@ -26,8 +21,3 @@ bb1:
bb2:
ret void
}
-
-declare i1 @llvm.public.type.test(ptr, metadata)
-declare void @llvm.assume(i1 noundef)
-declare i1 @llvm.type.test(ptr, metadata)
-declare void @llvm.ubsantrap(i8 immarg)
>From ca5b5ce5f56b40a10b9b7aea27b91621cf910fcb Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Thu, 9 Jul 2026 12:28:28 +0200
Subject: [PATCH 3/4] update test files
---
llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll | 1 -
llvm/test/CodeGen/X86/type-test-must-be-lowered.ll | 1 -
2 files changed, 2 deletions(-)
diff --git a/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll b/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
index 54e92fa554957..5c74a43a3f6a6 100644
--- a/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
+++ b/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
diff --git a/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll b/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
index 9ea77da7f1a7c..450be033979eb 100644
--- a/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
+++ b/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
>From 577caaa1652ec6d453ab5eed031dfee93a57778b Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Thu, 9 Jul 2026 12:44:50 +0200
Subject: [PATCH 4/4] combine test files into one
---
.../SelectionDAG/SelectionDAGBuilder.cpp | 47 ++++++++++++++-----
.../X86/public-type-test-must-be-lowered.ll | 19 --------
.../X86/type-checked-load-must-be-lowered.ll | 15 ------
...e-checked-load-relative-must-be-lowered.ll | 15 ------
.../CodeGen/X86/type-test-must-be-lowered.ll | 22 ---------
.../CodeGen/X86/type-tests-must-be-lowered.ll | 46 ++++++++++++++++++
6 files changed, 82 insertions(+), 82 deletions(-)
delete mode 100644 llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
delete mode 100644 llvm/test/CodeGen/X86/type-checked-load-must-be-lowered.ll
delete mode 100644 llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll
delete mode 100644 llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
create mode 100644 llvm/test/CodeGen/X86/type-tests-must-be-lowered.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 92034f4a9c78a..6d625e1d89c88 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7727,19 +7727,44 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
case Intrinsic::type_test:
case Intrinsic::public_type_test:
- reportFatalUsageError("llvm.type.test intrinsic must be lowered by the "
- "LowerTypeTests pass before code generation");
- return;
-
case Intrinsic::type_checked_load:
- case Intrinsic::type_checked_load_relative:
- // This likely indicates a misconfiguration where LowerTypeTests did not
- // run but should have, for instance when devirtualization is enabled
- // but LTO does not actually run.
- reportFatalUsageError(
- "llvm.type.checked.load intrinsic must be lowered by the "
- "LowerTypeTests pass before code generation");
+ case Intrinsic::type_checked_load_relative: {
+ // These intrinsics are expected to be lowered by the LowerTypeTests pass
+ // before code generation. Surviving until here usually indicates a
+ // misconfiguration, for instance when devirtualization is enabled but LTO
+ // does not actually run.
+ const char *Name = [&] {
+ switch (Intrinsic) {
+ case Intrinsic::type_test:
+ return "llvm.type.test";
+ case Intrinsic::public_type_test:
+ return "llvm.public.type.test";
+ case Intrinsic::type_checked_load:
+ return "llvm.type.checked.load";
+ default:
+ return "llvm.type.checked.load.relative";
+ }
+ }();
+
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ *I.getFunction(),
+ Twine(Name) + " intrinsic must be lowered by the LowerTypeTests pass "
+ "before code generation",
+ sdl.getDebugLoc()));
+
+ // Lower the result to poison so that compilation can continue and collect
+ // any further diagnostics.
+ if (!I.getType()->isVoidTy()) {
+ SmallVector<EVT, 4> ValueVTs;
+ ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(),
+ I.getType(), ValueVTs);
+ SmallVector<SDValue, 4> Results;
+ for (EVT VT : ValueVTs)
+ Results.push_back(DAG.getPOISON(VT));
+ setValue(&I, DAG.getMergeValues(Results, sdl));
+ }
return;
+ }
case Intrinsic::assume:
case Intrinsic::experimental_noalias_scope_decl:
diff --git a/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll b/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
deleted file mode 100644
index 5c74a43a3f6a6..0000000000000
--- a/llvm/test/CodeGen/X86/public-type-test-must-be-lowered.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
-; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
-
-; llvm.public.type.test is expected to be lowered by the LowerTypeTests
-; pass before code generation.
-;
-; If it survives, emit a clean diagnostic instead of crashing (see issue #142937).
-
-; CHECK: must be lowered by the LowerTypeTests pass
-
-define void @public_type_test() {
-bb:
- %call = call i1 @llvm.public.type.test(ptr null, metadata !"typeinfo")
- br label %bb1
-
-bb1:
- call void @llvm.assume(i1 %call)
- ret void
-}
diff --git a/llvm/test/CodeGen/X86/type-checked-load-must-be-lowered.ll b/llvm/test/CodeGen/X86/type-checked-load-must-be-lowered.ll
deleted file mode 100644
index 57e3aa71e5025..0000000000000
--- a/llvm/test/CodeGen/X86/type-checked-load-must-be-lowered.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
-; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
-
-; llvm.type.checked.load is expected to be lowered by the LowerTypeTests
-; pass before code generation.
-;
-; If it survives, emit a clean diagnostic instead of crashing (see issue #164663).
-
-; CHECK: llvm.type.checked.load intrinsic must be lowered by the LowerTypeTests pass
-
-define i1 @type_checked_load(ptr %vtable) {
- %pair = call { ptr, i1 } @llvm.type.checked.load(ptr %vtable, i32 4, metadata !"typeid")
- %ok = extractvalue { ptr, i1 } %pair, 1
- ret i1 %ok
-}
diff --git a/llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll b/llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll
deleted file mode 100644
index 5eded3979f6bf..0000000000000
--- a/llvm/test/CodeGen/X86/type-checked-load-relative-must-be-lowered.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
-; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
-
-; llvm.type.checked.load.relative is expected to be lowered by the
-; LowerTypeTests pass before code generation.
-;
-; If it survives, emit a clean diagnostic instead of crashing (see issue #164663).
-
-; CHECK: llvm.type.checked.load intrinsic must be lowered by the LowerTypeTests pass
-
-define i1 @type_checked_load_relative(ptr %vtable) {
- %pair = call { ptr, i1 } @llvm.type.checked.load.relative(ptr %vtable, i32 4, metadata !"typeid")
- %ok = extractvalue { ptr, i1 } %pair, 1
- ret i1 %ok
-}
diff --git a/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll b/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
deleted file mode 100644
index 450be033979eb..0000000000000
--- a/llvm/test/CodeGen/X86/type-test-must-be-lowered.ll
+++ /dev/null
@@ -1,22 +0,0 @@
-; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
-; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
-
-; llvm.type.test is expected to be lowered by the LowerTypeTests
-; pass before code generation.
-;
-; If it survives, emit a clean diagnostic instead of crashing (see issue #142937).
-
-; CHECK: must be lowered by the LowerTypeTests pass
-
-define void @type_test() {
-bb:
- %call = tail call i1 @llvm.type.test(ptr null, metadata !"typeinfo")
- br i1 %call, label %bb2, label %bb1
-
-bb1:
- tail call void @llvm.ubsantrap(i8 2)
- unreachable
-
-bb2:
- ret void
-}
diff --git a/llvm/test/CodeGen/X86/type-tests-must-be-lowered.ll b/llvm/test/CodeGen/X86/type-tests-must-be-lowered.ll
new file mode 100644
index 0000000000000..f0aeb1cb8127a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/type-tests-must-be-lowered.ll
@@ -0,0 +1,46 @@
+; RUN: not llc %s -mtriple=i686-- -O0 -filetype=null 2>&1 | FileCheck %s
+; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
+
+; The llvm.type.test, llvm.public.type.test, llvm.type.checked.load and
+; llvm.type.checked.load.relative intrinsics are expected to be lowered by the
+; LowerTypeTests pass before code generation. If one survives, emit a clean
+; diagnostic instead of crashing (see issues #142937 and #164663).
+
+; CHECK: llvm.type.test intrinsic must be lowered by the LowerTypeTests pass before code generation
+define void @type_test() {
+bb:
+ %call = tail call i1 @llvm.type.test(ptr null, metadata !"typeinfo")
+ br i1 %call, label %bb2, label %bb1
+
+bb1:
+ tail call void @llvm.ubsantrap(i8 2)
+ unreachable
+
+bb2:
+ ret void
+}
+
+; CHECK: llvm.public.type.test intrinsic must be lowered by the LowerTypeTests pass before code generation
+define void @public_type_test() {
+bb:
+ %call = call i1 @llvm.public.type.test(ptr null, metadata !"typeinfo")
+ br label %bb1
+
+bb1:
+ call void @llvm.assume(i1 %call)
+ ret void
+}
+
+; CHECK: llvm.type.checked.load intrinsic must be lowered by the LowerTypeTests pass before code generation
+define i1 @type_checked_load(ptr %vtable) {
+ %pair = call { ptr, i1 } @llvm.type.checked.load(ptr %vtable, i32 4, metadata !"typeid")
+ %ok = extractvalue { ptr, i1 } %pair, 1
+ ret i1 %ok
+}
+
+; CHECK: llvm.type.checked.load.relative intrinsic must be lowered by the LowerTypeTests pass before code generation
+define i1 @type_checked_load_relative(ptr %vtable) {
+ %pair = call { ptr, i1 } @llvm.type.checked.load.relative(ptr %vtable, i32 4, metadata !"typeid")
+ %ok = extractvalue { ptr, i1 } %pair, 1
+ ret i1 %ok
+}
More information about the llvm-commits
mailing list