For Darwin on ARMv6 and newer, make register r9 available for use as a
caller-saved register. llvm-svn: 73901
This commit is contained in:
parent
315fb72d36
commit
4582530a2c
|
@ -96,6 +96,8 @@ def HasV6 : Predicate<"Subtarget->hasV6Ops()">;
|
||||||
def IsThumb : Predicate<"Subtarget->isThumb()">;
|
def IsThumb : Predicate<"Subtarget->isThumb()">;
|
||||||
def HasThumb2 : Predicate<"Subtarget->hasThumb2()">;
|
def HasThumb2 : Predicate<"Subtarget->hasThumb2()">;
|
||||||
def IsARM : Predicate<"!Subtarget->isThumb()">;
|
def IsARM : Predicate<"!Subtarget->isThumb()">;
|
||||||
|
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
|
||||||
|
def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ARM Flag Definitions.
|
// ARM Flag Definitions.
|
||||||
|
@ -539,21 +541,22 @@ let isReturn = 1, isTerminator = 1 in
|
||||||
LdStMulFrm, "ldm${p}${addr:submode} $addr, $dst1",
|
LdStMulFrm, "ldm${p}${addr:submode} $addr, $dst1",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
|
// On non-Darwin platforms R9 is callee-saved.
|
||||||
let isCall = 1, Itinerary = IIC_Br,
|
let isCall = 1, Itinerary = IIC_Br,
|
||||||
Defs = [R0, R1, R2, R3, R12, LR,
|
Defs = [R0, R1, R2, R3, R12, LR,
|
||||||
D0, D1, D2, D3, D4, D5, D6, D7, CPSR] in {
|
D0, D1, D2, D3, D4, D5, D6, D7, CPSR] in {
|
||||||
def BL : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops),
|
def BL : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops),
|
||||||
"bl ${func:call}",
|
"bl ${func:call}",
|
||||||
[(ARMcall tglobaladdr:$func)]>;
|
[(ARMcall tglobaladdr:$func)]>, Requires<[IsNotDarwin]>;
|
||||||
|
|
||||||
def BL_pred : ABI<0b1011, (outs), (ins i32imm:$func, variable_ops),
|
def BL_pred : ABI<0b1011, (outs), (ins i32imm:$func, variable_ops),
|
||||||
"bl", " ${func:call}",
|
"bl", " ${func:call}",
|
||||||
[(ARMcall_pred tglobaladdr:$func)]>;
|
[(ARMcall_pred tglobaladdr:$func)]>, Requires<[IsNotDarwin]>;
|
||||||
|
|
||||||
// ARMv5T and above
|
// ARMv5T and above
|
||||||
def BLX : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm,
|
def BLX : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm,
|
||||||
"blx $func",
|
"blx $func",
|
||||||
[(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T]> {
|
[(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsNotDarwin]> {
|
||||||
let Inst{7-4} = 0b0011;
|
let Inst{7-4} = 0b0011;
|
||||||
let Inst{19-8} = 0b111111111111;
|
let Inst{19-8} = 0b111111111111;
|
||||||
let Inst{27-20} = 0b00010010;
|
let Inst{27-20} = 0b00010010;
|
||||||
|
@ -563,7 +566,36 @@ let isCall = 1, Itinerary = IIC_Br,
|
||||||
// ARMv4T
|
// ARMv4T
|
||||||
def BX : ABXIx2<(outs), (ins GPR:$func, variable_ops),
|
def BX : ABXIx2<(outs), (ins GPR:$func, variable_ops),
|
||||||
"mov lr, pc\n\tbx $func",
|
"mov lr, pc\n\tbx $func",
|
||||||
[(ARMcall_nolink GPR:$func)]>;
|
[(ARMcall_nolink GPR:$func)]>, Requires<[IsNotDarwin]>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Darwin R9 is call-clobbered.
|
||||||
|
let isCall = 1, Itinerary = IIC_Br,
|
||||||
|
Defs = [R0, R1, R2, R3, R9, R12, LR,
|
||||||
|
D0, D1, D2, D3, D4, D5, D6, D7, CPSR] in {
|
||||||
|
def BLr9 : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops),
|
||||||
|
"bl ${func:call}",
|
||||||
|
[(ARMcall tglobaladdr:$func)]>, Requires<[IsDarwin]>;
|
||||||
|
|
||||||
|
def BLr9_pred : ABI<0b1011, (outs), (ins i32imm:$func, variable_ops),
|
||||||
|
"bl", " ${func:call}",
|
||||||
|
[(ARMcall_pred tglobaladdr:$func)]>, Requires<[IsDarwin]>;
|
||||||
|
|
||||||
|
// ARMv5T and above
|
||||||
|
def BLXr9 : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm,
|
||||||
|
"blx $func",
|
||||||
|
[(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]> {
|
||||||
|
let Inst{7-4} = 0b0011;
|
||||||
|
let Inst{19-8} = 0b111111111111;
|
||||||
|
let Inst{27-20} = 0b00010010;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Uses = [LR] in {
|
||||||
|
// ARMv4T
|
||||||
|
def BXr9 : ABXIx2<(outs), (ins GPR:$func, variable_ops),
|
||||||
|
"mov lr, pc\n\tbx $func",
|
||||||
|
[(ARMcall_nolink GPR:$func)]>, Requires<[IsDarwin]>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1321,7 +1353,10 @@ def : ARMPat<(xor GPR:$LHS, so_imm2part:$RHS),
|
||||||
|
|
||||||
|
|
||||||
// Direct calls
|
// Direct calls
|
||||||
def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>;
|
def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>,
|
||||||
|
Requires<[IsNotDarwin]>;
|
||||||
|
def : ARMPat<(ARMcall texternalsym:$func), (BLr9 texternalsym:$func)>,
|
||||||
|
Requires<[IsDarwin]>;
|
||||||
|
|
||||||
// zextload i1 -> zextload i8
|
// zextload i1 -> zextload i8
|
||||||
def : ARMPat<(zextloadi1 addrmode2:$addr), (LDRB addrmode2:$addr)>;
|
def : ARMPat<(zextloadi1 addrmode2:$addr), (LDRB addrmode2:$addr)>;
|
||||||
|
|
|
@ -235,8 +235,10 @@ ARMRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned DarwinCalleeSavedRegs[] = {
|
static const unsigned DarwinCalleeSavedRegs[] = {
|
||||||
|
// Darwin ABI deviates from ARM standard ABI. R9 is not a callee-saved
|
||||||
|
// register.
|
||||||
ARM::LR, ARM::R7, ARM::R6, ARM::R5, ARM::R4,
|
ARM::LR, ARM::R7, ARM::R6, ARM::R5, ARM::R4,
|
||||||
ARM::R11, ARM::R10, ARM::R9, ARM::R8,
|
ARM::R11, ARM::R10, ARM::R8,
|
||||||
|
|
||||||
ARM::D15, ARM::D14, ARM::D13, ARM::D12,
|
ARM::D15, ARM::D14, ARM::D13, ARM::D12,
|
||||||
ARM::D11, ARM::D10, ARM::D9, ARM::D8,
|
ARM::D11, ARM::D10, ARM::D9, ARM::D8,
|
||||||
|
@ -256,6 +258,7 @@ ARMRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||||
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TargetRegisterClass * const ThumbCalleeSavedRegClasses[] = {
|
static const TargetRegisterClass * const ThumbCalleeSavedRegClasses[] = {
|
||||||
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass,
|
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass,
|
||||||
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::tGPRRegClass,
|
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::tGPRRegClass,
|
||||||
|
@ -265,7 +268,33 @@ ARMRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||||
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
return STI.isThumb() ? ThumbCalleeSavedRegClasses : CalleeSavedRegClasses;
|
|
||||||
|
static const TargetRegisterClass * const DarwinCalleeSavedRegClasses[] = {
|
||||||
|
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass,
|
||||||
|
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass,
|
||||||
|
&ARM::GPRRegClass, &ARM::GPRRegClass,
|
||||||
|
|
||||||
|
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
||||||
|
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const TargetRegisterClass * const DarwinThumbCalleeSavedRegClasses[] ={
|
||||||
|
&ARM::GPRRegClass, &ARM::tGPRRegClass, &ARM::tGPRRegClass,
|
||||||
|
&ARM::tGPRRegClass, &ARM::tGPRRegClass, &ARM::GPRRegClass,
|
||||||
|
&ARM::GPRRegClass, &ARM::GPRRegClass,
|
||||||
|
|
||||||
|
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
||||||
|
&ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass, &ARM::DPRRegClass,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (STI.isThumb()) {
|
||||||
|
return STI.isTargetDarwin()
|
||||||
|
? DarwinThumbCalleeSavedRegClasses : ThumbCalleeSavedRegClasses;
|
||||||
|
}
|
||||||
|
return STI.isTargetDarwin()
|
||||||
|
? DarwinCalleeSavedRegClasses : CalleeSavedRegClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitVector ARMRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
BitVector ARMRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||||
|
|
|
@ -87,6 +87,7 @@ def CPSR : ARMReg<0, "cpsr">;
|
||||||
// sp == Stack Pointer
|
// sp == Stack Pointer
|
||||||
// r12 == ip (scratch)
|
// r12 == ip (scratch)
|
||||||
// r7 == Frame Pointer (thumb-style backtraces)
|
// r7 == Frame Pointer (thumb-style backtraces)
|
||||||
|
// r9 == May be reserved as Thread Register
|
||||||
// r11 == Frame Pointer (arm-style backtraces)
|
// r11 == Frame Pointer (arm-style backtraces)
|
||||||
// r10 == Stack Limit
|
// r10 == Stack Limit
|
||||||
//
|
//
|
||||||
|
@ -115,13 +116,13 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
|
||||||
ARM::R4, ARM::R5, ARM::R6, ARM::R7,
|
ARM::R4, ARM::R5, ARM::R6, ARM::R7,
|
||||||
ARM::R8, ARM::R10,
|
ARM::R8, ARM::R10,
|
||||||
ARM::R11 };
|
ARM::R11 };
|
||||||
// FP is R7, R9 is available.
|
// FP is R7, R9 is available as non-callee-saved register.
|
||||||
|
// This is used by Darwin.
|
||||||
static const unsigned ARM_GPR_AO_3[] = {
|
static const unsigned ARM_GPR_AO_3[] = {
|
||||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||||
ARM::R12,ARM::LR,
|
ARM::R9, ARM::R12,ARM::LR,
|
||||||
ARM::R4, ARM::R5, ARM::R6,
|
ARM::R4, ARM::R5, ARM::R6,
|
||||||
ARM::R8, ARM::R9, ARM::R10,ARM::R11,
|
ARM::R8, ARM::R10,ARM::R11,ARM::R7 };
|
||||||
ARM::R7 };
|
|
||||||
// FP is R7, R9 is not available.
|
// FP is R7, R9 is not available.
|
||||||
static const unsigned ARM_GPR_AO_4[] = {
|
static const unsigned ARM_GPR_AO_4[] = {
|
||||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||||
|
@ -155,18 +156,16 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
|
||||||
GPRClass::iterator I;
|
GPRClass::iterator I;
|
||||||
|
|
||||||
if (Subtarget.isTargetDarwin()) {
|
if (Subtarget.isTargetDarwin()) {
|
||||||
if (Subtarget.isR9Reserved()) {
|
if (Subtarget.isR9Reserved())
|
||||||
I = ARM_GPR_AO_4 + (sizeof(ARM_GPR_AO_4)/sizeof(unsigned));
|
I = ARM_GPR_AO_4 + (sizeof(ARM_GPR_AO_4)/sizeof(unsigned));
|
||||||
} else {
|
else
|
||||||
I = ARM_GPR_AO_3 + (sizeof(ARM_GPR_AO_3)/sizeof(unsigned));
|
I = ARM_GPR_AO_3 + (sizeof(ARM_GPR_AO_3)/sizeof(unsigned));
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (Subtarget.isR9Reserved()) {
|
if (Subtarget.isR9Reserved())
|
||||||
I = ARM_GPR_AO_2 + (sizeof(ARM_GPR_AO_2)/sizeof(unsigned));
|
I = ARM_GPR_AO_2 + (sizeof(ARM_GPR_AO_2)/sizeof(unsigned));
|
||||||
} else {
|
else
|
||||||
I = ARM_GPR_AO_1 + (sizeof(ARM_GPR_AO_1)/sizeof(unsigned));
|
I = ARM_GPR_AO_1 + (sizeof(ARM_GPR_AO_1)/sizeof(unsigned));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Mac OS X requires FP not to be clobbered for backtracing purpose.
|
// Mac OS X requires FP not to be clobbered for backtracing purpose.
|
||||||
return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I;
|
return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I;
|
||||||
|
|
|
@ -16,15 +16,20 @@
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
ReserveR9("arm-reserve-r9", cl::Hidden,
|
||||||
|
cl::desc("Reserve R9, making it unavailable as GPR"));
|
||||||
|
|
||||||
ARMSubtarget::ARMSubtarget(const Module &M, const std::string &FS,
|
ARMSubtarget::ARMSubtarget(const Module &M, const std::string &FS,
|
||||||
bool isThumb)
|
bool isThumb)
|
||||||
: ARMArchVersion(V4T)
|
: ARMArchVersion(V4T)
|
||||||
, ARMFPUType(None)
|
, ARMFPUType(None)
|
||||||
, IsThumb(isThumb)
|
, IsThumb(isThumb)
|
||||||
, ThumbMode(Thumb1)
|
, ThumbMode(Thumb1)
|
||||||
, IsR9Reserved(false)
|
, IsR9Reserved(ReserveR9)
|
||||||
, stackAlignment(4)
|
, stackAlignment(4)
|
||||||
, CPUString("generic")
|
, CPUString("generic")
|
||||||
, TargetType(isELF) // Default to ELF unless otherwise specified.
|
, TargetType(isELF) // Default to ELF unless otherwise specified.
|
||||||
|
@ -83,5 +88,5 @@ ARMSubtarget::ARMSubtarget(const Module &M, const std::string &FS,
|
||||||
stackAlignment = 8;
|
stackAlignment = 8;
|
||||||
|
|
||||||
if (isTargetDarwin())
|
if (isTargetDarwin())
|
||||||
IsR9Reserved = true;
|
IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin -relocation-model=pic \
|
; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin -relocation-model=pic \
|
||||||
; RUN: -mattr=+v6 -ifcvt-limit=0 -stats |& grep asm-printer | grep 35
|
; RUN: -mattr=+v6 | grep r9
|
||||||
|
; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin -relocation-model=pic \
|
||||||
|
; RUN: -mattr=+v6 -arm-reserve-r9 -ifcvt-limit=0 -stats |& grep asm-printer
|
||||||
|
; | grep 35
|
||||||
|
|
||||||
define void @test(i32 %tmp56222, i32 %tmp36224, i32 %tmp46223, i32 %i.0196.0.ph, i32 %tmp8, i32* %tmp1011, i32** %tmp1, i32* %d2.1.out, i32* %d3.1.out, i32* %d0.1.out, i32* %d1.1.out) {
|
define void @test(i32 %tmp56222, i32 %tmp36224, i32 %tmp46223, i32 %i.0196.0.ph, i32 %tmp8, i32* %tmp1011, i32** %tmp1, i32* %d2.1.out, i32* %d3.1.out, i32* %d0.1.out, i32* %d1.1.out) {
|
||||||
newFuncRoot:
|
newFuncRoot:
|
||||||
|
|
Loading…
Reference in New Issue