/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //=== MicroMipsSizeReduction.cpp - MicroMips size reduction pass --------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | ///\file |
10 | | /// This pass is used to reduce the size of instructions where applicable. |
11 | | /// |
12 | | /// TODO: Implement microMIPS64 support. |
13 | | /// TODO: Implement support for reducing into lwp/swp instruction. |
14 | | //===----------------------------------------------------------------------===// |
15 | | #include "Mips.h" |
16 | | #include "MipsInstrInfo.h" |
17 | | #include "MipsSubtarget.h" |
18 | | #include "llvm/ADT/Statistic.h" |
19 | | #include "llvm/CodeGen/MachineFunctionPass.h" |
20 | | #include "llvm/Support/Debug.h" |
21 | | |
22 | | using namespace llvm; |
23 | | |
24 | | #define DEBUG_TYPE "micromips-reduce-size" |
25 | | |
26 | | STATISTIC(NumReduced, "Number of 32-bit instructions reduced to 16-bit ones"); |
27 | | |
28 | | namespace { |
29 | | |
30 | | /// Order of operands to transfer |
31 | | // TODO: Will be extended when additional optimizations are added |
32 | | enum OperandTransfer { |
33 | | OT_NA, ///< Not applicable |
34 | | OT_OperandsAll, ///< Transfer all operands |
35 | | OT_Operands02, ///< Transfer operands 0 and 2 |
36 | | OT_Operand2, ///< Transfer just operand 2 |
37 | | OT_OperandsXOR, ///< Transfer operands for XOR16 |
38 | | }; |
39 | | |
40 | | /// Reduction type |
41 | | // TODO: Will be extended when additional optimizations are added |
42 | | enum ReduceType { |
43 | | RT_OneInstr ///< Reduce one instruction into a smaller instruction |
44 | | }; |
45 | | |
46 | | // Information about immediate field restrictions |
47 | | struct ImmField { |
48 | 0 | ImmField() : ImmFieldOperand(-1), Shift(0), LBound(0), HBound(0) {} |
49 | | ImmField(uint8_t Shift, int16_t LBound, int16_t HBound, |
50 | | int8_t ImmFieldOperand) |
51 | | : ImmFieldOperand(ImmFieldOperand), Shift(Shift), LBound(LBound), |
52 | 2.08M | HBound(HBound) {} |
53 | | int8_t ImmFieldOperand; // Immediate operand, -1 if it does not exist |
54 | | uint8_t Shift; // Shift value |
55 | | int16_t LBound; // Low bound of the immediate operand |
56 | | int16_t HBound; // High bound of the immediate operand |
57 | | }; |
58 | | |
59 | | /// Information about operands |
60 | | // TODO: Will be extended when additional optimizations are added |
61 | | struct OpInfo { |
62 | | OpInfo(enum OperandTransfer TransferOperands) |
63 | 2.08M | : TransferOperands(TransferOperands) {} |
64 | 0 | OpInfo() : TransferOperands(OT_NA) {} |
65 | | |
66 | | enum OperandTransfer |
67 | | TransferOperands; ///< Operands to transfer to the new instruction |
68 | | }; |
69 | | |
70 | | // Information about opcodes |
71 | | struct OpCodes { |
72 | | OpCodes(unsigned WideOpc, unsigned NarrowOpc) |
73 | 2.08M | : WideOpc(WideOpc), NarrowOpc(NarrowOpc) {} |
74 | | |
75 | | unsigned WideOpc; ///< Wide opcode |
76 | | unsigned NarrowOpc; ///< Narrow opcode |
77 | | }; |
78 | | |
79 | | /// ReduceTable - A static table with information on mapping from wide |
80 | | /// opcodes to narrow |
81 | | struct ReduceEntry { |
82 | | |
83 | | enum ReduceType eRType; ///< Reduction type |
84 | | bool (*ReduceFunction)( |
85 | | MachineInstr *MI, |
86 | | const ReduceEntry &Entry); ///< Pointer to reduce function |
87 | | struct OpCodes Ops; ///< All relevant OpCodes |
88 | | struct OpInfo OpInf; ///< Characteristics of operands |
89 | | struct ImmField Imm; ///< Characteristics of immediate field |
90 | | |
91 | | ReduceEntry(enum ReduceType RType, struct OpCodes Op, |
92 | | bool (*F)(MachineInstr *MI, const ReduceEntry &Entry), |
93 | | struct OpInfo OpInf, struct ImmField Imm) |
94 | 2.08M | : eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {} |
95 | | |
96 | 337 | unsigned NarrowOpc() const { return Ops.NarrowOpc; } |
97 | 15.8k | unsigned WideOpc() const { return Ops.WideOpc; } |
98 | 365 | int16_t LBound() const { return Imm.LBound; } |
99 | 365 | int16_t HBound() const { return Imm.HBound; } |
100 | 365 | uint8_t Shift() const { return Imm.Shift; } |
101 | 537 | int8_t ImmField() const { return Imm.ImmFieldOperand; } |
102 | 337 | enum OperandTransfer TransferOperands() const { |
103 | 337 | return OpInf.TransferOperands; |
104 | 337 | } |
105 | 0 | enum ReduceType RType() const { return eRType; } |
106 | | |
107 | | // operator used by std::equal_range |
108 | 9.85k | bool operator<(const unsigned int r) const { return (WideOpc() < r); } |
109 | | |
110 | | // operator used by std::equal_range |
111 | 6.03k | friend bool operator<(const unsigned int r, const struct ReduceEntry &re) { |
112 | 6.03k | return (r < re.WideOpc()); |
113 | 6.03k | } |
114 | | }; |
115 | | |
116 | | class MicroMipsSizeReduce : public MachineFunctionPass { |
117 | | public: |
118 | | static char ID; |
119 | | MicroMipsSizeReduce(); |
120 | | |
121 | | static const MipsInstrInfo *MipsII; |
122 | | const MipsSubtarget *Subtarget; |
123 | | |
124 | | bool runOnMachineFunction(MachineFunction &MF) override; |
125 | | |
126 | 1.70k | llvm::StringRef getPassName() const override { |
127 | 1.70k | return "microMIPS instruction size reduction pass"; |
128 | 1.70k | } |
129 | | |
130 | | private: |
131 | | /// Reduces width of instructions in the specified basic block. |
132 | | bool ReduceMBB(MachineBasicBlock &MBB); |
133 | | |
134 | | /// Attempts to reduce MI, returns true on success. |
135 | | bool ReduceMI(const MachineBasicBlock::instr_iterator &MII); |
136 | | |
137 | | // Attempts to reduce LW/SW instruction into LWSP/SWSP, |
138 | | // returns true on success. |
139 | | static bool ReduceXWtoXWSP(MachineInstr *MI, const ReduceEntry &Entry); |
140 | | |
141 | | // Attempts to reduce LBU/LHU instruction into LBU16/LHU16, |
142 | | // returns true on success. |
143 | | static bool ReduceLXUtoLXU16(MachineInstr *MI, const ReduceEntry &Entry); |
144 | | |
145 | | // Attempts to reduce SB/SH instruction into SB16/SH16, |
146 | | // returns true on success. |
147 | | static bool ReduceSXtoSX16(MachineInstr *MI, const ReduceEntry &Entry); |
148 | | |
149 | | // Attempts to reduce arithmetic instructions, returns true on success. |
150 | | static bool ReduceArithmeticInstructions(MachineInstr *MI, |
151 | | const ReduceEntry &Entry); |
152 | | |
153 | | // Attempts to reduce ADDIU into ADDIUSP instruction, |
154 | | // returns true on success. |
155 | | static bool ReduceADDIUToADDIUSP(MachineInstr *MI, const ReduceEntry &Entry); |
156 | | |
157 | | // Attempts to reduce ADDIU into ADDIUR1SP instruction, |
158 | | // returns true on success. |
159 | | static bool ReduceADDIUToADDIUR1SP(MachineInstr *MI, |
160 | | const ReduceEntry &Entry); |
161 | | |
162 | | // Attempts to reduce XOR into XOR16 instruction, |
163 | | // returns true on success. |
164 | | static bool ReduceXORtoXOR16(MachineInstr *MI, const ReduceEntry &Entry); |
165 | | |
166 | | // Changes opcode of an instruction. |
167 | | static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry); |
168 | | |
169 | | // Table with transformation rules for each instruction. |
170 | | static llvm::SmallVector<ReduceEntry, 16> ReduceTable; |
171 | | }; |
172 | | |
173 | | char MicroMipsSizeReduce::ID = 0; |
174 | | const MipsInstrInfo *MicroMipsSizeReduce::MipsII; |
175 | | |
176 | | // This table must be sorted by WideOpc as a main criterion and |
177 | | // ReduceType as a sub-criterion (when wide opcodes are the same). |
178 | | llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = { |
179 | | |
180 | | // ReduceType, OpCodes, ReduceFunction, |
181 | | // OpInfo(TransferOperands), |
182 | | // ImmField(Shift, LBound, HBound, ImmFieldPosition) |
183 | | {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUR1SP_MM), |
184 | | ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, |
185 | | {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUSP_MM), ReduceADDIUToADDIUSP, |
186 | | OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)}, |
187 | | {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUR1SP_MM), |
188 | | ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, |
189 | | {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUSP_MM), |
190 | | ReduceADDIUToADDIUSP, OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)}, |
191 | | {RT_OneInstr, OpCodes(Mips::ADDu, Mips::ADDU16_MM), |
192 | | ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), |
193 | | ImmField(0, 0, 0, -1)}, |
194 | | {RT_OneInstr, OpCodes(Mips::ADDu_MM, Mips::ADDU16_MM), |
195 | | ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), |
196 | | ImmField(0, 0, 0, -1)}, |
197 | | {RT_OneInstr, OpCodes(Mips::LBu, Mips::LBU16_MM), ReduceLXUtoLXU16, |
198 | | OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, |
199 | | {RT_OneInstr, OpCodes(Mips::LBu_MM, Mips::LBU16_MM), ReduceLXUtoLXU16, |
200 | | OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, |
201 | | {RT_OneInstr, OpCodes(Mips::LEA_ADDiu, Mips::ADDIUR1SP_MM), |
202 | | ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, |
203 | | {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16, |
204 | | OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, |
205 | | {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16, |
206 | | OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, |
207 | | {RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP, |
208 | | OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, |
209 | | {RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP, |
210 | | OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, |
211 | | {RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16, |
212 | | OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)}, |
213 | | {RT_OneInstr, OpCodes(Mips::SB_MM, Mips::SB16_MM), ReduceSXtoSX16, |
214 | | OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)}, |
215 | | {RT_OneInstr, OpCodes(Mips::SH, Mips::SH16_MM), ReduceSXtoSX16, |
216 | | OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, |
217 | | {RT_OneInstr, OpCodes(Mips::SH_MM, Mips::SH16_MM), ReduceSXtoSX16, |
218 | | OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, |
219 | | {RT_OneInstr, OpCodes(Mips::SUBu, Mips::SUBU16_MM), |
220 | | ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), |
221 | | ImmField(0, 0, 0, -1)}, |
222 | | {RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM), |
223 | | ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), |
224 | | ImmField(0, 0, 0, -1)}, |
225 | | {RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP, |
226 | | OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, |
227 | | {RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP, |
228 | | OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, |
229 | | {RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16, |
230 | | OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}, |
231 | | {RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16, |
232 | | OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}}; |
233 | | } // namespace |
234 | | |
235 | | // Returns true if the machine operand MO is register SP. |
236 | 406 | static bool IsSP(const MachineOperand &MO) { |
237 | 406 | if (MO.isReg() && 406 ((MO.getReg() == Mips::SP))406 ) |
238 | 402 | return true; |
239 | 4 | return false; |
240 | 4 | } |
241 | | |
242 | | // Returns true if the machine operand MO is register $16, $17, or $2-$7. |
243 | 200 | static bool isMMThreeBitGPRegister(const MachineOperand &MO) { |
244 | 200 | if (MO.isReg() && 200 Mips::GPRMM16RegClass.contains(MO.getReg())200 ) |
245 | 100 | return true; |
246 | 100 | return false; |
247 | 100 | } |
248 | | |
249 | | // Returns true if the machine operand MO is register $0, $17, or $2-$7. |
250 | 2 | static bool isMMSourceRegister(const MachineOperand &MO) { |
251 | 2 | if (MO.isReg() && 2 Mips::GPRMM16ZeroRegClass.contains(MO.getReg())2 ) |
252 | 2 | return true; |
253 | 0 | return false; |
254 | 0 | } |
255 | | |
256 | | // Returns true if the operand Op is an immediate value |
257 | | // and writes the immediate value into variable Imm. |
258 | 537 | static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm) { |
259 | 537 | |
260 | 537 | if (!MI->getOperand(Op).isImm()) |
261 | 75 | return false; |
262 | 462 | Imm = MI->getOperand(Op).getImm(); |
263 | 462 | return true; |
264 | 462 | } |
265 | | |
266 | | // Returns true if the value is a valid immediate for ADDIUSP. |
267 | 97 | static bool AddiuspImmValue(int64_t Value) { |
268 | 97 | int64_t Value2 = Value >> 2; |
269 | 97 | if (((Value & (int64_t)maskTrailingZeros<uint64_t>(2)) == Value) && |
270 | 95 | ((Value2 >= 2 && 95 Value2 <= 25742 ) || (Value2 >= -258 && 54 Value2 <= -352 ))) |
271 | 74 | return true; |
272 | 23 | return false; |
273 | 23 | } |
274 | | |
275 | | // Returns true if the variable Value has the number of least-significant zero |
276 | | // bits equal to Shift and if the shifted value is between the bounds. |
277 | | static bool InRange(int64_t Value, unsigned short Shift, int LBound, |
278 | 365 | int HBound) { |
279 | 365 | int64_t Value2 = Value >> Shift; |
280 | 365 | if (((Value & (int64_t)maskTrailingZeros<uint64_t>(Shift)) == Value) && |
281 | 365 | (Value2 >= LBound)363 && (Value2 < HBound)310 ) |
282 | 308 | return true; |
283 | 57 | return false; |
284 | 57 | } |
285 | | |
286 | | // Returns true if immediate operand is in range. |
287 | 434 | static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) { |
288 | 434 | |
289 | 434 | int64_t offset; |
290 | 434 | |
291 | 434 | if (!GetImm(MI, Entry.ImmField(), offset)) |
292 | 69 | return false; |
293 | 365 | |
294 | 365 | if (365 !InRange(offset, Entry.Shift(), Entry.LBound(), Entry.HBound())365 ) |
295 | 57 | return false; |
296 | 308 | |
297 | 308 | return true; |
298 | 308 | } |
299 | | |
300 | 1.72k | MicroMipsSizeReduce::MicroMipsSizeReduce() : MachineFunctionPass(ID) {} |
301 | | |
302 | | bool MicroMipsSizeReduce::ReduceMI( |
303 | 2.07k | const MachineBasicBlock::instr_iterator &MII) { |
304 | 2.07k | |
305 | 2.07k | MachineInstr *MI = &*MII; |
306 | 2.07k | unsigned Opcode = MI->getOpcode(); |
307 | 2.07k | |
308 | 2.07k | // Search the table. |
309 | 2.07k | llvm::SmallVector<ReduceEntry, 16>::const_iterator Start = |
310 | 2.07k | std::begin(ReduceTable); |
311 | 2.07k | llvm::SmallVector<ReduceEntry, 16>::const_iterator End = |
312 | 2.07k | std::end(ReduceTable); |
313 | 2.07k | |
314 | 2.07k | std::pair<llvm::SmallVector<ReduceEntry, 16>::const_iterator, |
315 | 2.07k | llvm::SmallVector<ReduceEntry, 16>::const_iterator> |
316 | 2.07k | Range = std::equal_range(Start, End, Opcode); |
317 | 2.07k | |
318 | 2.07k | if (Range.first == Range.second) |
319 | 1.58k | return false; |
320 | 493 | |
321 | 493 | for (llvm::SmallVector<ReduceEntry, 16>::const_iterator Entry = Range.first; |
322 | 752 | Entry != Range.second752 ; ++Entry259 ) |
323 | 596 | if (596 ((*Entry).ReduceFunction)(&(*MII), *Entry)596 ) |
324 | 337 | return true; |
325 | 493 | |
326 | 156 | return false; |
327 | 2.07k | } |
328 | | |
329 | | bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI, |
330 | 324 | const ReduceEntry &Entry) { |
331 | 324 | |
332 | 324 | if (!ImmInRange(MI, Entry)) |
333 | 63 | return false; |
334 | 261 | |
335 | 261 | if (261 !IsSP(MI->getOperand(1))261 ) |
336 | 0 | return false; |
337 | 261 | |
338 | 261 | return ReplaceInstruction(MI, Entry); |
339 | 261 | } |
340 | | |
341 | | bool MicroMipsSizeReduce::ReduceArithmeticInstructions( |
342 | 51 | MachineInstr *MI, const ReduceEntry &Entry) { |
343 | 51 | |
344 | 51 | if (!isMMThreeBitGPRegister(MI->getOperand(0)) || |
345 | 44 | !isMMThreeBitGPRegister(MI->getOperand(1)) || |
346 | 44 | !isMMThreeBitGPRegister(MI->getOperand(2))) |
347 | 51 | return false; |
348 | 0 |
|
349 | 0 | return ReplaceInstruction(MI, Entry); |
350 | 0 | } |
351 | | |
352 | | bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI, |
353 | 104 | const ReduceEntry &Entry) { |
354 | 104 | |
355 | 104 | if (!ImmInRange(MI, Entry)) |
356 | 63 | return false; |
357 | 41 | |
358 | 41 | if (41 !isMMThreeBitGPRegister(MI->getOperand(0)) || 41 !IsSP(MI->getOperand(1))1 ) |
359 | 40 | return false; |
360 | 1 | |
361 | 1 | return ReplaceInstruction(MI, Entry); |
362 | 1 | } |
363 | | |
364 | | bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI, |
365 | 103 | const ReduceEntry &Entry) { |
366 | 103 | |
367 | 103 | int64_t ImmValue; |
368 | 103 | if (!GetImm(MI, Entry.ImmField(), ImmValue)) |
369 | 6 | return false; |
370 | 97 | |
371 | 97 | if (97 !AddiuspImmValue(ImmValue)97 ) |
372 | 23 | return false; |
373 | 74 | |
374 | 74 | if (74 !IsSP(MI->getOperand(0)) || 74 !IsSP(MI->getOperand(1))70 ) |
375 | 4 | return false; |
376 | 70 | |
377 | 70 | return ReplaceInstruction(MI, Entry); |
378 | 70 | } |
379 | | |
380 | | bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI, |
381 | 4 | const ReduceEntry &Entry) { |
382 | 4 | |
383 | 4 | if (!ImmInRange(MI, Entry)) |
384 | 0 | return false; |
385 | 4 | |
386 | 4 | if (4 !isMMThreeBitGPRegister(MI->getOperand(0)) || |
387 | 4 | !isMMThreeBitGPRegister(MI->getOperand(1))) |
388 | 2 | return false; |
389 | 2 | |
390 | 2 | return ReplaceInstruction(MI, Entry); |
391 | 2 | } |
392 | | |
393 | | bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI, |
394 | 2 | const ReduceEntry &Entry) { |
395 | 2 | |
396 | 2 | if (!ImmInRange(MI, Entry)) |
397 | 0 | return false; |
398 | 2 | |
399 | 2 | if (2 !isMMSourceRegister(MI->getOperand(0)) || |
400 | 2 | !isMMThreeBitGPRegister(MI->getOperand(1))) |
401 | 0 | return false; |
402 | 2 | |
403 | 2 | return ReplaceInstruction(MI, Entry); |
404 | 2 | } |
405 | | |
406 | | bool MicroMipsSizeReduce::ReduceXORtoXOR16(MachineInstr *MI, |
407 | 8 | const ReduceEntry &Entry) { |
408 | 8 | if (!isMMThreeBitGPRegister(MI->getOperand(0)) || |
409 | 1 | !isMMThreeBitGPRegister(MI->getOperand(1)) || |
410 | 1 | !isMMThreeBitGPRegister(MI->getOperand(2))) |
411 | 7 | return false; |
412 | 1 | |
413 | 1 | if (1 !(MI->getOperand(0).getReg() == MI->getOperand(2).getReg()) && |
414 | 0 | !(MI->getOperand(0).getReg() == MI->getOperand(1).getReg())) |
415 | 0 | return false; |
416 | 1 | |
417 | 1 | return ReplaceInstruction(MI, Entry); |
418 | 1 | } |
419 | | |
420 | 381 | bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) { |
421 | 381 | bool Modified = false; |
422 | 381 | MachineBasicBlock::instr_iterator MII = MBB.instr_begin(), |
423 | 381 | E = MBB.instr_end(); |
424 | 381 | MachineBasicBlock::instr_iterator NextMII; |
425 | 381 | |
426 | 381 | // Iterate through the instructions in the basic block |
427 | 2.54k | for (; MII != E2.54k ; MII = NextMII2.16k ) { |
428 | 2.16k | NextMII = std::next(MII); |
429 | 2.16k | MachineInstr *MI = &*MII; |
430 | 2.16k | |
431 | 2.16k | // Don't reduce bundled instructions or pseudo operations |
432 | 2.16k | if (MI->isBundle() || 2.16k MI->isTransient()2.16k ) |
433 | 90 | continue; |
434 | 2.07k | |
435 | 2.07k | // Try to reduce 32-bit instruction into 16-bit instruction |
436 | 2.07k | Modified |= ReduceMI(MII); |
437 | 2.07k | } |
438 | 381 | |
439 | 381 | return Modified; |
440 | 381 | } |
441 | | |
442 | | bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI, |
443 | 337 | const ReduceEntry &Entry) { |
444 | 337 | |
445 | 337 | enum OperandTransfer OpTransfer = Entry.TransferOperands(); |
446 | 337 | |
447 | 337 | DEBUG(dbgs() << "Converting 32-bit: " << *MI); |
448 | 337 | ++NumReduced; |
449 | 337 | |
450 | 337 | if (OpTransfer == OT_OperandsAll337 ) { |
451 | 265 | MI->setDesc(MipsII->get(Entry.NarrowOpc())); |
452 | 265 | DEBUG(dbgs() << " to 16-bit: " << *MI); |
453 | 265 | return true; |
454 | 0 | } else { |
455 | 72 | MachineBasicBlock &MBB = *MI->getParent(); |
456 | 72 | const MCInstrDesc &NewMCID = MipsII->get(Entry.NarrowOpc()); |
457 | 72 | DebugLoc dl = MI->getDebugLoc(); |
458 | 72 | MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, NewMCID); |
459 | 72 | switch (OpTransfer) { |
460 | 70 | case OT_Operand2: |
461 | 70 | MIB.add(MI->getOperand(2)); |
462 | 70 | break; |
463 | 1 | case OT_Operands02: { |
464 | 1 | MIB.add(MI->getOperand(0)); |
465 | 1 | MIB.add(MI->getOperand(2)); |
466 | 1 | break; |
467 | 72 | } |
468 | 1 | case OT_OperandsXOR: { |
469 | 1 | if (MI->getOperand(0).getReg() == MI->getOperand(2).getReg()1 ) { |
470 | 1 | MIB.add(MI->getOperand(0)); |
471 | 1 | MIB.add(MI->getOperand(1)); |
472 | 1 | MIB.add(MI->getOperand(2)); |
473 | 1 | } else { |
474 | 0 | MIB.add(MI->getOperand(0)); |
475 | 0 | MIB.add(MI->getOperand(2)); |
476 | 0 | MIB.add(MI->getOperand(1)); |
477 | 0 | } |
478 | 1 | break; |
479 | 72 | } |
480 | 0 | default: |
481 | 0 | llvm_unreachable("Unknown operand transfer!"); |
482 | 72 | } |
483 | 72 | |
484 | 72 | // Transfer MI flags. |
485 | 72 | MIB.setMIFlags(MI->getFlags()); |
486 | 72 | |
487 | 72 | DEBUG(dbgs() << " to 16-bit: " << *MIB); |
488 | 72 | MBB.erase_instr(MI); |
489 | 72 | return true; |
490 | 72 | } |
491 | 0 | return false; |
492 | 0 | } |
493 | | |
494 | 12.3k | bool MicroMipsSizeReduce::runOnMachineFunction(MachineFunction &MF) { |
495 | 12.3k | |
496 | 12.3k | Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); |
497 | 12.3k | |
498 | 12.3k | // TODO: Add support for other subtargets: |
499 | 12.3k | // microMIPS32r6 and microMIPS64r6 |
500 | 12.3k | if (!Subtarget->inMicroMipsMode() || 12.3k !Subtarget->hasMips32r2()950 || |
501 | 899 | Subtarget->hasMips32r6()) |
502 | 11.9k | return false; |
503 | 322 | |
504 | 322 | MipsII = static_cast<const MipsInstrInfo *>(Subtarget->getInstrInfo()); |
505 | 322 | |
506 | 322 | bool Modified = false; |
507 | 322 | MachineFunction::iterator I = MF.begin(), E = MF.end(); |
508 | 322 | |
509 | 703 | for (; I != E703 ; ++I381 ) |
510 | 381 | Modified |= ReduceMBB(*I); |
511 | 12.3k | return Modified; |
512 | 12.3k | } |
513 | | |
514 | | /// Returns an instance of the MicroMips size reduction pass. |
515 | 1.72k | FunctionPass *llvm::createMicroMipsSizeReductionPass() { |
516 | 1.72k | return new MicroMipsSizeReduce(); |
517 | 1.72k | } |