diff options
Diffstat (limited to 'llvm/lib/Target/Mips/MipsInstrInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.cpp | 106 |
1 files changed, 81 insertions, 25 deletions
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; |

