aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MicroMipsSizeReduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips/MicroMipsSizeReduction.cpp')
-rw-r--r--lib/Target/Mips/MicroMipsSizeReduction.cpp158
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());