[llvm] [JumpTableToSwitch] Bail out on function type mismatch (PR #207700)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 6 03:55:49 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
If the function types of the functions in the jump table don't match the function type of the call, we currently get an assertion failure. We could avoid that by using a different API, but the usefulness of the transform in this case is questionable (e.g. we wouldn't be able to inline the call). For simplicity just bail out.
---
Full diff: https://github.com/llvm/llvm-project/pull/207700.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp (+5-3)
- (added) llvm/test/Transforms/JumpTableToSwitch/callee-type-mismatch.ll (+48)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
index d5696bc9ea956..bd4946ac5e69f 100644
--- a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
@@ -61,7 +61,8 @@ struct JumpTableTy {
} // anonymous namespace
static std::optional<JumpTableTy> parseJumpTable(GetElementPtrInst *GEP,
- PointerType *PtrTy) {
+ PointerType *PtrTy,
+ FunctionType *CallFTy) {
Constant *Ptr = dyn_cast<Constant>(GEP->getPointerOperand());
if (!Ptr)
return std::nullopt;
@@ -101,7 +102,7 @@ static std::optional<JumpTableTy> parseJumpTable(GetElementPtrInst *GEP,
Constant *C =
ConstantFoldLoadFromConst(GV->getInitializer(), PtrTy, Offset, DL);
auto *Func = dyn_cast_or_null<Function>(C);
- if (!Func || Func->isDeclaration() ||
+ if (!Func || Func->isDeclaration() || Func->getFunctionType() != CallFTy ||
Func->getInstructionCount() > FunctionSizeThreshold)
return std::nullopt;
JumpTable.Funcs.push_back(Func);
@@ -240,7 +241,8 @@ PreservedAnalyses JumpTableToSwitchPass::run(Function &F,
continue;
auto *PtrTy = dyn_cast<PointerType>(L->getType());
assert(PtrTy && "call operand must be a pointer");
- std::optional<JumpTableTy> JumpTable = parseJumpTable(GEP, PtrTy);
+ std::optional<JumpTableTy> JumpTable =
+ parseJumpTable(GEP, PtrTy, Call->getFunctionType());
if (!JumpTable)
continue;
SplittedOutTail =
diff --git a/llvm/test/Transforms/JumpTableToSwitch/callee-type-mismatch.ll b/llvm/test/Transforms/JumpTableToSwitch/callee-type-mismatch.ll
new file mode 100644
index 0000000000000..04d3206268f38
--- /dev/null
+++ b/llvm/test/Transforms/JumpTableToSwitch/callee-type-mismatch.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=jump-table-to-switch -S | FileCheck %s
+
+ at arr_argcount = constant [1 x ptr] [ptr @f_argcount]
+ at arr_rettype = constant [1 x ptr] [ptr @f_rettype]
+
+define i32 @f_argcount(i32 %x) {
+; CHECK-LABEL: define i32 @f_argcount(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: ret i32 [[X]]
+;
+ ret i32 %x
+}
+
+define i64 @f_rettype() {
+; CHECK-LABEL: define i64 @f_rettype() {
+; CHECK-NEXT: ret i64 123
+;
+ ret i64 123
+}
+
+define i32 @argcount(i32 %idx) {
+; CHECK-LABEL: define i32 @argcount(
+; CHECK-SAME: i32 [[IDX:%.*]]) {
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr [1 x ptr], ptr @arr_argcount, i32 0, i32 [[IDX]]
+; CHECK-NEXT: [[FP:%.*]] = load ptr, ptr [[GEP]], align 8
+; CHECK-NEXT: [[R:%.*]] = call i32 [[FP]]()
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %gep = getelementptr [1 x ptr], ptr @arr_argcount, i32 0, i32 %idx
+ %fp = load ptr, ptr %gep
+ %r = call i32 %fp()
+ ret i32 %r
+}
+
+define i32 @rettype(i32 %idx) {
+; CHECK-LABEL: define i32 @rettype(
+; CHECK-SAME: i32 [[IDX:%.*]]) {
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr [1 x ptr], ptr @arr_rettype, i32 0, i32 [[IDX]]
+; CHECK-NEXT: [[FP:%.*]] = load ptr, ptr [[GEP]], align 8
+; CHECK-NEXT: [[R:%.*]] = call i32 [[FP]]()
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %gep = getelementptr [1 x ptr], ptr @arr_rettype, i32 0, i32 %idx
+ %fp = load ptr, ptr %gep
+ %r = call i32 %fp()
+ ret i32 %r
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/207700
More information about the llvm-commits
mailing list