summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Mips
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Mips')
-rw-r--r--llvm/lib/Target/Mips/MicroMipsInstrInfo.td18
-rw-r--r--llvm/lib/Target/Mips/Mips32r6InstrInfo.td2
-rw-r--r--llvm/lib/Target/Mips/Mips64InstrInfo.td8
-rw-r--r--llvm/lib/Target/Mips/Mips64r6InstrInfo.td4
-rw-r--r--llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp22
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.cpp4
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td7
-rw-r--r--llvm/lib/Target/Mips/MipsSEISelLowering.cpp6
8 files changed, 61 insertions, 10 deletions
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
index fdf3c5f0e8c..de2f7d49844 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -471,6 +471,18 @@ class JumpRegCMM16<string opstr, RegisterOperand RO> :
let isIndirectBranch = 1;
}
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
+ hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in {
+ class TailCall_MM<Instruction JumpInst> :
+ PseudoSE<(outs), (ins calltarget:$target), [], II_J>,
+ PseudoInstExpansion<(JumpInst jmptarget_mm:$target)>;
+
+ class TailCallReg_MM<RegisterOperand RO, Instruction JRInst,
+ RegisterOperand ResRO = RO> :
+ PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
+ PseudoInstExpansion<(JRInst ResRO:$rs)>;
+}
+
// Break16 and Sdbbp16
class BrkSdbbp16MM<string opstr> :
MicroMipsInst16<(outs), (ins uimm4:$code_),
@@ -969,6 +981,12 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def PREFX_MM : PrefetchIndexed<"prefx">, POOL32F_PREFX_FM_MM<0x15, 0x1A0>;
}
+let AdditionalPredicates = [InMicroMips] in {
+ def TAILCALL_MM : TailCall_MM<J_MM>, ISA_MIPS1_NOT_32R6_64R6;
+ def TAILCALLREG_MM : TailCallReg_MM<GPR32Opnd, JR_MM>,
+ ISA_MIPS1_NOT_32R6_64R6;
+}
+
let DecoderNamespace = "MicroMips" in {
def RDHWR_MM : MMRel, R6MMR6Rel, ReadHardware<GPR32Opnd, HWRegsOpnd>,
RDHWR_FM_MM, ISA_MICROMIPS32_NOT_MIPS32R6;
diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
index f552f8d37af..be239b0aa60 100644
--- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
@@ -848,6 +848,8 @@ let AdditionalPredicates = [NotInMicroMips] in {
def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6;
def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6;
}
+def TAILCALL_R6 : TailCall<J>, ISA_MIPS32R6;
+def TAILCALLREG_R6 : TailCallReg<GPR32Opnd, JR>, GPR_32, ISA_MIPS32R6;
//===----------------------------------------------------------------------===//
//
diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td
index 39313e11890..c3d8754416a 100644
--- a/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -228,22 +228,24 @@ def LL64 : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_64,
ISA_MIPS2_NOT_32R6_64R6;
def SC64 : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_64,
ISA_MIPS2_NOT_32R6_64R6;
+def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>, PTR_64;
}
+def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM;
+
/// Jump and Branch Instructions
let isCodeGenOnly = 1 in {
- def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>;
def BEQ64 : CBranch<"beq", brtarget, seteq, GPR64Opnd>, BEQ_FM<4>;
def BNE64 : CBranch<"bne", brtarget, setne, GPR64Opnd>, BEQ_FM<5>;
def BGEZ64 : CBranchZero<"bgez", brtarget, setge, GPR64Opnd>, BGEZ_FM<1, 1>;
def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>;
def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>;
def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>;
- def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM;
def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>;
- def TAILCALL64_R : TailCallReg<GPR64Opnd, JR, GPR32Opnd>;
+ def TAILCALLREG64 : TailCallReg<GPR64Opnd, JR64>, GPR_64, ISA_MIPS1_NOT_32R6_64R6;
}
+
def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>;
def PseudoIndirectBranch64 : PseudoIndirectBranchBase<GPR64Opnd>;
diff --git a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td
index cc01400bb0d..0f366608cba 100644
--- a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td
@@ -165,6 +165,10 @@ def BLTZC64 : BLTZC_ENC, BLTZC64_DESC, ISA_MIPS64R6, GPR_64;
def BGEZC64 : BGEZC_ENC, BGEZC64_DESC, ISA_MIPS64R6, GPR_64;
}
+def TAILCALL64_R6 : TailCall<J>, ISA_MIPS64R6;
+def TAILCALLREG64_R6 : TailCallReg<GPR64Opnd, JR64>, GPR_64,
+ ISA_MIPS64R6;
+
//===----------------------------------------------------------------------===//
//
// Instruction Aliases
diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
index 44bb872554d..c473c6ccd06 100644
--- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -543,6 +543,9 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch,
// For given opcode returns opcode of corresponding instruction with short
// delay slot.
+// For the pseudo TAILCALL*_MM instrunctions return the short delay slot
+// form. Unfortunately, TAILCALL<->b16 is denied as b16 has a limited range
+// that is too short to make use of for tail calls.
static int getEquivalentCallShort(int Opcode) {
switch (Opcode) {
case Mips::BGEZAL:
@@ -555,6 +558,10 @@ static int getEquivalentCallShort(int Opcode) {
return Mips::JALRS_MM;
case Mips::JALR16_MM:
return Mips::JALRS16_MM;
+ case Mips::TAILCALL_MM:
+ llvm_unreachable("Attempting to shorten the TAILCALL_MM pseudo!");
+ case Mips::TAILCALLREG_MM:
+ return Mips::JR16_MM;
default:
llvm_unreachable("Unexpected call instruction for microMIPS.");
}
@@ -606,6 +613,12 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
DSI->isCall()) {
// If instruction in delay slot is 16b change opcode to
// corresponding instruction with short delay slot.
+
+ // TODO: Implement an instruction mapping table of 16bit opcodes to
+ // 32bit opcodes so that an instruction can be expanded. This would
+ // save 16 bits as a TAILCALL_MM pseudo requires a fullsized nop.
+ // TODO: Permit b16 when branching backwards to the the same function
+ // if it is in range.
DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode())));
}
continue;
@@ -692,9 +705,14 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End,
bool InMicroMipsMode = STI.inMicroMipsMode();
const MipsInstrInfo *TII = STI.getInstrInfo();
unsigned Opcode = (*Slot).getOpcode();
- if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 &&
+ // This is complicated by the tail call optimization. For non-PIC code
+ // there is only a 32bit sized unconditional branch which can be assumed
+ // to be able to reach the target. b16 only has a range of +/- 1 KB.
+ // It's entirely possible that the target function is reachable with b16
+ // but we don't have enough information to make that decision.
+ if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 &&
(Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
- Opcode == Mips::PseudoReturn))
+ Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL))
continue;
Filler = CurrI;
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
index 1f38ca6447b..c317ecb91b2 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
@@ -282,6 +282,7 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
case Mips::JR:
case Mips::PseudoReturn:
case Mips::PseudoIndirectBranch:
+ case Mips::TAILCALLREG_MM:
canUseShortMicroMipsCTI = true;
break;
}
@@ -362,6 +363,8 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
case Mips::JR:
case Mips::PseudoReturn:
case Mips::PseudoIndirectBranch:
+ case Mips::TAILCALLREG_MM:
+ case Mips::TAILCALLREG_R6:
if (canUseShortMicroMipsCTI)
return Mips::JRC16_MM;
return Mips::JIC;
@@ -370,6 +373,7 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
case Mips::JR64:
case Mips::PseudoReturn64:
case Mips::PseudoIndirectBranch64:
+ case Mips::TAILCALLREG64_R6:
return Mips::JIC64;
case Mips::JALR64Pseudo:
return Mips::JIALC64;
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 43e4818e264..ff8a5fba732 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -1918,8 +1918,11 @@ def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>,
def BLTZALL : MMRel, BGEZAL_FT<"bltzall", brtarget, GPR32Opnd, 0>,
BGEZAL_FM<0x12>, ISA_MIPS2_NOT_32R6_64R6;
def BAL_BR : BAL_BR_Pseudo<BGEZAL>;
-def TAILCALL : TailCall<J>;
-def TAILCALL_R : TailCallReg<GPR32Opnd, JR>;
+
+let AdditionalPredicates = [NotInMicroMips] in {
+def TAILCALL : TailCall<J>, ISA_MIPS1_NOT_32R6_64R6;
+def TAILCALLREG : TailCallReg<GPR32Opnd, JR>, ISA_MIPS1_NOT_32R6_64R6, GPR_32;
+}
// Indirect branches are matched as PseudoIndirectBranch/PseudoIndirectBranch64
// then are expanded to JR, JR64, JALR, or JALR64 depending on the ISA.
diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
index 80c000d5746..73c461ba9f0 100644
--- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -27,8 +27,8 @@ using namespace llvm;
#define DEBUG_TYPE "mips-isel"
static cl::opt<bool>
-EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden,
- cl::desc("MIPS: Enable tail calls."), cl::init(false));
+UseMipsTailCalls("mips-tail-calls", cl::Hidden,
+ cl::desc("MIPS: permit tail calls."), cl::init(true));
static cl::opt<bool> NoDPLoadStore("mno-ldc1-sdc1", cl::init(false),
cl::desc("Expand double precision loads and "
@@ -1178,7 +1178,7 @@ MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
bool MipsSETargetLowering::isEligibleForTailCallOptimization(
const CCState &CCInfo, unsigned NextStackOffset,
const MipsFunctionInfo &FI) const {
- if (!EnableMipsTailCalls)
+ if (!UseMipsTailCalls)
return false;
// Exception has to be cleared with eret.
OpenPOWER on IntegriCloud