Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -1804,7 +1804,25 @@ ARMFunctionInfo *AFI = MF.getInfo(); auto PtrVt = getPointerTy(DAG.getDataLayout()); - if (Subtarget->genLongCalls()) { + bool isCalleeLongCall = false; + bool isCalleeShortCall = false; + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + const Function *CalleeF = dyn_cast(G->getGlobal()); + if (CalleeF) { + StringRef Features = + CalleeF->getFnAttribute("target-features").getValueAsString(); + SmallVector Tmp; + Features.split(Tmp, ','); + isCalleeLongCall = + std::find(Tmp.begin(), Tmp.end(), "+long-calls") != Tmp.end(); + isCalleeShortCall = + std::find(Tmp.begin(), Tmp.end(), "-long-calls") != Tmp.end(); + } + } + + // Generate long call if (1) callee is not short call and (2) either callee + // or caller has long-call attr. + if (!isCalleeShortCall && (isCalleeLongCall || Subtarget->genLongCalls())) { assert((Subtarget->isTargetWindows() || getTargetMachine().getRelocationModel() == Reloc::Static) && "long-calls with non-static relocation model!"); Index: test/CodeGen/ARM/long-calls.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/long-calls.ll @@ -0,0 +1,44 @@ +; RUN: llc -mtriple=thumbv7-linux-gnueabi -relocation-model=static %s -O0 -o - | FileCheck %s +target triple = "armv4t--linux-gnueabi" + +define i32 @caller_long() #0 { +; CHECK-LABEL: caller_long +entry: + call void @callee0() +; CHECK: ldr [[R0:r[0-9]+]], [[L0:.*]] +; CHECK: blx [[R0]] + call void @callee_long() +; CHECK: ldr [[R1:r[0-9]+]], [[L1:.*]] +; CHECK: blx [[R1]] + tail call void @callee_short() +; CHECK: bl callee_short + ret i32 0 +; CHECK: [[L0]]: +; CHECK: .long {{_?}}callee0 +; CHECK: [[L1]]: +; CHECK: .long {{_?}}callee_long +} + +define i32 @caller1() { +; CHECK-LABEL: caller1 +entry: + call void @callee0() +; CHECK: bl callee0 + call void @callee_long() +; CHECK: ldr{{.*}} [[R2:.+]], [[L2:.*]] +; CHECK: blx [[R2]] + tail call void @callee_short() +; CHECK: bl callee_short + ret i32 0 +; CHECK: [[L2]]: +; CHECK: .long callee_long +} + +declare void @callee0() + +declare void @callee_long() #0 + +declare void @callee_short() #1 + +attributes #0 = { "target-features"="+long-calls" } +attributes #1 = { "target-features"="-long-calls" }