[llvm] 7c15144 - [SDAG] emit error when `llvm.type.checked.load` is not lowered (#208058)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 01:58:37 PDT 2026
Author: Folkert de Vries
Date: 2026-07-14T10:58:33+02:00
New Revision: 7c151447bc8abceefa3be9e5f1b27b83803d77af
URL: https://github.com/llvm/llvm-project/commit/7c151447bc8abceefa3be9e5f1b27b83803d77af
DIFF: https://github.com/llvm/llvm-project/commit/7c151447bc8abceefa3be9e5f1b27b83803d77af.diff
LOG: [SDAG] emit error when `llvm.type.checked.load` is not lowered (#208058)
Fixes https://github.com/llvm/llvm-project/issues/164663
In rust we can enable devirtualization and LTO on a build that actually
builds a library and hence LTO does not really run. That means typed
loads are emitted, but they are not lowered (or cleaned up), which made
us hit an ICE. Giving a slightly better error message, analogous to the
existing one for `Intrinsic::type_test`, seems nice.
I'm putting this together based on
https://github.com/llvm/llvm-project/pull/179249 and
https://github.com/llvm/llvm-project/issues/164663#issuecomment-3433581033.
Added:
llvm/test/CodeGen/X86/type-tests-must-be-lowered.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
Removed:
llvm/test/CodeGen/X86/pr142937.ll
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 98c91e65b4752..0f6bd53cafdd8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1814,6 +1814,19 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) {
return Val;
}
+void SelectionDAGBuilder::setValueToPoison(const Value *V, const SDLoc &dl) {
+ if (V->getType()->isVoidTy())
+ return;
+
+ SmallVector<EVT, 4> ValueVTs;
+ ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(),
+ V->getType(), ValueVTs);
+ SmallVector<SDValue, 4> Results;
+ for (EVT VT : ValueVTs)
+ Results.push_back(DAG.getPOISON(VT));
+ setValue(V, DAG.getMergeValues(Results, dl));
+}
+
/// getNonRegisterValue - Return an SDValue for the given Value, but
/// don't look in FuncInfo.ValueMap for a virtual register.
SDValue SelectionDAGBuilder::getNonRegisterValue(const Value *V) {
@@ -5566,15 +5579,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
if (HasChain && !OnlyLoad)
DAG.setRoot(getRoot());
- 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, DL));
- }
+ setValueToPoison(&I, DL);
return;
}
@@ -7729,9 +7734,24 @@ 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");
+ case Intrinsic::type_checked_load:
+ 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.
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ *I.getFunction(),
+ Intrinsic::getBaseName(Intrinsic) +
+ " 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.
+ setValueToPoison(&I, sdl);
return;
+ }
case Intrinsic::assume:
case Intrinsic::experimental_noalias_scope_decl:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 21aac333a73cd..6c7711af078f0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -397,6 +397,8 @@ class SelectionDAGBuilder {
N = NewN;
}
+ void setValueToPoison(const Value *V, const SDLoc &dl);
+
bool shouldKeepJumpConditionsTogether(
const FunctionLoweringInfo &FuncInfo, const CondBrInst &I,
Instruction::BinaryOps Opc, const Value *Lhs, const Value *Rhs,
diff --git a/llvm/test/CodeGen/X86/pr142937.ll b/llvm/test/CodeGen/X86/pr142937.ll
deleted file mode 100644
index 675bb9ea52189..0000000000000
--- a/llvm/test/CodeGen/X86/pr142937.ll
+++ /dev/null
@@ -1,33 +0,0 @@
-; 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
-
-; 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
-}
-
-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
-}
-
-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)
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..2b49ee1826a36
--- /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: 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: 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: 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: 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