LLVM 24.0.0git
MicroMipsSizeReduction.cpp
Go to the documentation of this file.
1//=== MicroMipsSizeReduction.cpp - MicroMips size reduction pass --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///\file
9/// This pass is used to reduce the size of instructions where applicable.
10///
11/// TODO: Implement microMIPS64 support.
12//===----------------------------------------------------------------------===//
13#include "Mips.h"
14#include "MipsInstrInfo.h"
15#include "MipsSubtarget.h"
16#include "llvm/ADT/Statistic.h"
20#include "llvm/IR/Analysis.h"
21#include "llvm/Pass.h"
22#include "llvm/Support/Debug.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "mips-micromips-reduce-size"
27#define MICROMIPS_SIZE_REDUCE_NAME "MicroMips instruction size reduce pass"
28
29STATISTIC(NumReduced, "Number of instructions reduced (32-bit to 16-bit ones, "
30 "or two instructions into one");
31
32namespace {
33
34/// Order of operands to transfer
35// TODO: Will be extended when additional optimizations are added
36enum OperandTransfer {
37 OT_NA, ///< Not applicable
38 OT_OperandsAll, ///< Transfer all operands
39 OT_Operands02, ///< Transfer operands 0 and 2
40 OT_Operand2, ///< Transfer just operand 2
41 OT_OperandsXOR, ///< Transfer operands for XOR16
42 OT_OperandsLwp, ///< Transfer operands for LWP
43 OT_OperandsSwp, ///< Transfer operands for SWP
44 OT_OperandsMovep, ///< Transfer operands for MOVEP
45};
46
47/// Reduction type
48// TODO: Will be extended when additional optimizations are added
49enum ReduceType {
50 RT_TwoInstr, ///< Reduce two instructions into one instruction
51 RT_OneInstr ///< Reduce one instruction into a smaller instruction
52};
53
54// Information about immediate field restrictions
55struct ImmField {
56 ImmField() : ImmFieldOperand(-1), Shift(0), LBound(0), HBound(0) {}
57 ImmField(uint8_t Shift, int16_t LBound, int16_t HBound,
58 int8_t ImmFieldOperand)
59 : ImmFieldOperand(ImmFieldOperand), Shift(Shift), LBound(LBound),
60 HBound(HBound) {}
61 int8_t ImmFieldOperand; // Immediate operand, -1 if it does not exist
62 uint8_t Shift; // Shift value
63 int16_t LBound; // Low bound of the immediate operand
64 int16_t HBound; // High bound of the immediate operand
65};
66
67/// Information about operands
68// TODO: Will be extended when additional optimizations are added
69struct OpInfo {
70 OpInfo(enum OperandTransfer TransferOperands)
71 : TransferOperands(TransferOperands) {}
72 OpInfo() : TransferOperands(OT_NA) {}
73
74 enum OperandTransfer
75 TransferOperands; ///< Operands to transfer to the new instruction
76};
77
78// Information about opcodes
79struct OpCodes {
80 OpCodes(unsigned WideOpc, unsigned NarrowOpc)
81 : WideOpc(WideOpc), NarrowOpc(NarrowOpc) {}
82
83 unsigned WideOpc; ///< Wide opcode
84 unsigned NarrowOpc; ///< Narrow opcode
85};
86
87typedef struct ReduceEntryFunArgs ReduceEntryFunArgs;
88
89/// ReduceTable - A static table with information on mapping from wide
90/// opcodes to narrow
91struct ReduceEntry {
92
93 enum ReduceType eRType; ///< Reduction type
94 bool (*ReduceFunction)(
95 ReduceEntryFunArgs *Arguments); ///< Pointer to reduce function
96 struct OpCodes Ops; ///< All relevant OpCodes
97 struct OpInfo OpInf; ///< Characteristics of operands
98 struct ImmField Imm; ///< Characteristics of immediate field
99
100 ReduceEntry(enum ReduceType RType, struct OpCodes Op,
101 bool (*F)(ReduceEntryFunArgs *Arguments), struct OpInfo OpInf,
102 struct ImmField Imm)
103 : eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {}
104
105 unsigned NarrowOpc() const { return Ops.NarrowOpc; }
106 unsigned WideOpc() const { return Ops.WideOpc; }
107 int16_t LBound() const { return Imm.LBound; }
108 int16_t HBound() const { return Imm.HBound; }
109 uint8_t Shift() const { return Imm.Shift; }
110 int8_t ImmField() const { return Imm.ImmFieldOperand; }
111 enum OperandTransfer TransferOperands() const {
112 return OpInf.TransferOperands;
113 }
114 enum ReduceType RType() const { return eRType; }
115
116 // operator used by std::equal_range
117 bool operator<(const unsigned int r) const { return (WideOpc() < r); }
118
119 // operator used by std::equal_range
120 friend bool operator<(const unsigned int r, const struct ReduceEntry &re) {
121 return (r < re.WideOpc());
122 }
123};
124
125// Function arguments for ReduceFunction
126struct ReduceEntryFunArgs {
127 MachineInstr *MI; // Instruction
128 const ReduceEntry &Entry; // Entry field
129 const MipsInstrInfo *MipsII;
131 &NextMII; // Iterator to next instruction in block
132
133 ReduceEntryFunArgs(MachineInstr *argMI, const ReduceEntry &argEntry,
134 const MipsInstrInfo *argMipsII,
136 : MI(argMI), Entry(argEntry), MipsII(argMipsII), NextMII(argNextMII) {}
137};
138
139typedef llvm::SmallVector<ReduceEntry, 32> ReduceEntryVector;
140
141class MicroMipsSizeReduceLegacy : public MachineFunctionPass {
142public:
143 static char ID;
144 MicroMipsSizeReduceLegacy();
145
146 bool runOnMachineFunction(MachineFunction &MF) override;
147
148 llvm::StringRef getPassName() const override {
149 return "microMIPS instruction size reduction pass";
150 }
151
152 void getAnalysisUsage(AnalysisUsage &AU) const override {
153 AU.setPreservesCFG();
155 }
156};
157
158char MicroMipsSizeReduceLegacy::ID = 0;
159
160} // namespace
161
162INITIALIZE_PASS(MicroMipsSizeReduceLegacy, DEBUG_TYPE,
163 MICROMIPS_SIZE_REDUCE_NAME, false, false)
164
165// Returns true if the machine operand MO is register SP.
166static bool IsSP(const MachineOperand &MO) {
167 if (MO.isReg() && ((MO.getReg() == Mips::SP)))
168 return true;
169 return false;
170}
171
172// Returns true if the machine operand MO is register $16, $17, or $2-$7.
174 if (MO.isReg() && Mips::GPRMM16RegClass.contains(MO.getReg()))
175 return true;
176 return false;
177}
178
179// Returns true if the machine operand MO is register $0, $17, or $2-$7.
180static bool isMMSourceRegister(const MachineOperand &MO) {
181 if (MO.isReg() && Mips::GPRMM16ZeroRegClass.contains(MO.getReg()))
182 return true;
183 return false;
184}
185
186// Returns true if the operand Op is an immediate value
187// and writes the immediate value into variable Imm.
188static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm) {
189
190 if (!MI->getOperand(Op).isImm())
191 return false;
192 Imm = MI->getOperand(Op).getImm();
193 return true;
194}
195
196// Returns true if the value is a valid immediate for ADDIUSP.
197static bool AddiuspImmValue(int64_t Value) {
198 int64_t Value2 = Value >> 2;
199 if (((Value & (int64_t)maskTrailingZeros<uint64_t>(2)) == Value) &&
200 ((Value2 >= 2 && Value2 <= 257) || (Value2 >= -258 && Value2 <= -3)))
201 return true;
202 return false;
203}
204
205// Returns true if the variable Value has the number of least-significant zero
206// bits equal to Shift and if the shifted value is between the bounds.
207static bool InRange(int64_t Value, unsigned short Shift, int LBound,
208 int HBound) {
209 int64_t Value2 = Value >> Shift;
210 if (((Value & (int64_t)maskTrailingZeros<uint64_t>(Shift)) == Value) &&
211 (Value2 >= LBound) && (Value2 < HBound))
212 return true;
213 return false;
214}
215
216// Returns true if immediate operand is in range.
217static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) {
218
219 int64_t offset;
220
221 if (!GetImm(MI, Entry.ImmField(), offset))
222 return false;
223
224 if (!InRange(offset, Entry.Shift(), Entry.LBound(), Entry.HBound()))
225 return false;
226
227 return true;
228}
229
230// Returns true if MI can be reduced to lwp/swp instruction
231static bool CheckXWPInstr(MachineInstr *MI, bool ReduceToLwp,
232 const ReduceEntry &Entry) {
233
234 if (ReduceToLwp &&
235 !(MI->getOpcode() == Mips::LW || MI->getOpcode() == Mips::LW_MM ||
236 MI->getOpcode() == Mips::LW16_MM))
237 return false;
238
239 if (!ReduceToLwp &&
240 !(MI->getOpcode() == Mips::SW || MI->getOpcode() == Mips::SW_MM ||
241 MI->getOpcode() == Mips::SW16_MM))
242 return false;
243
244 Register reg = MI->getOperand(0).getReg();
245 if (reg == Mips::RA)
246 return false;
247
248 if (!ImmInRange(MI, Entry))
249 return false;
250
251 if (ReduceToLwp && (MI->getOperand(0).getReg() == MI->getOperand(1).getReg()))
252 return false;
253
254 return true;
255}
256
257// Returns true if the registers Reg1 and Reg2 are consecutive
258static bool ConsecutiveRegisters(unsigned Reg1, unsigned Reg2) {
259 constexpr std::array<unsigned, 31> Registers = {
260 {Mips::R1, Mips::R2, Mips::R3, Mips::R4, Mips::R5, Mips::R6,
261 Mips::R7, Mips::R8, Mips::R9, Mips::R10, Mips::R11, Mips::R12,
262 Mips::R13, Mips::R14, Mips::R15, Mips::R16, Mips::R17, Mips::R18,
263 Mips::R19, Mips::R20, Mips::R21, Mips::R22, Mips::R23, Mips::R24,
264 Mips::R25, Mips::R26, Mips::R27, Mips::R28, Mips::R29, Mips::R30,
265 Mips::R31}};
266
267 for (uint8_t i = 0; i < Registers.size() - 1; i++) {
268 if (Registers[i] == Reg1) {
269 if (Registers[i + 1] == Reg2)
270 return true;
271 else
272 return false;
273 }
274 }
275 return false;
276}
277
278// Returns true if registers and offsets are consecutive
280
281 int64_t Offset1, Offset2;
282 if (!GetImm(MI1, 2, Offset1))
283 return false;
284 if (!GetImm(MI2, 2, Offset2))
285 return false;
286
287 Register Reg1 = MI1->getOperand(0).getReg();
288 Register Reg2 = MI2->getOperand(0).getReg();
289
290 return ((Offset1 == (Offset2 - 4)) && (ConsecutiveRegisters(Reg1, Reg2)));
291}
292
293MicroMipsSizeReduceLegacy::MicroMipsSizeReduceLegacy()
294 : MachineFunctionPass(ID) {}
295
296// Changes opcode of an instruction, replaces an instruction with a
297// new one, or replaces two instructions with a new instruction
298// depending on their order i.e. if these are consecutive forward
299// or consecutive backward
300static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry,
301 const MipsInstrInfo *MipsII,
302 MachineInstr *MI2 = nullptr,
303 bool ConsecutiveForward = true) {
304
305 enum OperandTransfer OpTransfer = Entry.TransferOperands();
306
307 LLVM_DEBUG(dbgs() << "Converting 32-bit: " << *MI);
308 ++NumReduced;
309
310 if (OpTransfer == OT_OperandsAll) {
311 MI->setDesc(MipsII->get(Entry.NarrowOpc()));
312 LLVM_DEBUG(dbgs() << " to 16-bit: " << *MI);
313 return true;
314 } else {
315 MachineBasicBlock &MBB = *MI->getParent();
316 const MCInstrDesc &NewMCID = MipsII->get(Entry.NarrowOpc());
317 DebugLoc dl = MI->getDebugLoc();
318 MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, NewMCID);
319 switch (OpTransfer) {
320 case OT_Operand2:
321 MIB.add(MI->getOperand(2));
322 break;
323 case OT_Operands02: {
324 MIB.add(MI->getOperand(0));
325 MIB.add(MI->getOperand(2));
326 break;
327 }
328 case OT_OperandsXOR: {
329 if (MI->getOperand(0).getReg() == MI->getOperand(2).getReg()) {
330 MIB.add(MI->getOperand(0));
331 MIB.add(MI->getOperand(1));
332 MIB.add(MI->getOperand(2));
333 } else {
334 MIB.add(MI->getOperand(0));
335 MIB.add(MI->getOperand(2));
336 MIB.add(MI->getOperand(1));
337 }
338 break;
339 }
340 case OT_OperandsMovep:
341 case OT_OperandsLwp:
342 case OT_OperandsSwp: {
343 if (ConsecutiveForward) {
344 MIB.add(MI->getOperand(0));
345 MIB.add(MI2->getOperand(0));
346 MIB.add(MI->getOperand(1));
347 if (OpTransfer == OT_OperandsMovep)
348 MIB.add(MI2->getOperand(1));
349 else
350 MIB.add(MI->getOperand(2));
351 } else { // consecutive backward
352 MIB.add(MI2->getOperand(0));
353 MIB.add(MI->getOperand(0));
354 MIB.add(MI2->getOperand(1));
355 if (OpTransfer == OT_OperandsMovep)
356 MIB.add(MI->getOperand(1));
357 else
358 MIB.add(MI2->getOperand(2));
359 }
360
361 LLVM_DEBUG(dbgs() << "and converting 32-bit: " << *MI2
362 << " to: " << *MIB);
363
364 MBB.erase_instr(MI);
365 MBB.erase_instr(MI2);
366 return true;
367 }
368 default:
369 llvm_unreachable("Unknown operand transfer!");
370 }
371
372 // Transfer MI flags.
373 MIB.setMIFlags(MI->getFlags());
374
375 LLVM_DEBUG(dbgs() << " to 16-bit: " << *MIB);
376 MBB.erase_instr(MI);
377 return true;
378 }
379 return false;
380}
381
382// Attempts to reduce LW/SW instruction into LWSP/SWSP,
383// returns true on success.
384static bool ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments) {
385
387 const ReduceEntry &Entry = Arguments->Entry;
388
389 if (!ImmInRange(MI, Entry))
390 return false;
391
392 if (!IsSP(MI->getOperand(1)))
393 return false;
394
395 return ReplaceInstruction(MI, Entry, Arguments->MipsII);
396}
397
398// Attempts to reduce two LW/SW instructions into LWP/SWP instruction,
399// returns true on success.
400static bool ReduceXWtoXWP(ReduceEntryFunArgs *Arguments) {
401
402 const ReduceEntry &Entry = Arguments->Entry;
405 Arguments->MI->getParent()->instr_end();
406
407 if (NextMII == E)
408 return false;
409
410 MachineInstr *MI1 = Arguments->MI;
411 MachineInstr *MI2 = &*NextMII;
412
413 // ReduceToLwp = true/false - reduce to LWP/SWP instruction
414 bool ReduceToLwp = (MI1->getOpcode() == Mips::LW) ||
415 (MI1->getOpcode() == Mips::LW_MM) ||
416 (MI1->getOpcode() == Mips::LW16_MM);
417
418 if (!CheckXWPInstr(MI1, ReduceToLwp, Entry))
419 return false;
420
421 if (!CheckXWPInstr(MI2, ReduceToLwp, Entry))
422 return false;
423
424 Register Reg1 = MI1->getOperand(1).getReg();
425 Register Reg2 = MI2->getOperand(1).getReg();
426
427 if (Reg1 != Reg2)
428 return false;
429
430 bool ConsecutiveForward = ConsecutiveInstr(MI1, MI2);
431 bool ConsecutiveBackward = ConsecutiveInstr(MI2, MI1);
432
433 if (!(ConsecutiveForward || ConsecutiveBackward))
434 return false;
435
436 NextMII = std::next(NextMII);
437 return ReplaceInstruction(MI1, Entry, Arguments->MipsII, MI2,
438 ConsecutiveForward);
439}
440
441// Attempts to reduce arithmetic instructions, returns true on success.
442static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *Arguments) {
443
445 const ReduceEntry &Entry = Arguments->Entry;
446
447 if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
448 !isMMThreeBitGPRegister(MI->getOperand(1)) ||
449 !isMMThreeBitGPRegister(MI->getOperand(2)))
450 return false;
451
452 return ReplaceInstruction(MI, Entry, Arguments->MipsII);
453}
454
455// Attempts to reduce ADDIU into ADDIUR1SP instruction,
456// returns true on success.
457static bool ReduceADDIUToADDIUR1SP(ReduceEntryFunArgs *Arguments) {
458
460 const ReduceEntry &Entry = Arguments->Entry;
461
462 if (!ImmInRange(MI, Entry))
463 return false;
464
465 if (!isMMThreeBitGPRegister(MI->getOperand(0)) || !IsSP(MI->getOperand(1)))
466 return false;
467
468 return ReplaceInstruction(MI, Entry, Arguments->MipsII);
469}
470
471// Attempts to reduce ADDIU into ADDIUSP instruction,
472// returns true on success.
473static bool ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments) {
474
476 const ReduceEntry &Entry = Arguments->Entry;
477
478 int64_t ImmValue;
479 if (!GetImm(MI, Entry.ImmField(), ImmValue))
480 return false;
481
482 if (!AddiuspImmValue(ImmValue))
483 return false;
484
485 if (!IsSP(MI->getOperand(0)) || !IsSP(MI->getOperand(1)))
486 return false;
487
488 return ReplaceInstruction(MI, Entry, Arguments->MipsII);
489}
490
491// Attempts to reduce LBU/LHU instruction into LBU16/LHU16,
492// returns true on success.
493static bool ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments) {
494
496 const ReduceEntry &Entry = Arguments->Entry;
497
498 if (!ImmInRange(MI, Entry))
499 return false;
500
501 if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
502 !isMMThreeBitGPRegister(MI->getOperand(1)))
503 return false;
504
505 return ReplaceInstruction(MI, Entry, Arguments->MipsII);
506}
507
508// Attempts to reduce SB/SH instruction into SB16/SH16,
509// returns true on success.
510static bool ReduceSXtoSX16(ReduceEntryFunArgs *Arguments) {
511
513 const ReduceEntry &Entry = Arguments->Entry;
514
515 if (!ImmInRange(MI, Entry))
516 return false;
517
518 if (!isMMSourceRegister(MI->getOperand(0)) ||
519 !isMMThreeBitGPRegister(MI->getOperand(1)))
520 return false;
521
522 return ReplaceInstruction(MI, Entry, Arguments->MipsII);
523}
524
525// Returns true if Reg can be a source register
526// of MOVEP instruction
527static bool IsMovepSrcRegister(unsigned Reg) {
528
529 if (Reg == Mips::R0 || Reg == Mips::R2 || Reg == Mips::R3 ||
530 Reg == Mips::R16 || Reg == Mips::R17 || Reg == Mips::R18 ||
531 Reg == Mips::R19 || Reg == Mips::R20)
532 return true;
533
534 return false;
535}
536
537// Returns true if Reg can be a destination register
538// of MOVEP instruction
539static bool IsMovepDestinationReg(unsigned Reg) {
540
541 if (Reg == Mips::R4 || Reg == Mips::R5 || Reg == Mips::R6 ||
542 Reg == Mips::R7 || Reg == Mips::R21 || Reg == Mips::R22)
543 return true;
544
545 return false;
546}
547
548// Returns true if the registers can be a pair of destination
549// registers in MOVEP instruction
550static bool IsMovepDestinationRegPair(unsigned R0, unsigned R1) {
551
552 if ((R0 == Mips::R4 && R1 == Mips::R21) ||
553 (R0 == Mips::R4 && R1 == Mips::R22) ||
554 (R0 == Mips::R4 && R1 == Mips::R5) ||
555 (R0 == Mips::R4 && R1 == Mips::R6) ||
556 (R0 == Mips::R4 && R1 == Mips::R7) ||
557 (R0 == Mips::R5 && R1 == Mips::R6) ||
558 (R0 == Mips::R5 && R1 == Mips::R7) || (R0 == Mips::R6 && R1 == Mips::R7))
559 return true;
560
561 return false;
562}
563
564// Attempts to reduce two MOVE instructions into MOVEP instruction,
565// returns true on success.
566static bool ReduceMoveToMovep(ReduceEntryFunArgs *Arguments) {
567
568 const ReduceEntry &Entry = Arguments->Entry;
571 Arguments->MI->getParent()->instr_end();
572
573 if (NextMII == E)
574 return false;
575
576 MachineInstr *MI1 = Arguments->MI;
577 MachineInstr *MI2 = &*NextMII;
578
579 Register RegDstMI1 = MI1->getOperand(0).getReg();
580 Register RegSrcMI1 = MI1->getOperand(1).getReg();
581
582 if (!IsMovepSrcRegister(RegSrcMI1))
583 return false;
584
585 if (!IsMovepDestinationReg(RegDstMI1))
586 return false;
587
588 if (MI2->getOpcode() != Entry.WideOpc())
589 return false;
590
591 Register RegDstMI2 = MI2->getOperand(0).getReg();
592 Register RegSrcMI2 = MI2->getOperand(1).getReg();
593
594 if (!IsMovepSrcRegister(RegSrcMI2))
595 return false;
596
597 bool ConsecutiveForward;
598 if (IsMovepDestinationRegPair(RegDstMI1, RegDstMI2)) {
599 ConsecutiveForward = true;
600 } else if (IsMovepDestinationRegPair(RegDstMI2, RegDstMI1)) {
601 ConsecutiveForward = false;
602 } else
603 return false;
604
605 NextMII = std::next(NextMII);
606 return ReplaceInstruction(MI1, Entry, Arguments->MipsII, MI2,
607 ConsecutiveForward);
608}
609
610// Attempts to reduce XOR into XOR16 instruction,
611// returns true on success.
612static bool ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments) {
613
615 const ReduceEntry &Entry = Arguments->Entry;
616
617 if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
618 !isMMThreeBitGPRegister(MI->getOperand(1)) ||
619 !isMMThreeBitGPRegister(MI->getOperand(2)))
620 return false;
621
622 if (!(MI->getOperand(0).getReg() == MI->getOperand(2).getReg()) &&
623 !(MI->getOperand(0).getReg() == MI->getOperand(1).getReg()))
624 return false;
625
626 return ReplaceInstruction(MI, Entry, Arguments->MipsII);
627}
628
629// Table with transformation rules for each instruction.
630// This table must be sorted by WideOpc as a main criterion and
631// ReduceType as a sub-criterion (when wide opcodes are the same).
632static ReduceEntryVector ReduceTable = {
633 // ReduceType, OpCodes, ReduceFunction,
634 // OpInfo(TransferOperands),
635 // ImmField(Shift, LBound, HBound, ImmFieldPosition)
636 {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUR1SP_MM),
637 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
638 {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUSP_MM), ReduceADDIUToADDIUSP,
639 OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)},
640 {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUR1SP_MM),
641 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
642 {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUSP_MM),
643 ReduceADDIUToADDIUSP, OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)},
644 {RT_OneInstr, OpCodes(Mips::ADDu, Mips::ADDU16_MM),
645 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
646 ImmField(0, 0, 0, -1)},
647 {RT_OneInstr, OpCodes(Mips::ADDu_MM, Mips::ADDU16_MM),
648 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
649 ImmField(0, 0, 0, -1)},
650 {RT_OneInstr, OpCodes(Mips::LBu, Mips::LBU16_MM), ReduceLXUtoLXU16,
651 OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)},
652 {RT_OneInstr, OpCodes(Mips::LBu_MM, Mips::LBU16_MM), ReduceLXUtoLXU16,
653 OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)},
654 {RT_OneInstr, OpCodes(Mips::LEA_ADDiu, Mips::ADDIUR1SP_MM),
655 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
656 {RT_OneInstr, OpCodes(Mips::LEA_ADDiu_MM, Mips::ADDIUR1SP_MM),
657 ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)},
658 {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16,
659 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
660 {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16,
661 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
662 {RT_TwoInstr, OpCodes(Mips::LW, Mips::LWP_MM), ReduceXWtoXWP,
663 OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
664 {RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP,
665 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
666 {RT_TwoInstr, OpCodes(Mips::LW16_MM, Mips::LWP_MM), ReduceXWtoXWP,
667 OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
668 {RT_TwoInstr, OpCodes(Mips::LW_MM, Mips::LWP_MM), ReduceXWtoXWP,
669 OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
670 {RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP,
671 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
672 {RT_TwoInstr, OpCodes(Mips::MOVE16_MM, Mips::MOVEP_MM), ReduceMoveToMovep,
673 OpInfo(OT_OperandsMovep), ImmField(0, 0, 0, -1)},
674 {RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16,
675 OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)},
676 {RT_OneInstr, OpCodes(Mips::SB_MM, Mips::SB16_MM), ReduceSXtoSX16,
677 OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)},
678 {RT_OneInstr, OpCodes(Mips::SH, Mips::SH16_MM), ReduceSXtoSX16,
679 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
680 {RT_OneInstr, OpCodes(Mips::SH_MM, Mips::SH16_MM), ReduceSXtoSX16,
681 OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
682 {RT_OneInstr, OpCodes(Mips::SUBu, Mips::SUBU16_MM),
683 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
684 ImmField(0, 0, 0, -1)},
685 {RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM),
686 ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
687 ImmField(0, 0, 0, -1)},
688 {RT_TwoInstr, OpCodes(Mips::SW, Mips::SWP_MM), ReduceXWtoXWP,
689 OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
690 {RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP,
691 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
692 {RT_TwoInstr, OpCodes(Mips::SW16_MM, Mips::SWP_MM), ReduceXWtoXWP,
693 OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
694 {RT_TwoInstr, OpCodes(Mips::SW_MM, Mips::SWP_MM), ReduceXWtoXWP,
695 OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
696 {RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP,
697 OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
698 {RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16,
699 OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)},
700 {RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16,
701 OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}};
702
703// Attempts to reduce MI, returns true on success.
706 const MipsInstrInfo *MipsII) {
707
708 MachineInstr *MI = &*MII;
709 unsigned Opcode = MI->getOpcode();
710
711 // Search the table.
712 ReduceEntryVector::const_iterator Start = std::begin(ReduceTable);
713 ReduceEntryVector::const_iterator End = std::end(ReduceTable);
714
715 std::pair<ReduceEntryVector::const_iterator,
716 ReduceEntryVector::const_iterator>
717 Range = std::equal_range(Start, End, Opcode);
718
719 if (Range.first == Range.second)
720 return false;
721
722 for (ReduceEntryVector::const_iterator Entry = Range.first;
723 Entry != Range.second; ++Entry) {
724 ReduceEntryFunArgs Arguments(&(*MII), *Entry, MipsII, NextMII);
725 if (((*Entry).ReduceFunction)(&Arguments))
726 return true;
727 }
728 return false;
729}
730
731/// Reduces width of instructions in the specified basic block.
733 bool Modified = false;
734 MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
735 E = MBB.instr_end();
737
738 // Iterate through the instructions in the basic block
739 for (; MII != E; MII = NextMII) {
740 NextMII = std::next(MII);
741 MachineInstr *MI = &*MII;
742
743 // Don't reduce bundled instructions or pseudo operations
744 if (MI->isBundle() || MI->isTransient())
745 continue;
746
747 // Try to reduce 32-bit instruction into 16-bit instruction
748 Modified |= ReduceMI(MII, NextMII, MipsII);
749 }
750
751 return Modified;
752}
753
756
757 // TODO: Add support for the subtarget microMIPS32R6.
758 if (!Subtarget->inMicroMipsMode() || !Subtarget->hasMips32r2() ||
759 Subtarget->hasMips32r6())
760 return false;
761
762 const MipsInstrInfo *MipsII = Subtarget->getInstrInfo();
763
764 bool Modified = false;
765 MachineFunction::iterator I = MF.begin(), E = MF.end();
766
767 for (; I != E; ++I)
769 return Modified;
770}
771
772/// Returns an instance of the MicroMips size reduction pass.
774 return new MicroMipsSizeReduceLegacy();
775}
776
777bool MicroMipsSizeReduceLegacy::runOnMachineFunction(MachineFunction &MF) {
778 return runMipsSizeReduce(MF);
779}
780
781PreservedAnalyses
const AArch64Subtarget & Subtarget
aarch64 promote const
uint64_t Imm
AMDGPU Lower Kernel Arguments
AMDGPU Reserve WWM Registers
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
static bool ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments)
static bool ReduceMBB(MachineBasicBlock &MBB, const MipsInstrInfo *MipsII)
Reduces width of instructions in the specified basic block.
static bool runMipsSizeReduce(MachineFunction &MF)
static bool ReduceMoveToMovep(ReduceEntryFunArgs *Arguments)
static bool ReduceADDIUToADDIUR1SP(ReduceEntryFunArgs *Arguments)
static bool isMMSourceRegister(const MachineOperand &MO)
static bool IsMovepDestinationReg(unsigned Reg)
static bool ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments)
static bool CheckXWPInstr(MachineInstr *MI, bool ReduceToLwp, const ReduceEntry &Entry)
static ReduceEntryVector ReduceTable
static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry)
static bool IsMovepDestinationRegPair(unsigned R0, unsigned R1)
static bool ReduceSXtoSX16(ReduceEntryFunArgs *Arguments)
static bool ReduceXWtoXWP(ReduceEntryFunArgs *Arguments)
static bool ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments)
static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *Arguments)
#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 ReduceMI(const MachineBasicBlock::instr_iterator &MII, MachineBasicBlock::instr_iterator &NextMII, const MipsInstrInfo *MipsII)
static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry, const MipsInstrInfo *MipsII, MachineInstr *MI2=nullptr, bool ConsecutiveForward=true)
static bool isMMThreeBitGPRegister(const MachineOperand &MO)
static bool ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:280
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
A debug info location.
Definition DebugLoc.h:126
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
Describe properties that are true of each instruction in the target description file.
Instructions::iterator instr_iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
BasicBlockListType::iterator iterator
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.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
Definition Value.h:75
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MipsII - This namespace holds all of the target specific flags that instruction info tracks.
constexpr MCPhysReg SP
constexpr MCPhysReg RA
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
Definition MathExtras.h:95
DWARFExpression::Operation Op
FunctionPass * createMicroMipsSizeReduceLegacyPass()
Returns an instance of the MicroMips size reduction pass.
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320