[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