22#define DEBUG_TYPE "micromips-reduce-size"
23#define MICROMIPS_SIZE_REDUCE_NAME "MicroMips instruction size reduce pass"
25STATISTIC(NumReduced,
"Number of instructions reduced (32-bit to 16-bit ones, "
26 "or two instructions into one");
52 ImmField() : ImmFieldOperand(-1), Shift(0), LBound(0), HBound(0) {}
53 ImmField(uint8_t Shift, int16_t LBound, int16_t HBound,
54 int8_t ImmFieldOperand)
55 : ImmFieldOperand(ImmFieldOperand), Shift(Shift), LBound(LBound),
57 int8_t ImmFieldOperand;
66 OpInfo(
enum OperandTransfer TransferOperands)
67 : TransferOperands(TransferOperands) {}
68 OpInfo() : TransferOperands(OT_NA) {}
76 OpCodes(
unsigned WideOpc,
unsigned NarrowOpc)
77 : WideOpc(WideOpc), NarrowOpc(NarrowOpc) {}
83typedef struct ReduceEntryFunArgs ReduceEntryFunArgs;
89 enum ReduceType eRType;
90 bool (*ReduceFunction)(
96 ReduceEntry(
enum ReduceType RType,
struct OpCodes
Op,
97 bool (*
F)(ReduceEntryFunArgs *
Arguments),
struct OpInfo OpInf,
99 : eRType(RType), ReduceFunction(
F), Ops(
Op), OpInf(OpInf),
Imm(
Imm) {}
101 unsigned NarrowOpc()
const {
return Ops.NarrowOpc; }
102 unsigned WideOpc()
const {
return Ops.WideOpc; }
103 int16_t LBound()
const {
return Imm.LBound; }
104 int16_t HBound()
const {
return Imm.HBound; }
105 uint8_t Shift()
const {
return Imm.Shift; }
106 int8_t ImmField()
const {
return Imm.ImmFieldOperand; }
107 enum OperandTransfer TransferOperands()
const {
108 return OpInf.TransferOperands;
110 enum ReduceType RType()
const {
return eRType; }
113 bool operator<(
const unsigned int r)
const {
return (WideOpc() < r); }
116 friend bool operator<(
const unsigned int r,
const struct ReduceEntry &re) {
117 return (r < re.WideOpc());
122struct ReduceEntryFunArgs {
124 const ReduceEntry &
Entry;
128 ReduceEntryFunArgs(
MachineInstr *argMI,
const ReduceEntry &argEntry,
130 :
MI(argMI),
Entry(argEntry), NextMII(argNextMII) {}
138 MicroMipsSizeReduce();
146 return "microMIPS instruction size reduction pass";
159 static bool ReduceXWtoXWSP(ReduceEntryFunArgs *
Arguments);
163 static bool ReduceXWtoXWP(ReduceEntryFunArgs *
Arguments);
167 static bool ReduceLXUtoLXU16(ReduceEntryFunArgs *
Arguments);
171 static bool ReduceSXtoSX16(ReduceEntryFunArgs *
Arguments);
175 static bool ReduceMoveToMovep(ReduceEntryFunArgs *
Arguments);
178 static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *
Arguments);
182 static bool ReduceADDIUToADDIUSP(ReduceEntryFunArgs *
Arguments);
186 static bool ReduceADDIUToADDIUR1SP(ReduceEntryFunArgs *
Arguments);
190 static bool ReduceXORtoXOR16(ReduceEntryFunArgs *
Arguments);
196 static bool ReplaceInstruction(
MachineInstr *
MI,
const ReduceEntry &Entry,
198 bool ConsecutiveForward =
true);
201 static ReduceEntryVector ReduceTable;
204char MicroMipsSizeReduce::ID = 0;
209ReduceEntryVector MicroMipsSizeReduce::ReduceTable = {
214 {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUR1SP_MM),
215 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
216 {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUSP_MM), ReduceADDIUToADDIUSP,
217 OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)},
218 {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUR1SP_MM),
219 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
220 {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUSP_MM),
221 ReduceADDIUToADDIUSP, OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)},
222 {RT_OneInstr, OpCodes(Mips::ADDu, Mips::ADDU16_MM),
223 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
224 ImmField(0, 0, 0, -1)},
225 {RT_OneInstr, OpCodes(Mips::ADDu_MM, Mips::ADDU16_MM),
226 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
227 ImmField(0, 0, 0, -1)},
228 {RT_OneInstr, OpCodes(Mips::LBu, Mips::LBU16_MM), ReduceLXUtoLXU16,
229 OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)},
230 {RT_OneInstr, OpCodes(Mips::LBu_MM, Mips::LBU16_MM), ReduceLXUtoLXU16,
231 OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)},
232 {RT_OneInstr, OpCodes(Mips::LEA_ADDiu, Mips::ADDIUR1SP_MM),
233 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
234 {RT_OneInstr, OpCodes(Mips::LEA_ADDiu_MM, Mips::ADDIUR1SP_MM),
235 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
236 {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16,
237 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
238 {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16,
239 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
240 {RT_TwoInstr, OpCodes(Mips::LW, Mips::LWP_MM), ReduceXWtoXWP,
241 OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
242 {RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP,
243 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
244 {RT_TwoInstr, OpCodes(Mips::LW16_MM, Mips::LWP_MM), ReduceXWtoXWP,
245 OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
246 {RT_TwoInstr, OpCodes(Mips::LW_MM, Mips::LWP_MM), ReduceXWtoXWP,
247 OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
248 {RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP,
249 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
250 {RT_TwoInstr, OpCodes(Mips::MOVE16_MM, Mips::MOVEP_MM), ReduceMoveToMovep,
251 OpInfo(OT_OperandsMovep), ImmField(0, 0, 0, -1)},
252 {RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16,
253 OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)},
254 {RT_OneInstr, OpCodes(Mips::SB_MM, Mips::SB16_MM), ReduceSXtoSX16,
255 OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)},
256 {RT_OneInstr, OpCodes(Mips::SH, Mips::SH16_MM), ReduceSXtoSX16,
257 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
258 {RT_OneInstr, OpCodes(Mips::SH_MM, Mips::SH16_MM), ReduceSXtoSX16,
259 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
260 {RT_OneInstr, OpCodes(Mips::SUBu, Mips::SUBU16_MM),
261 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
262 ImmField(0, 0, 0, -1)},
263 {RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM),
264 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
265 ImmField(0, 0, 0, -1)},
266 {RT_TwoInstr, OpCodes(Mips::SW, Mips::SWP_MM), ReduceXWtoXWP,
267 OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
268 {RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP,
269 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
270 {RT_TwoInstr, OpCodes(Mips::SW16_MM, Mips::SWP_MM), ReduceXWtoXWP,
271 OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
272 {RT_TwoInstr, OpCodes(Mips::SW_MM, Mips::SWP_MM), ReduceXWtoXWP,
273 OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
274 {RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP,
275 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
276 {RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16,
277 OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)},
278 {RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16,
279 OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}};
287 if (MO.isReg() && ((MO.getReg() == Mips::SP)))
294 if (MO.
isReg() && Mips::GPRMM16RegClass.contains(MO.
getReg()))
301 if (MO.
isReg() && Mips::GPRMM16ZeroRegClass.contains(MO.
getReg()))
310 if (!
MI->getOperand(
Op).isImm())
312 Imm =
MI->getOperand(
Op).getImm();
318 int64_t Value2 =
Value >> 2;
319 if (((
Value & (int64_t)maskTrailingZeros<uint64_t>(2)) ==
Value) &&
320 ((Value2 >= 2 && Value2 <= 257) || (Value2 >= -258 && Value2 <= -3)))
329 int64_t Value2 =
Value >> Shift;
330 if (((
Value & (int64_t)maskTrailingZeros<uint64_t>(Shift)) ==
Value) &&
331 (Value2 >= LBound) && (Value2 < HBound))
341 if (!
GetImm(
MI, Entry.ImmField(), offset))
344 if (!
InRange(offset, Entry.Shift(), Entry.LBound(), Entry.HBound()))
352 const ReduceEntry &Entry) {
355 !(
MI->getOpcode() == Mips::LW ||
MI->getOpcode() == Mips::LW_MM ||
356 MI->getOpcode() == Mips::LW16_MM))
360 !(
MI->getOpcode() == Mips::SW ||
MI->getOpcode() == Mips::SW_MM ||
361 MI->getOpcode() == Mips::SW16_MM))
371 if (ReduceToLwp && (
MI->getOperand(0).getReg() ==
MI->getOperand(1).getReg()))
379 constexpr std::array<unsigned, 31>
Registers = {
380 {Mips::AT, Mips::V0, Mips::V1, Mips::A0, Mips::A1, Mips::A2, Mips::A3,
381 Mips::T0, Mips::T1, Mips::T2, Mips::T3, Mips::T4, Mips::T5, Mips::T6,
382 Mips::T7, Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5,
383 Mips::S6, Mips::S7, Mips::T8, Mips::T9, Mips::K0, Mips::K1, Mips::GP,
384 Mips::SP, Mips::FP, Mips::RA}};
386 for (uint8_t i = 0; i <
Registers.size() - 1; i++) {
400 int64_t Offset1, Offset2;
401 if (!
GetImm(MI1, 2, Offset1))
403 if (!
GetImm(MI2, 2, Offset2))
418 unsigned Opcode =
MI->getOpcode();
421 ReduceEntryVector::const_iterator Start = std::begin(ReduceTable);
422 ReduceEntryVector::const_iterator
End = std::end(ReduceTable);
424 std::pair<ReduceEntryVector::const_iterator,
425 ReduceEntryVector::const_iterator>
426 Range = std::equal_range(Start,
End, Opcode);
431 for (ReduceEntryVector::const_iterator Entry =
Range.first;
432 Entry !=
Range.second; ++Entry) {
433 ReduceEntryFunArgs
Arguments(&(*MII), *Entry, NextMII);
434 if (((*Entry).ReduceFunction)(&
Arguments))
440bool MicroMipsSizeReduce::ReduceXWtoXWSP(ReduceEntryFunArgs *
Arguments) {
448 if (!IsSP(
MI->getOperand(1)))
451 return ReplaceInstruction(
MI, Entry);
454bool MicroMipsSizeReduce::ReduceXWtoXWP(ReduceEntryFunArgs *
Arguments) {
468 bool ReduceToLwp = (MI1->
getOpcode() == Mips::LW) ||
487 if (!(ConsecutiveForward || ConsecutiveBackward))
490 NextMII = std::next(NextMII);
491 return ReplaceInstruction(MI1, Entry, MI2, ConsecutiveForward);
494bool MicroMipsSizeReduce::ReduceArithmeticInstructions(
505 return ReplaceInstruction(
MI, Entry);
508bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(
520 return ReplaceInstruction(
MI, Entry);
523bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(ReduceEntryFunArgs *
Arguments) {
535 if (!IsSP(
MI->getOperand(0)) || !IsSP(
MI->getOperand(1)))
538 return ReplaceInstruction(
MI, Entry);
541bool MicroMipsSizeReduce::ReduceLXUtoLXU16(ReduceEntryFunArgs *
Arguments) {
553 return ReplaceInstruction(
MI, Entry);
556bool MicroMipsSizeReduce::ReduceSXtoSX16(ReduceEntryFunArgs *
Arguments) {
568 return ReplaceInstruction(
MI, Entry);
575 if (Reg == Mips::ZERO || Reg == Mips::V0 || Reg == Mips::V1 ||
576 Reg == Mips::S0 || Reg == Mips::S1 || Reg == Mips::S2 ||
577 Reg == Mips::S3 || Reg == Mips::S4)
587 if (Reg == Mips::A0 || Reg == Mips::A1 || Reg == Mips::A2 ||
588 Reg == Mips::A3 || Reg == Mips::S5 || Reg == Mips::S6)
598 if ((R0 == Mips::A0 && R1 == Mips::S5) ||
599 (R0 == Mips::A0 && R1 == Mips::S6) ||
600 (R0 == Mips::A0 && R1 == Mips::A1) ||
601 (R0 == Mips::A0 && R1 == Mips::A2) ||
602 (R0 == Mips::A0 && R1 == Mips::A3) ||
603 (R0 == Mips::A1 && R1 == Mips::A2) ||
604 (R0 == Mips::A1 && R1 == Mips::A3) ||
605 (R0 == Mips::A2 && R1 == Mips::A3))
611bool MicroMipsSizeReduce::ReduceMoveToMovep(ReduceEntryFunArgs *
Arguments) {
642 bool ConsecutiveForward;
644 ConsecutiveForward =
true;
646 ConsecutiveForward =
false;
650 NextMII = std::next(NextMII);
651 return ReplaceInstruction(MI1, Entry, MI2, ConsecutiveForward);
654bool MicroMipsSizeReduce::ReduceXORtoXOR16(ReduceEntryFunArgs *
Arguments) {
664 if (!(
MI->getOperand(0).getReg() ==
MI->getOperand(2).getReg()) &&
665 !(
MI->getOperand(0).getReg() ==
MI->getOperand(1).getReg()))
668 return ReplaceInstruction(
MI, Entry);
678 for (; MII != E; MII = NextMII) {
679 NextMII = std::next(MII);
683 if (
MI->isBundle() ||
MI->isTransient())
694 const ReduceEntry &Entry,
696 bool ConsecutiveForward) {
698 enum OperandTransfer OpTransfer =
Entry.TransferOperands();
703 if (OpTransfer == OT_OperandsAll) {
704 MI->setDesc(MipsII->get(
Entry.NarrowOpc()));
712 switch (OpTransfer) {
714 MIB.
add(
MI->getOperand(2));
716 case OT_Operands02: {
717 MIB.
add(
MI->getOperand(0));
718 MIB.
add(
MI->getOperand(2));
721 case OT_OperandsXOR: {
722 if (
MI->getOperand(0).getReg() ==
MI->getOperand(2).getReg()) {
723 MIB.
add(
MI->getOperand(0));
724 MIB.
add(
MI->getOperand(1));
725 MIB.
add(
MI->getOperand(2));
727 MIB.
add(
MI->getOperand(0));
728 MIB.
add(
MI->getOperand(2));
729 MIB.
add(
MI->getOperand(1));
733 case OT_OperandsMovep:
735 case OT_OperandsSwp: {
736 if (ConsecutiveForward) {
737 MIB.
add(
MI->getOperand(0));
739 MIB.
add(
MI->getOperand(1));
740 if (OpTransfer == OT_OperandsMovep)
743 MIB.
add(
MI->getOperand(2));
746 MIB.
add(
MI->getOperand(0));
748 if (OpTransfer == OT_OperandsMovep)
749 MIB.
add(
MI->getOperand(1));
780 if (!Subtarget->inMicroMipsMode() || !Subtarget->hasMips32r2() ||
781 Subtarget->hasMips32r6())
784 MipsII =
static_cast<const MipsInstrInfo *
>(Subtarget->getInstrInfo());
796 return new MicroMipsSizeReduce();
AMDGPU Lower Kernel Arguments
static bool isMMSourceRegister(const MachineOperand &MO)
static bool IsMovepDestinationReg(unsigned Reg)
static bool CheckXWPInstr(MachineInstr *MI, bool ReduceToLwp, const ReduceEntry &Entry)
static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry)
static bool IsMovepDestinationRegPair(unsigned R0, unsigned R1)
#define MICROMIPS_SIZE_REDUCE_NAME
static bool InRange(int64_t Value, unsigned short Shift, int LBound, int HBound)
static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm)
static bool IsMovepSrcRegister(unsigned Reg)
static bool AddiuspImmValue(int64_t Value)
static bool ConsecutiveRegisters(unsigned Reg1, unsigned Reg2)
static bool ConsecutiveInstr(MachineInstr *MI1, MachineInstr *MI2)
static bool isMMThreeBitGPRegister(const MachineOperand &MO)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
SI Pre allocate WWM Registers
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Describe properties that are true of each instruction in the target description file.
instr_iterator instr_begin()
instr_iterator erase_instr(MachineInstr *I)
Remove an instruction from the instruction list and delete it.
Instructions::iterator instr_iterator
instr_iterator instr_end()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createMicroMipsSizeReducePass()
Returns an instance of the MicroMips size reduction pass.