diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -52,8 +52,18 @@ if (const Function *F = CS.getCalledFunction()) Info.Callee = MachineOperand::CreateGA(F, 0); - else - Info.Callee = MachineOperand::CreateReg(GetCalleeReg(), false); + else { + // Try looking through a bitcast from one function type to another. + // Commonly happens with calls to objc_msgSend(). + const Value *CalleeV = CS.getCalledValue(); + if (auto *BC = dyn_cast(CalleeV)) { + if (const auto *F = dyn_cast(BC->getOperand(0))) { + Info.Callee = MachineOperand::CreateGA(F, 0); + } + } else { + Info.Callee = MachineOperand::CreateReg(GetCalleeReg(), false); + } + } Info.OrigRet = ArgInfo{ResRegs, CS.getType(), ISD::ArgFlagsTy{}}; if (!Info.OrigRet.Ty->isVoidTy()) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/call-lowering-const-bitcast-func.ll b/llvm/test/CodeGen/AArch64/GlobalISel/call-lowering-const-bitcast-func.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/call-lowering-const-bitcast-func.ll @@ -0,0 +1,14 @@ +; RUN: llc -O0 -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-darwin-ios13.0" + +declare i8* @objc_msgSend(i8*, i8*, ...) +define void @call_bitcast_ptr_const() { +; CHECK-LABEL: @call_bitcast_ptr_const +; CHECK: bl _objc_msgSend +; CHECK-NOT: blr +entry: + call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, [2 x i32], i32, float)*)(i8* undef, i8* undef, [2 x i32] zeroinitializer, i32 0, float 1.000000e+00) + ret void +}