Skip to content

Commit

Permalink
[ARM] Define a subtarget feature and use it to decide whether long ca…
Browse files Browse the repository at this point in the history
…lls should

be emitted.

This is needed to enable ARM long calls for LTO and enable and disable it on a
per-function basis.

Out-of-tree projects currently using EnableARMLongCalls to emit long calls
should start passing "+long-calls" to the feature string (see the changes made
to clang in r241565).

rdar://problem/21529937

Differential Revision: http://reviews.llvm.org/D9364

llvm-svn: 241566
  • Loading branch information
ahatanaka committed Jul 7, 2015
1 parent 3fb33a5 commit 1bc8af7
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 21 deletions.
4 changes: 4 additions & 0 deletions llvm/lib/Target/ARM/ARM.td
Expand Up @@ -150,6 +150,10 @@ def FeatureAClass : SubtargetFeature<"aclass", "ARMProcClass", "AClass",
def FeatureNaClTrap : SubtargetFeature<"nacl-trap", "UseNaClTrap", "true",
"NaCl trap">;

def FeatureLongCalls : SubtargetFeature<"long-calls", "GenLongCalls", "true",
"Generate calls via indirect call "
"instructions">;

// ARM ISAs.
def HasV4TOps : SubtargetFeature<"v4t", "HasV4TOps", "true",
"Support ARM v4T instructions">;
Expand Down
10 changes: 4 additions & 6 deletions llvm/lib/Target/ARM/ARMFastISel.cpp
Expand Up @@ -49,8 +49,6 @@
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

extern cl::opt<bool> EnableARMLongCalls;

namespace {

// All possible address modes, plus some.
Expand Down Expand Up @@ -2246,19 +2244,19 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) {
return false;

unsigned CalleeReg = 0;
if (EnableARMLongCalls) {
if (Subtarget->genLongCalls()) {
CalleeReg = getLibcallReg(TLI.getLibcallName(Call));
if (CalleeReg == 0) return false;
}

// Issue the call.
unsigned CallOpc = ARMSelectCallOp(EnableARMLongCalls);
unsigned CallOpc = ARMSelectCallOp(Subtarget->genLongCalls());
MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
DbgLoc, TII.get(CallOpc));
// BL / BLX don't take a predicate, but tBL / tBLX do.
if (isThumb2)
AddDefaultPred(MIB);
if (EnableARMLongCalls)
if (Subtarget->genLongCalls())
MIB.addReg(CalleeReg);
else
MIB.addExternalSymbol(TLI.getLibcallName(Call));
Expand Down Expand Up @@ -2380,7 +2378,7 @@ bool ARMFastISel::SelectCall(const Instruction *I,

bool UseReg = false;
const GlobalValue *GV = dyn_cast<GlobalValue>(Callee);
if (!GV || EnableARMLongCalls) UseReg = true;
if (!GV || Subtarget->genLongCalls()) UseReg = true;

unsigned CalleeReg = 0;
if (UseReg) {
Expand Down
7 changes: 1 addition & 6 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Expand Up @@ -60,11 +60,6 @@ STATISTIC(NumTailCalls, "Number of tail calls");
STATISTIC(NumMovwMovt, "Number of GAs materialized with movw + movt");
STATISTIC(NumLoopByVals, "Number of loops generated for byval arguments");

cl::opt<bool>
EnableARMLongCalls("arm-long-calls", cl::Hidden,
cl::desc("Generate calls via indirect call instructions"),
cl::init(false));

static cl::opt<bool>
ARMInterworking("arm-interworking", cl::Hidden,
cl::desc("Enable / disable ARM interworking (for debugging only)"),
Expand Down Expand Up @@ -1694,7 +1689,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
bool isLocalARMFunc = false;
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();

if (EnableARMLongCalls) {
if (Subtarget->genLongCalls()) {
assert((Subtarget->isTargetWindows() ||
getTargetMachine().getRelocationModel() == Reloc::Static) &&
"long-calls with non-static relocation model!");
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/ARM/ARMSubtarget.cpp
Expand Up @@ -172,6 +172,7 @@ void ARMSubtarget::initializeEnvironment() {
AllowsUnalignedMem = false;
Thumb2DSP = false;
UseNaClTrap = false;
GenLongCalls = false;
UnsafeFPMath = false;
}

Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/ARM/ARMSubtarget.h
Expand Up @@ -206,6 +206,9 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
/// NaCl TRAP instruction is generated instead of the regular TRAP.
bool UseNaClTrap;

/// Generate calls via indirect call instructions.
bool GenLongCalls;

/// Target machine allowed unsafe FP math (such as use of NEON fp)
bool UnsafeFPMath;

Expand Down Expand Up @@ -342,6 +345,7 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
bool hasMPExtension() const { return HasMPExtension; }
bool hasThumb2DSP() const { return Thumb2DSP; }
bool useNaClTrap() const { return UseNaClTrap; }
bool genLongCalls() const { return GenLongCalls; }

bool hasFP16() const { return HasFP16; }
bool hasD16() const { return HasD16; }
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/ARM/Windows/long-calls.ll
@@ -1,4 +1,4 @@
; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 -arm-long-calls -o - %s \
; RUN: llc -mtriple=thumbv7-windows -mcpu=cortex-a9 -mattr=+long-calls -o - %s \
; RUN: | FileCheck %s

declare arm_aapcs_vfpcc void @callee()
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/CodeGen/ARM/fast-isel-call.ll
@@ -1,9 +1,9 @@
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=ARM
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi | FileCheck %s --check-prefix=ARM
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -arm-long-calls | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -arm-long-calls | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -arm-long-calls | FileCheck %s --check-prefix=THUMB-LONG
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -mattr=+long-calls | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -mattr=+long-calls | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -mattr=+long-calls | FileCheck %s --check-prefix=THUMB-LONG
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -mattr=-vfp2 | FileCheck %s --check-prefix=ARM-NOVFP
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -mattr=-vfp2 | FileCheck %s --check-prefix=ARM-NOVFP
; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -mattr=-vfp2 | FileCheck %s --check-prefix=THUMB-NOVFP
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/CodeGen/ARM/fast-isel-intrinsic.ll
@@ -1,9 +1,9 @@
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=ARM
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -verify-machineinstrs | FileCheck %s --check-prefix=ARM
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=THUMB
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -arm-long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -arm-long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -arm-long-calls -verify-machineinstrs | FileCheck %s --check-prefix=THUMB-LONG
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG
; RUN: llc < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=THUMB-LONG

; Note that some of these tests assume that relocations are either
; movw/movt or constant pool loads. Different platforms will select
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/ARM/fast-isel-static.ll
@@ -1,5 +1,5 @@
; RUN: llc < %s -mtriple=thumbv7-apple-ios -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=static -arm-long-calls | FileCheck -check-prefix=CHECK-LONG %s
; RUN: llc < %s -mtriple=armv7-linux-gnueabi -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=static -arm-long-calls | FileCheck -check-prefix=CHECK-LONG %s
; RUN: llc < %s -mtriple=thumbv7-apple-ios -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=static -mattr=+long-calls | FileCheck -check-prefix=CHECK-LONG %s
; RUN: llc < %s -mtriple=armv7-linux-gnueabi -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=static -mattr=+long-calls | FileCheck -check-prefix=CHECK-LONG %s
; RUN: llc < %s -mtriple=thumbv7-apple-ios -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=static | FileCheck -check-prefix=CHECK-NORM %s
; RUN: llc < %s -mtriple=armv7-linux-gnueabi -O0 -verify-machineinstrs -fast-isel-abort=1 -relocation-model=static | FileCheck -check-prefix=CHECK-NORM %s

Expand Down
40 changes: 40 additions & 0 deletions llvm/test/CodeGen/ARM/subtarget-features-long-calls.ll
@@ -0,0 +1,40 @@
; RUN: llc -march arm -mcpu cortex-a8 -relocation-model=static %s -o - | FileCheck -check-prefix=NO-OPTION %s
; RUN: llc -march arm -mcpu cortex-a8 -relocation-model=static %s -o - -mattr=+long-calls | FileCheck -check-prefix=LONGCALL %s
; RUN: llc -march arm -mcpu cortex-a8 -relocation-model=static %s -o - -mattr=-long-calls | FileCheck -check-prefix=NO-LONGCALL %s
; RUN: llc -march arm -mcpu cortex-a8 -relocation-model=static %s -o - -O0 | FileCheck -check-prefix=NO-OPTION %s
; RUN: llc -march arm -mcpu cortex-a8 -relocation-model=static %s -o - -O0 -mattr=+long-calls | FileCheck -check-prefix=LONGCALL %s
; RUN: llc -march arm -mcpu cortex-a8 -relocation-model=static %s -o - -O0 -mattr=-long-calls | FileCheck -check-prefix=NO-LONGCALL %s

; NO-OPTION-LABEL: {{_?}}caller0
; NO-OPTION: blx {{r[0-9]+}}

; LONGCALL-LABEL: {{_?}}caller0
; LONGCALL: blx {{r[0-9]+}}

; NO-LONGCALL-LABEL: {{_?}}caller0
; NO-LONGCALL: bl {{_?}}callee0

define i32 @caller0() #0 {
entry:
tail call void @callee0()
ret i32 0
}

; NO-OPTION-LABEL: {{_?}}caller1
; NO-OPTION: bl {{_?}}callee0

; LONGCALL-LABEL: {{_?}}caller1
; LONGCALL: blx {{r[0-9]+}}

; NO-LONGCALL-LABEL: {{_?}}caller1
; NO-LONGCALL: bl {{_?}}callee0

define i32 @caller1() {
entry:
tail call void @callee0()
ret i32 0
}

declare void @callee0()

attributes #0 = { "target-features"="+long-calls" }

0 comments on commit 1bc8af7

Please sign in to comment.