mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-22 13:29:44 +00:00
Next round of tail call changes. Register used in a tail
call must not be callee-saved; following x86, add a new regclass to represent this. Also fixes a couple of bugs. Still disabled by default; Thumb doesn't work yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106053 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8a3eab9b20
commit
6470a116f1
@ -596,6 +596,7 @@ ARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI,
|
||||
return true;
|
||||
}
|
||||
case ARM::MOVr:
|
||||
case ARM::MOVr_TC:
|
||||
case ARM::tMOVr:
|
||||
case ARM::tMOVgpr2tgpr:
|
||||
case ARM::tMOVtgpr2gpr:
|
||||
@ -701,11 +702,11 @@ ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
const TargetRegisterClass *DestRC,
|
||||
const TargetRegisterClass *SrcRC,
|
||||
DebugLoc DL) const {
|
||||
// tGPR is used sometimes in ARM instructions that need to avoid using
|
||||
// certain registers. Just treat it as GPR here.
|
||||
if (DestRC == ARM::tGPRRegisterClass)
|
||||
// tGPR or tcGPR is used sometimes in ARM instructions that need to avoid
|
||||
// using certain registers. Just treat them as GPR here.
|
||||
if (DestRC == ARM::tGPRRegisterClass || DestRC == ARM::tcGPRRegisterClass)
|
||||
DestRC = ARM::GPRRegisterClass;
|
||||
if (SrcRC == ARM::tGPRRegisterClass)
|
||||
if (SrcRC == ARM::tGPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass)
|
||||
SrcRC = ARM::GPRRegisterClass;
|
||||
|
||||
// Allow DPR / DPR_VFP2 / DPR_8 cross-class copies.
|
||||
@ -799,7 +800,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
|
||||
// tGPR is used sometimes in ARM instructions that need to avoid using
|
||||
// certain registers. Just treat it as GPR here.
|
||||
if (RC == ARM::tGPRRegisterClass)
|
||||
if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass)
|
||||
RC = ARM::GPRRegisterClass;
|
||||
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
@ -890,7 +891,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
|
||||
// tGPR is used sometimes in ARM instructions that need to avoid using
|
||||
// certain registers. Just treat it as GPR here.
|
||||
if (RC == ARM::tGPRRegisterClass)
|
||||
if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass)
|
||||
RC = ARM::GPRRegisterClass;
|
||||
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
|
@ -1662,13 +1662,15 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
|
||||
addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
|
||||
JumpTarget.getTargetFlags());
|
||||
} else if (RetOpcode == ARM::TCRETURNri) {
|
||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr), JumpTarget.getReg());
|
||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr)).
|
||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||
} else if (RetOpcode == ARM::TCRETURNriND) {
|
||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND), JumpTarget.getReg());
|
||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND)).
|
||||
addReg(JumpTarget.getReg(), RegState::Kill);
|
||||
}
|
||||
|
||||
MachineInstr *NewMI = prior(MBBI);
|
||||
for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i)
|
||||
for (unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i)
|
||||
NewMI->addOperand(MBBI->getOperand(i));
|
||||
|
||||
// Delete the pseudo instruction TCRETURN.
|
||||
|
@ -1109,11 +1109,14 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||
// Build a sequence of copy-to-reg nodes chained together with token chain
|
||||
// and flag operands which copy the outgoing args into the appropriate regs.
|
||||
SDValue InFlag;
|
||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
||||
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
|
||||
RegsToPass[i].second, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
// Tail call byval lowering might overwrite argument registers so in case of
|
||||
// tail call optimization the copies to registers are lowered later.
|
||||
if (!isTailCall)
|
||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
||||
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
|
||||
RegsToPass[i].second, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
// For tail calls lower the arguments to the 'real' stack slot.
|
||||
if (isTailCall) {
|
||||
|
@ -349,6 +349,83 @@ def tGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> {
|
||||
}];
|
||||
}
|
||||
|
||||
// For tail calls, we can't use callee-saved registers, as they are restored
|
||||
// to the saved value before the tail call, which would clobber a call address.
|
||||
// Note, getMinimalPhysRegClass(R0) returns tGPR because of the names of
|
||||
// this class and the preceding one(!) This is what we want.
|
||||
def tcGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R9, R12]> {
|
||||
let MethodProtos = [{
|
||||
iterator allocation_order_begin(const MachineFunction &MF) const;
|
||||
iterator allocation_order_end(const MachineFunction &MF) const;
|
||||
}];
|
||||
let MethodBodies = [{
|
||||
// R9 is available.
|
||||
static const unsigned ARM_GPR_R9_TC[] = {
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||
ARM::R9, ARM::R12 };
|
||||
// R9 is not available.
|
||||
static const unsigned ARM_GPR_NOR9_TC[] = {
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||
ARM::R12 };
|
||||
|
||||
// For Thumb1 mode, we don't want to allocate hi regs at all, as we
|
||||
// don't know how to spill them. If we make our prologue/epilogue code
|
||||
// smarter at some point, we can go back to using the above allocation
|
||||
// orders for the Thumb1 instructions that know how to use hi regs.
|
||||
static const unsigned THUMB_GPR_AO_TC[] = {
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
|
||||
|
||||
tcGPRClass::iterator
|
||||
tcGPRClass::allocation_order_begin(const MachineFunction &MF) const {
|
||||
const TargetMachine &TM = MF.getTarget();
|
||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
||||
if (Subtarget.isThumb1Only())
|
||||
return THUMB_GPR_AO_TC;
|
||||
if (Subtarget.isTargetDarwin()) {
|
||||
if (Subtarget.isR9Reserved())
|
||||
return ARM_GPR_NOR9_TC;
|
||||
else
|
||||
return ARM_GPR_R9_TC;
|
||||
} else {
|
||||
if (Subtarget.isR9Reserved())
|
||||
return ARM_GPR_NOR9_TC;
|
||||
else if (Subtarget.isThumb())
|
||||
return ARM_GPR_R9_TC;
|
||||
else
|
||||
return ARM_GPR_R9_TC;
|
||||
}
|
||||
}
|
||||
|
||||
tcGPRClass::iterator
|
||||
tcGPRClass::allocation_order_end(const MachineFunction &MF) const {
|
||||
const TargetMachine &TM = MF.getTarget();
|
||||
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
|
||||
GPRClass::iterator I;
|
||||
|
||||
if (Subtarget.isThumb1Only()) {
|
||||
I = THUMB_GPR_AO_TC + (sizeof(THUMB_GPR_AO_TC)/sizeof(unsigned));
|
||||
return I;
|
||||
}
|
||||
|
||||
if (Subtarget.isTargetDarwin()) {
|
||||
if (Subtarget.isR9Reserved())
|
||||
I = ARM_GPR_NOR9_TC + (sizeof(ARM_GPR_NOR9_TC)/sizeof(unsigned));
|
||||
else
|
||||
I = ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned));
|
||||
} else {
|
||||
if (Subtarget.isR9Reserved())
|
||||
I = ARM_GPR_NOR9_TC + (sizeof(ARM_GPR_NOR9_TC)/sizeof(unsigned));
|
||||
else if (Subtarget.isThumb())
|
||||
I = ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned));
|
||||
else
|
||||
I = ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned));
|
||||
}
|
||||
return I;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
// Scalar single precision floating point register class..
|
||||
def SPR : RegisterClass<"ARM", [f32], 32, [S0, S1, S2, S3, S4, S5, S6, S7, S8,
|
||||
S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22,
|
||||
|
@ -39,8 +39,8 @@ bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
const TargetRegisterClass *DestRC,
|
||||
const TargetRegisterClass *SrcRC,
|
||||
DebugLoc DL) const {
|
||||
if (DestRC == ARM::GPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
if (DestRC == ARM::GPRRegisterClass || DestRC == ARM::tcGPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
@ -48,7 +48,7 @@ bool Thumb1InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
return true;
|
||||
}
|
||||
} else if (DestRC == ARM::tGPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
|
@ -42,8 +42,8 @@ Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
const TargetRegisterClass *DestRC,
|
||||
const TargetRegisterClass *SrcRC,
|
||||
DebugLoc DL) const {
|
||||
if (DestRC == ARM::GPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
if (DestRC == ARM::GPRRegisterClass || DestRC == ARM::tcGPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVgpr2gpr), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
@ -51,7 +51,7 @@ Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
return true;
|
||||
}
|
||||
} else if (DestRC == ARM::tGPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass || SrcRC == ARM::tcGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVgpr2tgpr), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
@ -70,7 +70,8 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned SrcReg, bool isKill, int FI,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass) {
|
||||
if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass ||
|
||||
RC == ARM::tcGPRRegisterClass) {
|
||||
DebugLoc DL;
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
@ -95,7 +96,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, int FI,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass) {
|
||||
if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass ||
|
||||
RC == ARM::tcGPRRegisterClass) {
|
||||
DebugLoc DL;
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
|
@ -1579,7 +1579,8 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction(
|
||||
if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" ||
|
||||
Name == "TCRETURNri" || Name == "TCRETURNriND" ||
|
||||
Name == "TAILJMPd" || Name == "TAILJMPdND" ||
|
||||
Name == "TAILJMPr" || Name == "TAILJMPrND")
|
||||
Name == "TAILJMPr" || Name == "TAILJMPrND" ||
|
||||
Name == "MOVr_TC")
|
||||
return false;
|
||||
|
||||
// VLDMQ/VSTMQ can be hanlded with the more generic VLDMD/VSTMD.
|
||||
|
@ -570,6 +570,7 @@ static void X86ExtractSemantics(
|
||||
static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
const std::string &name) {
|
||||
REG("GPR");
|
||||
REG("tcGPR");
|
||||
REG("cc_out");
|
||||
REG("s_cc_out");
|
||||
REG("tGPR");
|
||||
|
Loading…
x
Reference in New Issue
Block a user