diff options
| author | Simon Dardis <simon.dardis@imgtec.com> | 2016-04-05 12:50:29 +0000 |
|---|---|---|
| committer | Simon Dardis <simon.dardis@imgtec.com> | 2016-04-05 12:50:29 +0000 |
| commit | d9d41f531ef63ecf14472df29c68d8113284f051 (patch) | |
| tree | 43394adb2c652f5c9a3c9e3b627c563dc43331a7 /llvm/lib | |
| parent | c79979299aea78ae516bea2ecb25e4d4add37f08 (diff) | |
| download | bcm5719-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.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Mips64r6InstrInfo.td | 17 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp | 49 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.cpp | 106 |
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; |

