diff options
Diffstat (limited to 'lib/Target/Mips/MicroMipsSizeReduction.cpp')
| -rw-r--r-- | lib/Target/Mips/MicroMipsSizeReduction.cpp | 158 | 
1 files changed, 141 insertions, 17 deletions
diff --git a/lib/Target/Mips/MicroMipsSizeReduction.cpp b/lib/Target/Mips/MicroMipsSizeReduction.cpp index 35948e36ad91..f2e014084e46 100644 --- a/lib/Target/Mips/MicroMipsSizeReduction.cpp +++ b/lib/Target/Mips/MicroMipsSizeReduction.cpp @@ -32,6 +32,9 @@ namespace {  enum OperandTransfer {    OT_NA,          ///< Not applicable    OT_OperandsAll, ///< Transfer all operands +  OT_Operands02,  ///< Transfer operands 0 and 2 +  OT_Operand2,    ///< Transfer just operand 2 +  OT_OperandsXOR, ///< Transfer operands for XOR16  };  /// Reduction type @@ -143,14 +146,27 @@ private:    // returns true on success.    static bool ReduceSXtoSX16(MachineInstr *MI, const ReduceEntry &Entry); -  // Attempts to reduce arithmetic instructions, returns true on success +  // Attempts to reduce arithmetic instructions, returns true on success.    static bool ReduceArithmeticInstructions(MachineInstr *MI,                                             const ReduceEntry &Entry); -  // Changes opcode of an instruction +  // Attempts to reduce ADDIU into ADDIUSP instruction, +  // returns true on success. +  static bool ReduceADDIUToADDIUSP(MachineInstr *MI, const ReduceEntry &Entry); + +  // Attempts to reduce ADDIU into ADDIUR1SP instruction, +  // returns true on success. +  static bool ReduceADDIUToADDIUR1SP(MachineInstr *MI, +                                     const ReduceEntry &Entry); + +  // Attempts to reduce XOR into XOR16 instruction, +  // returns true on success. +  static bool ReduceXORtoXOR16(MachineInstr *MI, const ReduceEntry &Entry); + +  // Changes opcode of an instruction.    static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry); -  // Table with transformation rules for each instruction +  // Table with transformation rules for each instruction.    static llvm::SmallVector<ReduceEntry, 16> ReduceTable;  }; @@ -158,12 +174,20 @@ char MicroMipsSizeReduce::ID = 0;  const MipsInstrInfo *MicroMipsSizeReduce::MipsII;  // This table must be sorted by WideOpc as a main criterion and -// ReduceType as a sub-criterion (when wide opcodes are the same) +// ReduceType as a sub-criterion (when wide opcodes are the same).  llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {      // ReduceType, OpCodes, ReduceFunction,      // OpInfo(TransferOperands),      // ImmField(Shift, LBound, HBound, ImmFieldPosition) +    {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUR1SP_MM), +     ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, +    {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUSP_MM), ReduceADDIUToADDIUSP, +     OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)}, +    {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUR1SP_MM), +     ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, +    {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUSP_MM), +     ReduceADDIUToADDIUSP, OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)},      {RT_OneInstr, OpCodes(Mips::ADDu, Mips::ADDU16_MM),       ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),       ImmField(0, 0, 0, -1)}, @@ -174,6 +198,8 @@ llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {       OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)},      {RT_OneInstr, OpCodes(Mips::LBu_MM, Mips::LBU16_MM), ReduceLXUtoLXU16,       OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, +    {RT_OneInstr, OpCodes(Mips::LEA_ADDiu, Mips::ADDIUR1SP_MM), +     ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},      {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16,       OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},      {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16, @@ -200,10 +226,13 @@ llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {       OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},      {RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP,       OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, -}; -} +    {RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16, +     OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}, +    {RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16, +     OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}}; +} // namespace -// Returns true if the machine operand MO is register SP +// Returns true if the machine operand MO is register SP.  static bool IsSP(const MachineOperand &MO) {    if (MO.isReg() && ((MO.getReg() == Mips::SP)))      return true; @@ -225,7 +254,7 @@ static bool isMMSourceRegister(const MachineOperand &MO) {  }  // Returns true if the operand Op is an immediate value -// and writes the immediate value into variable Imm +// and writes the immediate value into variable Imm.  static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm) {    if (!MI->getOperand(Op).isImm()) @@ -234,17 +263,27 @@ static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm) {    return true;  } +// Returns true if the value is a valid immediate for ADDIUSP. +static bool AddiuspImmValue(int64_t Value) { +  int64_t Value2 = Value >> 2; +  if (((Value & (int64_t)maskTrailingZeros<uint64_t>(2)) == Value) && +      ((Value2 >= 2 && Value2 <= 257) || (Value2 >= -258 && Value2 <= -3))) +    return true; +  return false; +} +  // Returns true if the variable Value has the number of least-significant zero -// bits equal to Shift and if the shifted value is between the bounds +// bits equal to Shift and if the shifted value is between the bounds.  static bool InRange(int64_t Value, unsigned short Shift, int LBound,                      int HBound) {    int64_t Value2 = Value >> Shift; -  if ((Value2 << Shift) == Value && (Value2 >= LBound) && (Value2 < HBound)) +  if (((Value & (int64_t)maskTrailingZeros<uint64_t>(Shift)) == Value) && +      (Value2 >= LBound) && (Value2 < HBound))      return true;    return false;  } -// Returns true if immediate operand is in range +// Returns true if immediate operand is in range.  static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) {    int64_t offset; @@ -310,6 +349,34 @@ bool MicroMipsSizeReduce::ReduceArithmeticInstructions(    return ReplaceInstruction(MI, Entry);  } +bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI, +                                                 const ReduceEntry &Entry) { + +  if (!ImmInRange(MI, Entry)) +    return false; + +  if (!isMMThreeBitGPRegister(MI->getOperand(0)) || !IsSP(MI->getOperand(1))) +    return false; + +  return ReplaceInstruction(MI, Entry); +} + +bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI, +                                               const ReduceEntry &Entry) { + +  int64_t ImmValue; +  if (!GetImm(MI, Entry.ImmField(), ImmValue)) +    return false; + +  if (!AddiuspImmValue(ImmValue)) +    return false; + +  if (!IsSP(MI->getOperand(0)) || !IsSP(MI->getOperand(1))) +    return false; + +  return ReplaceInstruction(MI, Entry); +} +  bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI,                                             const ReduceEntry &Entry) { @@ -336,6 +403,20 @@ bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI,    return ReplaceInstruction(MI, Entry);  } +bool MicroMipsSizeReduce::ReduceXORtoXOR16(MachineInstr *MI, +                                           const ReduceEntry &Entry) { +  if (!isMMThreeBitGPRegister(MI->getOperand(0)) || +      !isMMThreeBitGPRegister(MI->getOperand(1)) || +      !isMMThreeBitGPRegister(MI->getOperand(2))) +    return false; + +  if (!(MI->getOperand(0).getReg() == MI->getOperand(2).getReg()) && +      !(MI->getOperand(0).getReg() == MI->getOperand(1).getReg())) +    return false; + +  return ReplaceInstruction(MI, Entry); +} +  bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) {    bool Modified = false;    MachineBasicBlock::instr_iterator MII = MBB.instr_begin(), @@ -361,19 +442,62 @@ bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) {  bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI,                                               const ReduceEntry &Entry) { -  MI->setDesc(MipsII->get(Entry.NarrowOpc())); -  DEBUG(dbgs() << "Converted into 16-bit: " << *MI); +  enum OperandTransfer OpTransfer = Entry.TransferOperands(); + +  DEBUG(dbgs() << "Converting 32-bit: " << *MI);    ++NumReduced; -  return true; + +  if (OpTransfer == OT_OperandsAll) { +    MI->setDesc(MipsII->get(Entry.NarrowOpc())); +    DEBUG(dbgs() << "       to 16-bit: " << *MI); +    return true; +  } else { +    MachineBasicBlock &MBB = *MI->getParent(); +    const MCInstrDesc &NewMCID = MipsII->get(Entry.NarrowOpc()); +    DebugLoc dl = MI->getDebugLoc(); +    MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, NewMCID); +    switch (OpTransfer) { +    case OT_Operand2: +      MIB.add(MI->getOperand(2)); +      break; +    case OT_Operands02: { +      MIB.add(MI->getOperand(0)); +      MIB.add(MI->getOperand(2)); +      break; +    } +    case OT_OperandsXOR: { +      if (MI->getOperand(0).getReg() == MI->getOperand(2).getReg()) { +        MIB.add(MI->getOperand(0)); +        MIB.add(MI->getOperand(1)); +        MIB.add(MI->getOperand(2)); +      } else { +        MIB.add(MI->getOperand(0)); +        MIB.add(MI->getOperand(2)); +        MIB.add(MI->getOperand(1)); +      } +      break; +    } +    default: +      llvm_unreachable("Unknown operand transfer!"); +    } + +    // Transfer MI flags. +    MIB.setMIFlags(MI->getFlags()); + +    DEBUG(dbgs() << "       to 16-bit: " << *MIB); +    MBB.erase_instr(MI); +    return true; +  } +  return false;  }  bool MicroMipsSizeReduce::runOnMachineFunction(MachineFunction &MF) {    Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); -  // TODO: Add support for other subtargets: -  // microMIPS32r6 and microMIPS64r6 -  if (!Subtarget->inMicroMipsMode() || !Subtarget->hasMips32r2()) +  // TODO: Add support for the subtarget microMIPS32R6. +  if (!Subtarget->inMicroMipsMode() || !Subtarget->hasMips32r2() || +      Subtarget->hasMips32r6())      return false;    MipsII = static_cast<const MipsInstrInfo *>(Subtarget->getInstrInfo());  | 
