summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@imgtec.com>2016-04-05 12:50:29 +0000
committerSimon Dardis <simon.dardis@imgtec.com>2016-04-05 12:50:29 +0000
commitd9d41f531ef63ecf14472df29c68d8113284f051 (patch)
tree43394adb2c652f5c9a3c9e3b627c563dc43331a7 /llvm/lib
parentc79979299aea78ae516bea2ecb25e4d4add37f08 (diff)
downloadbcm5719-llvm-d9d41f531ef63ecf14472df29c68d8113284f051.tar.gz
bcm5719-llvm-d9d41f531ef63ecf14472df29c68d8113284f051.zip
[mips] MIPSR6 Compact jump support
This patch adds support for compact jumps similiar to the previous compact branch support for MIPSR6. Unlike compact branches, compact jumps do not have a forbidden slot. As MipsInstrInfo::getEquivalentCompactForm can determine the correct expansion for jumps and branches for both microMIPS and MIPSR6, remove the unnecessary distinction in the delay slot filler. Reviewers: vkalintiris Subscribers: llvm-commits, dsanders llvm-svn: 265390
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Mips/Mips32r6InstrInfo.td4
-rw-r--r--llvm/lib/Target/Mips/Mips64r6InstrInfo.td17
-rw-r--r--llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp49
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.cpp106
4 files changed, 109 insertions, 67 deletions
diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
index f3bd2bf275f..3e2c8293c26 100644
--- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td
@@ -412,10 +412,11 @@ class JMP_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd,
dag InOperandList = (ins GPROpnd:$rt, opnd:$offset);
string AsmString = !strconcat(opstr, "\t$rt, $offset");
list<dag> Pattern = [];
- bit isTerminator = 1;
bit hasDelaySlot = 0;
InstrItinClass Itinerary = itin;
bit isCTI = 1;
+ bit isBranch = 1;
+ bit isIndirectBranch = 1;
}
class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16,
@@ -427,6 +428,7 @@ class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16,
class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16,
GPR32Opnd, II_JIALC> {
bit isBarrier = 1;
+ bit isTerminator = 1;
list<Register> Defs = [AT];
}
diff --git a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td
index b2fc9111170..d11f2a2890a 100644
--- a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td
@@ -76,6 +76,18 @@ class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd, II_SCD>;
class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>;
class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>;
+class JIALC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16,
+ GPR64Opnd> {
+ bit isCall = 1;
+ list<Register> Defs = [RA];
+}
+
+class JIC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR64Opnd> {
+ bit isBarrier = 1;
+ bit isTerminator = 1;
+ list<Register> Defs = [AT];
+}
+
//===----------------------------------------------------------------------===//
//
// Instruction Definitions
@@ -107,7 +119,10 @@ let DecoderNamespace = "Mips32r6_64r6_GP64" in {
def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64;
def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64;
}
-
+let isCodeGenOnly = 1 in {
+def JIALC64 : JIALC_ENC, JIALC64_DESC, ISA_MIPS64R6;
+def JIC64 : JIC_ENC, JIC64_DESC, ISA_MIPS64R6;
+}
//===----------------------------------------------------------------------===//
//
// Instruction Aliases
diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
index a40b51cb19f..0a7ffb10153 100644
--- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -205,9 +205,6 @@ namespace {
Iter replaceWithCompactBranch(MachineBasicBlock &MBB,
Iter Branch, DebugLoc DL);
- Iter replaceWithCompactJump(MachineBasicBlock &MBB,
- Iter Jump, DebugLoc DL);
-
/// This function checks if it is valid to move Candidate to the delay slot
/// and returns true if it isn't. It also updates memory and register
/// dependence information.
@@ -522,24 +519,6 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB,
return Branch;
}
-// Replace Jumps with the compact jump instruction.
-Iter Filler::replaceWithCompactJump(MachineBasicBlock &MBB,
- Iter Jump, DebugLoc DL) {
- const MipsInstrInfo *TII =
- MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo();
-
- const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM);
- MachineInstrBuilder MIB = BuildMI(MBB, Jump, DL, NewDesc);
-
- MIB.addReg(Jump->getOperand(0).getReg());
-
- Iter tmpIter = Jump;
- Jump = std::prev(Jump);
- MBB.erase(tmpIter);
-
- return Jump;
-}
-
// For given opcode returns opcode of corresponding instruction with short
// delay slot.
static int getEquivalentCallShort(int Opcode) {
@@ -604,31 +583,21 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
// corresponding instruction with short delay slot.
DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode())));
}
-
continue;
}
}
- // If instruction is BEQ or BNE with one ZERO register, then instead of
- // adding NOP replace this instruction with the corresponding compact
- // branch instruction, i.e. BEQZC or BNEZC.
- if (InMicroMipsMode) {
- if (TII->getEquivalentCompactForm(I)) {
- I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
- continue;
- }
-
- if (I->isIndirectBranch() || I->isReturn()) {
- // For microMIPS the PseudoReturn and PseudoIndirectBranch are always
- // expanded to JR_MM, so they can be replaced with JRC16_MM.
- I = replaceWithCompactJump(MBB, I, I->getDebugLoc());
- continue;
- }
- }
+ // For microMIPS if instruction is BEQ or BNE with one ZERO register, then
+ // instead of adding NOP replace this instruction with the corresponding
+ // compact branch instruction, i.e. BEQZC or BNEZC. Additionally
+ // PseudoReturn and PseudoIndirectBranch are expanded to JR_MM, so they can
+ // be replaced with JRC16_MM.
// For MIPSR6 attempt to produce the corresponding compact (no delay slot)
- // form of the branch. This should save putting in a NOP.
- if ((STI.hasMips32r6()) && TII->getEquivalentCompactForm(I)) {
+ // form of the CTI. For indirect jumps this will not require inserting a
+ // NOP and for branches will hopefully avoid requiring a NOP.
+ if ((InMicroMipsMode || STI.hasMips32r6()) &&
+ TII->getEquivalentCompactForm(I)) {
I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
continue;
}
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
index 84368d7b80f..0f4e820fb00 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp
@@ -261,24 +261,40 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
unsigned MipsInstrInfo::getEquivalentCompactForm(
const MachineBasicBlock::iterator I) const {
unsigned Opcode = I->getOpcode();
- bool canUseShortMMBranches =
- Subtarget.inMicroMipsMode() &&
- (Opcode == Mips::BNE || Opcode == Mips::BEQ) &&
- I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg();
+ bool canUseShortMicroMipsCTI = false;
- if (Subtarget.hasMips32r6() || canUseShortMMBranches) {
+ if (Subtarget.inMicroMipsMode()) {
+ switch (Opcode) {
+ case Mips::BNE:
+ case Mips::BEQ:
+ // microMIPS has NE,EQ branches that do not have delay slots provided one
+ // of the operands is zero.
+ if (I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg())
+ canUseShortMicroMipsCTI = true;
+ break;
+ // For microMIPS the PseudoReturn and PseudoIndirectBranch are always
+ // expanded to JR_MM, so they can be replaced with JRC16_MM.
+ case Mips::JR:
+ case Mips::PseudoReturn:
+ case Mips::PseudoIndirectBranch:
+ canUseShortMicroMipsCTI = true;
+ break;
+ }
+ }
+
+ if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) {
switch (Opcode) {
case Mips::B:
return Mips::BC;
case Mips::BAL:
return Mips::BALC;
case Mips::BEQ:
- if (canUseShortMMBranches)
+ if (canUseShortMicroMipsCTI)
return Mips::BEQZC_MM;
else
return Mips::BEQC;
case Mips::BNE:
- if (canUseShortMMBranches)
+ if (canUseShortMicroMipsCTI)
return Mips::BNEZC_MM;
else
return Mips::BNEC;
@@ -298,7 +314,23 @@ unsigned MipsInstrInfo::getEquivalentCompactForm(
return Mips::BLTUC;
case Mips::BLTZ:
return Mips::BLTZC;
- default:
+ // For MIPSR6, the instruction 'jic' can be used for these cases. Some
+ // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'.
+ case Mips::JR:
+ case Mips::PseudoReturn:
+ case Mips::PseudoIndirectBranch:
+ if (canUseShortMicroMipsCTI)
+ return Mips::JRC16_MM;
+ return Mips::JIC;
+ case Mips::JALRPseudo:
+ return Mips::JIALC;
+ case Mips::JR64:
+ case Mips::PseudoReturn64:
+ case Mips::PseudoIndirectBranch64:
+ return Mips::JIC64;
+ case Mips::JALR64Pseudo:
+ return Mips::JIALC64;
+ default:
return 0;
}
}
@@ -343,19 +375,20 @@ MachineInstrBuilder
MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
MachineBasicBlock::iterator I) const {
MachineInstrBuilder MIB;
- bool BranchWithZeroOperand = false;
// Certain branches have two forms: e.g beq $1, $zero, dst vs beqz $1, dest
// Pick the zero form of the branch for readable assembly and for greater
// branch distance in non-microMIPS mode.
- if (I->isBranch() && I->getOperand(1).isReg() &&
- // FIXME: Certain atomic sequences on mips64 generate 32bit references to
- // Mips::ZERO, which is incorrect. This test should be updated to use
- // Subtarget.getABI().GetZeroReg() when those atomic sequences and others
- // are fixed.
- (I->getOperand(1).getReg() == Mips::ZERO ||
- I->getOperand(1).getReg() == Mips::ZERO_64)) {
- BranchWithZeroOperand = true;
+ // FIXME: Certain atomic sequences on mips64 generate 32bit references to
+ // Mips::ZERO, which is incorrect. This test should be updated to use
+ // Subtarget.getABI().GetZeroReg() when those atomic sequences and others
+ // are fixed.
+ bool BranchWithZeroOperand =
+ (I->isBranch() && !I->isPseudo() && I->getOperand(1).isReg() &&
+ (I->getOperand(1).getReg() == Mips::ZERO ||
+ I->getOperand(1).getReg() == Mips::ZERO_64));
+
+ if (BranchWithZeroOperand) {
switch (NewOpc) {
case Mips::BEQC:
NewOpc = Mips::BEQZC;
@@ -369,20 +402,43 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
case Mips::BLTC:
NewOpc = Mips::BLTZC;
break;
- case Mips::BNEZC_MM:
- case Mips::BEQZC_MM:
- break;
- default:
- BranchWithZeroOperand = false;
- break;
}
}
MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc));
- for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J)
- if (!(BranchWithZeroOperand && (J == 1)))
+ // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an
+ // immediate 0 as an operand and requires the removal of it's %RA<imp-def>
+ // implicit operand as copying the implicit operations of the instructio we're
+ // looking at will give us the correct flags.
+ if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 ||
+ NewOpc == Mips::JIALC64) {
+
+ if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64)
+ MIB->RemoveOperand(0);
+
+ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) {
+ MIB.addOperand(I->getOperand(J));
+ }
+
+ MIB.addImm(0);
+
+ } else if (BranchWithZeroOperand) {
+ // For MIPSR6 and microMIPS branches with an explicit zero operand, copy
+ // everything after the zero.
+ MIB.addOperand(I->getOperand(0));
+
+ for (unsigned J = 2, E = I->getDesc().getNumOperands(); J < E; ++J) {
MIB.addOperand(I->getOperand(J));
+ }
+ } else {
+ // All other cases copy all other operands.
+ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) {
+ MIB.addOperand(I->getOperand(J));
+ }
+ }
+
+ MIB.copyImplicitOps(*I);
MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end());
return MIB;
OpenPOWER on IntegriCloud