diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp --- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp +++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp @@ -190,7 +190,10 @@ if (I.getCondition() != LastVisited->first) return 0; - auto *C = cast(LastVisited->second); + auto *C = dyn_cast(LastVisited->second); + if (!C) + return 0; + BasicBlock *Succ = I.findCaseValue(C)->getCaseSuccessor(); // Initialize the worklist with the dead basic blocks. These are the // destination labels which are different from the one corresponding diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression6.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression6.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression6.ll @@ -0,0 +1,22 @@ +; RUN: opt -passes="ipsccp" -force-specialization -S < %s +; Check that we don't crash when SwitchInst Constant is not ConstantInt. + +@S = external constant [1 x i8] + +define i1 @foo() { +entry: + %tmp = call i32 @bar(ptr @S) + ret i1 0 +} + +define i32 @bar(ptr %arg) { +entry: + %magicptr = ptrtoint ptr %arg to i64 + switch i64 %magicptr, label %bb2 [ + i64 0, label %bb1 + ] +bb1: + ret i32 0 +bb2: + ret i32 1 +}