LLVM 24.0.0git
Thumb2SizeReduction.cpp
Go to the documentation of this file.
1//===-- Thumb2SizeReduction.cpp - Thumb2 code size reduction pass -*- C++ -*-=//
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
9#include "ARM.h"
10#include "ARMBaseInstrInfo.h"
11#include "ARMSubtarget.h"
13#include "Thumb2InstrInfo.h"
14#include "llvm/ADT/DenseMap.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/SmallSet.h"
19#include "llvm/ADT/Statistic.h"
20#include "llvm/ADT/StringRef.h"
29#include "llvm/IR/DebugLoc.h"
30#include "llvm/IR/Function.h"
31#include "llvm/MC/MCAsmInfo.h"
32#include "llvm/MC/MCInstrDesc.h"
35#include "llvm/Support/Debug.h"
38#include <cassert>
39#include <cstdint>
40#include <functional>
41#include <iterator>
42#include <utility>
43
44using namespace llvm;
45
46#define DEBUG_TYPE "thumb2-reduce-size"
47#define THUMB2_SIZE_REDUCE_NAME "Thumb2 instruction size reduce pass"
48
49STATISTIC(NumNarrows, "Number of 32-bit instrs reduced to 16-bit ones");
50STATISTIC(Num2Addrs, "Number of 32-bit instrs reduced to 2addr 16-bit ones");
51STATISTIC(NumLdSts, "Number of 32-bit load / store reduced to 16-bit ones");
52
53static cl::opt<int> ReduceLimit("t2-reduce-limit",
54 cl::init(-1), cl::Hidden);
55static cl::opt<int> ReduceLimit2Addr("t2-reduce-limit2",
56 cl::init(-1), cl::Hidden);
57static cl::opt<int> ReduceLimitLdSt("t2-reduce-limit3",
58 cl::init(-1), cl::Hidden);
59
60namespace {
61
62 /// ReduceTable - A static table with information on mapping from wide
63 /// opcodes to narrow
64 struct ReduceEntry {
65 uint16_t WideOpc; // Wide opcode
66 uint16_t NarrowOpc1; // Narrow opcode to transform to
67 uint16_t NarrowOpc2; // Narrow opcode when it's two-address
68 uint8_t Imm1Limit; // Limit of immediate field (bits)
69 uint8_t Imm2Limit; // Limit of immediate field when it's two-address
70 unsigned LowRegs1 : 1; // Only possible if low-registers are used
71 unsigned LowRegs2 : 1; // Only possible if low-registers are used (2addr)
72 unsigned PredCC1 : 2; // 0 - If predicated, cc is on and vice versa.
73 // 1 - No cc field.
74 // 2 - Always set CPSR.
75 unsigned PredCC2 : 2;
76 unsigned PartFlag : 1; // 16-bit instruction does partial flag update
77 unsigned Special : 1; // Needs to be dealt with specially
78 unsigned AvoidMovs: 1; // Avoid movs with shifter operand (for Swift)
79 };
80
81 static const ReduceEntry ReduceTable[] = {
82 // Wide, Narrow1, Narrow2, imm1,imm2, lo1, lo2, P/C,PF,S,AM
83 { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0,0,0 },
84 { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,1,0 },
85 { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0,0,0 },
86 { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 0,1,0 },
87 { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 0,1,0 },
88 { ARM::t2ANDrr, 0, ARM::tAND, 0, 0, 0, 1, 0,0, 1,0,0 },
89 { ARM::t2ASRri, ARM::tASRri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
90 { ARM::t2ASRrr, 0, ARM::tASRrr, 0, 0, 0, 1, 0,0, 1,0,1 },
91 { ARM::t2BICrr, 0, ARM::tBIC, 0, 0, 0, 1, 0,0, 1,0,0 },
92 { ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
93 { ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0,0,0 },
94 { ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 0,1,0 },
95 { ARM::t2EORrr, 0, ARM::tEOR, 0, 0, 0, 1, 0,0, 1,0,0 },
96 // FIXME: adr.n immediate offset must be multiple of 4.
97 //{ ARM::t2LEApcrelJT,ARM::tLEApcrelJT, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
98 { ARM::t2LSLri, ARM::tLSLri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
99 { ARM::t2LSLrr, 0, ARM::tLSLrr, 0, 0, 0, 1, 0,0, 1,0,1 },
100 { ARM::t2LSRri, ARM::tLSRri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
101 { ARM::t2LSRrr, 0, ARM::tLSRrr, 0, 0, 0, 1, 0,0, 1,0,1 },
102 { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1,0,0 },
103 { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1,1,0 },
104 // FIXME: Do we need the 16-bit 'S' variant?
105 { ARM::t2MOVr,ARM::tMOVr, 0, 0, 0, 0, 0, 1,0, 0,0,0 },
106 { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 1,0,0 },
107 { ARM::t2MVNr, ARM::tMVN, 0, 0, 0, 1, 0, 0,0, 0,0,0 },
108 { ARM::t2ORRrr, 0, ARM::tORR, 0, 0, 0, 1, 0,0, 1,0,0 },
109 { ARM::t2REV, ARM::tREV, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
110 { ARM::t2REV16, ARM::tREV16, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
111 { ARM::t2REVSH, ARM::tREVSH, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
112 { ARM::t2RORrr, 0, ARM::tROR, 0, 0, 0, 1, 0,0, 1,0,0 },
113 { ARM::t2RSBri, ARM::tRSB, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
114 { ARM::t2RSBSri,ARM::tRSB, 0, 0, 0, 1, 0, 2,0, 0,1,0 },
115 { ARM::t2SBCrr, 0, ARM::tSBC, 0, 0, 0, 1, 0,0, 0,0,0 },
116 { ARM::t2SUBri, ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0,0,0 },
117 { ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0,0,0 },
118 { ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0,0,0 },
119 { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
120 { ARM::t2SXTB, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
121 { ARM::t2SXTH, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
122 { ARM::t2TEQrr, ARM::tEOR, 0, 0, 0, 1, 0, 2,0, 0,1,0 },
123 { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
124 { ARM::t2UXTB, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
125 { ARM::t2UXTH, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
126
127 // FIXME: Clean this up after splitting each Thumb load / store opcode
128 // into multiple ones.
129 { ARM::t2LDRi12,ARM::tLDRi, ARM::tLDRspi, 5, 8, 1, 0, 0,0, 0,1,0 },
130 { ARM::t2LDRs, ARM::tLDRr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
131 { ARM::t2LDRBi12,ARM::tLDRBi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
132 { ARM::t2LDRBs, ARM::tLDRBr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
133 { ARM::t2LDRHi12,ARM::tLDRHi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
134 { ARM::t2LDRHs, ARM::tLDRHr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
135 { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
136 { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
137 { ARM::t2LDR_POST,ARM::tLDMIA_UPD,0, 0, 0, 1, 0, 0,0, 0,1,0 },
138 { ARM::t2STRi12,ARM::tSTRi, ARM::tSTRspi, 5, 8, 1, 0, 0,0, 0,1,0 },
139 { ARM::t2STRs, ARM::tSTRr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
140 { ARM::t2STRBi12,ARM::tSTRBi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
141 { ARM::t2STRBs, ARM::tSTRBr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
142 { ARM::t2STRHi12,ARM::tSTRHi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
143 { ARM::t2STRHs, ARM::tSTRHr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
144 { ARM::t2STR_POST,ARM::tSTMIA_UPD,0, 0, 0, 1, 0, 0,0, 0,1,0 },
145
146 { ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
147 { ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 0,1,0 },
148 { ARM::t2LDMIA_UPD,ARM::tLDMIA_UPD,ARM::tPOP,0, 0, 1, 1, 1,1, 0,1,0 },
149 // ARM::t2STMIA (with no basereg writeback) has no Thumb1 equivalent.
150 // tSTMIA_UPD is a change in semantics which can only be used if the base
151 // register is killed. This difference is correctly handled elsewhere.
152 { ARM::t2STMIA, ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
153 { ARM::t2STMIA_UPD,ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
154 { ARM::t2STMDB_UPD, 0, ARM::tPUSH, 0, 0, 1, 1, 1,1, 0,1,0 }
155 };
156
157 class Thumb2SizeReduce : public MachineFunctionPass {
158 public:
159 static char ID;
160
161 const Thumb2InstrInfo *TII;
162 const ARMSubtarget *STI;
163
164 Thumb2SizeReduce(std::function<bool(const Function &)> Ftor = nullptr);
165
166 bool runOnMachineFunction(MachineFunction &MF) override;
167
168 MachineFunctionProperties getRequiredProperties() const override {
169 return MachineFunctionProperties().setNoVRegs();
170 }
171
172 StringRef getPassName() const override {
174 }
175
176 void getAnalysisUsage(AnalysisUsage &AU) const override {
177 AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
179 }
180
181 private:
182 /// ReduceOpcodeMap - Maps wide opcode to index of entry in ReduceTable.
183 DenseMap<unsigned, unsigned> ReduceOpcodeMap;
184
185 bool canAddPseudoFlagDep(MachineInstr *Use, bool IsSelfLoop);
186
187 bool VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry,
188 bool is2Addr, ARMCC::CondCodes Pred,
189 bool LiveCPSR, bool &HasCC, bool &CCDead);
190
191 bool ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
192 const ReduceEntry &Entry);
193
194 bool ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
195 const ReduceEntry &Entry, bool LiveCPSR, bool IsSelfLoop);
196
197 /// ReduceTo2Addr - Reduce a 32-bit instruction to a 16-bit two-address
198 /// instruction.
199 bool ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
200 const ReduceEntry &Entry, bool LiveCPSR,
201 bool IsSelfLoop);
202
203 /// ReduceToNarrow - Reduce a 32-bit instruction to a 16-bit
204 /// non-two-address instruction.
205 bool ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI,
206 const ReduceEntry &Entry, bool LiveCPSR,
207 bool IsSelfLoop);
208
209 /// ReduceMI - Attempt to reduce MI, return true on success.
210 bool ReduceMI(MachineBasicBlock &MBB, MachineInstr *MI, bool LiveCPSR,
211 bool IsSelfLoop, bool SkipPrologueEpilogue);
212
213 /// ReduceMBB - Reduce width of instructions in the specified basic block.
214 bool ReduceMBB(MachineBasicBlock &MBB, bool SkipPrologueEpilogue);
215
216 bool OptimizeSize;
217 bool MinimizeSize;
218
219 // Last instruction to define CPSR in the current block.
220 MachineInstr *CPSRDef;
221 // Was CPSR last defined by a high latency instruction?
222 // When CPSRDef is null, this refers to CPSR defs in predecessors.
223 bool HighLatencyCPSR;
224
225 struct MBBInfo {
226 // The flags leaving this block have high latency.
227 bool HighLatencyCPSR = false;
228 // Has this block been visited yet?
229 bool Visited = false;
230
231 MBBInfo() = default;
232 };
233
234 SmallVector<MBBInfo, 8> BlockInfo;
235
236 std::function<bool(const Function &)> PredicateFtor;
237 };
238
239 char Thumb2SizeReduce::ID = 0;
240
241} // end anonymous namespace
242
244 false)
245
246Thumb2SizeReduce::Thumb2SizeReduce(std::function<bool(const Function &)> Ftor)
247 : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) {
248 OptimizeSize = MinimizeSize = false;
249 for (unsigned i = 0, e = std::size(ReduceTable); i != e; ++i) {
250 unsigned FromOpc = ReduceTable[i].WideOpc;
251 if (!ReduceOpcodeMap.insert(std::make_pair(FromOpc, i)).second)
252 llvm_unreachable("Duplicated entries?");
253 }
254}
255
257 return is_contained(MCID.implicit_defs(), ARM::CPSR);
258}
259
260// Check for a likely high-latency flag def.
262 switch(Def->getOpcode()) {
263 case ARM::FMSTAT:
264 case ARM::tMUL:
265 return true;
266 }
267 return false;
268}
269
270/// canAddPseudoFlagDep - For A9 (and other out-of-order) implementations,
271/// the 's' 16-bit instruction partially update CPSR. Abort the
272/// transformation to avoid adding false dependency on last CPSR setting
273/// instruction which hurts the ability for out-of-order execution engine
274/// to do register renaming magic.
275/// This function checks if there is a read-of-write dependency between the
276/// last instruction that defines the CPSR and the current instruction. If there
277/// is, then there is no harm done since the instruction cannot be retired
278/// before the CPSR setting instruction anyway.
279/// Note, we are not doing full dependency analysis here for the sake of compile
280/// time. We're not looking for cases like:
281/// r0 = muls ...
282/// r1 = add.w r0, ...
283/// ...
284/// = mul.w r1
285/// In this case it would have been ok to narrow the mul.w to muls since there
286/// are indirect RAW dependency between the muls and the mul.w
287bool
288Thumb2SizeReduce::canAddPseudoFlagDep(MachineInstr *Use, bool FirstInSelfLoop) {
289 // Disable the check for -Oz (aka OptimizeForSizeHarder).
290 if (MinimizeSize || !STI->avoidCPSRPartialUpdate())
291 return false;
292
293 if (!CPSRDef)
294 // If this BB loops back to itself, conservatively avoid narrowing the
295 // first instruction that does partial flag update.
296 return HighLatencyCPSR || FirstInSelfLoop;
297
298 SmallSet<unsigned, 2> Defs;
299 for (const MachineOperand &MO : CPSRDef->operands()) {
300 if (!MO.isReg() || MO.isUndef() || MO.isUse())
301 continue;
302 Register Reg = MO.getReg();
303 if (Reg == 0 || Reg == ARM::CPSR)
304 continue;
305 Defs.insert(Reg);
306 }
307
308 for (const MachineOperand &MO : Use->operands()) {
309 if (!MO.isReg() || MO.isUndef() || MO.isDef())
310 continue;
311 Register Reg = MO.getReg();
312 if (Defs.count(Reg))
313 return false;
314 }
315
316 // If the current CPSR has high latency, try to avoid the false dependency.
317 if (HighLatencyCPSR)
318 return true;
319
320 // tMOVi8 usually doesn't start long dependency chains, and there are a lot
321 // of them, so always shrink them when CPSR doesn't have high latency.
322 if (Use->getOpcode() == ARM::t2MOVi ||
323 Use->getOpcode() == ARM::t2MOVi16)
324 return false;
325
326 // No read-after-write dependency. The narrowing will add false dependency.
327 return true;
328}
329
330bool
331Thumb2SizeReduce::VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry,
332 bool is2Addr, ARMCC::CondCodes Pred,
333 bool LiveCPSR, bool &HasCC, bool &CCDead) {
334 if ((is2Addr && Entry.PredCC2 == 0) ||
335 (!is2Addr && Entry.PredCC1 == 0)) {
336 if (Pred == ARMCC::AL) {
337 // Not predicated, must set CPSR.
338 if (!HasCC) {
339 // Original instruction was not setting CPSR, but CPSR is not
340 // currently live anyway. It's ok to set it. The CPSR def is
341 // dead though.
342 if (!LiveCPSR) {
343 HasCC = true;
344 CCDead = true;
345 return true;
346 }
347 return false;
348 }
349 } else {
350 // Predicated, must not set CPSR.
351 if (HasCC)
352 return false;
353 }
354 } else if ((is2Addr && Entry.PredCC2 == 2) ||
355 (!is2Addr && Entry.PredCC1 == 2)) {
356 /// Old opcode has an optional def of CPSR.
357 if (HasCC)
358 return true;
359 // If old opcode does not implicitly define CPSR, then it's not ok since
360 // these new opcodes' CPSR def is not meant to be thrown away. e.g. CMP.
361 if (!HasImplicitCPSRDef(MI->getDesc()))
362 return false;
363 HasCC = true;
364 } else {
365 // 16-bit instruction does not set CPSR.
366 if (HasCC)
367 return false;
368 }
369
370 return true;
371}
372
374 unsigned Opc = MI->getOpcode();
375 bool isPCOk = (Opc == ARM::t2LDMIA_RET || Opc == ARM::t2LDMIA_UPD);
376 bool isLROk = (Opc == ARM::t2STMDB_UPD);
377 bool isSPOk = isPCOk || isLROk;
378 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
379 const MachineOperand &MO = MI->getOperand(i);
380 if (!MO.isReg() || MO.isImplicit())
381 continue;
382 Register Reg = MO.getReg();
383 if (Reg == 0 || Reg == ARM::CPSR)
384 continue;
385 if (isPCOk && Reg == ARM::PC)
386 continue;
387 if (isLROk && Reg == ARM::LR)
388 continue;
389 if (Reg == ARM::SP) {
390 if (isSPOk)
391 continue;
392 if (i == 1 && (Opc == ARM::t2LDRi12 || Opc == ARM::t2STRi12))
393 // Special case for these ldr / str with sp as base register.
394 continue;
395 }
396 if (!isARMLowRegister(Reg))
397 return false;
398 }
399 return true;
400}
401
402bool
403Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
404 const ReduceEntry &Entry) {
405 if (ReduceLimitLdSt != -1 && ((int)NumLdSts >= ReduceLimitLdSt))
406 return false;
407
408 unsigned Scale = 1;
409 bool HasImmOffset = false;
410 bool HasShift = false;
411 bool HasOffReg = true;
412 bool isLdStMul = false;
413 unsigned Opc = Entry.NarrowOpc1;
414 unsigned OpNum = 3; // First 'rest' of operands.
415 uint8_t ImmLimit = Entry.Imm1Limit;
416
417 switch (Entry.WideOpc) {
418 default:
419 llvm_unreachable("Unexpected Thumb2 load / store opcode!");
420 case ARM::t2LDRi12:
421 case ARM::t2STRi12:
422 if (MI->getOperand(1).getReg() == ARM::SP) {
423 Opc = Entry.NarrowOpc2;
424 ImmLimit = Entry.Imm2Limit;
425 }
426
427 Scale = 4;
428 HasImmOffset = true;
429 HasOffReg = false;
430 break;
431 case ARM::t2LDRBi12:
432 case ARM::t2STRBi12:
433 HasImmOffset = true;
434 HasOffReg = false;
435 break;
436 case ARM::t2LDRHi12:
437 case ARM::t2STRHi12:
438 Scale = 2;
439 HasImmOffset = true;
440 HasOffReg = false;
441 break;
442 case ARM::t2LDRs:
443 case ARM::t2LDRBs:
444 case ARM::t2LDRHs:
445 case ARM::t2LDRSBs:
446 case ARM::t2LDRSHs:
447 case ARM::t2STRs:
448 case ARM::t2STRBs:
449 case ARM::t2STRHs:
450 HasShift = true;
451 OpNum = 4;
452 break;
453 case ARM::t2LDR_POST:
454 case ARM::t2STR_POST: {
455 if (!MinimizeSize)
456 return false;
457
458 if (!MI->hasOneMemOperand() ||
459 (*MI->memoperands_begin())->getAlign() < Align(4))
460 return false;
461
462 // We're creating a completely different type of load/store - LDM from LDR.
463 // For this reason we can't reuse the logic at the end of this function; we
464 // have to implement the MI building here.
465 bool IsStore = Entry.WideOpc == ARM::t2STR_POST;
466 Register Rt = MI->getOperand(IsStore ? 1 : 0).getReg();
467 Register Rn = MI->getOperand(IsStore ? 0 : 1).getReg();
468 unsigned Offset = MI->getOperand(3).getImm();
469 unsigned PredImm = MI->getOperand(4).getImm();
470 Register PredReg = MI->getOperand(5).getReg();
473
474 if (Offset != 4)
475 return false;
476
477 // Add the 16-bit load / store instruction.
478 DebugLoc dl = MI->getDebugLoc();
479 auto MIB = BuildMI(MBB, MI, dl, TII->get(Entry.NarrowOpc1))
480 .addReg(Rn, RegState::Define)
481 .addReg(Rn)
482 .addImm(PredImm)
483 .addReg(PredReg)
484 .addReg(Rt, getDefRegState(!IsStore));
485
486 // Transfer memoperands.
487 MIB.setMemRefs(MI->memoperands());
488
489 // Transfer MI flags.
490 MIB.setMIFlags(MI->getFlags());
491
492 // Kill the old instruction.
493 MI->eraseFromBundle();
494 ++NumLdSts;
495 return true;
496 }
497 case ARM::t2LDMIA: {
498 Register BaseReg = MI->getOperand(0).getReg();
499 assert(isARMLowRegister(BaseReg));
500
501 // For the non-writeback version (this one), the base register must be
502 // one of the registers being loaded.
503 bool isOK = false;
504 for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 3)) {
505 if (MO.getReg() == BaseReg) {
506 isOK = true;
507 break;
508 }
509 }
510
511 if (!isOK)
512 return false;
513
514 OpNum = 0;
515 isLdStMul = true;
516 break;
517 }
518 case ARM::t2STMIA: {
519 // t2STMIA is reduced to tSTMIA_UPD which has writeback. We can only do this
520 // if the base register is killed, as then it doesn't matter what its value
521 // is after the instruction.
522 if (!MI->getOperand(0).isKill())
523 return false;
524
525 // If the base register is in the register list and isn't the lowest
526 // numbered register (i.e. it's in operand 4 onwards) then with writeback
527 // the stored value is unknown, so we can't convert to tSTMIA_UPD.
528 Register BaseReg = MI->getOperand(0).getReg();
529 for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 4))
530 if (MO.getReg() == BaseReg)
531 return false;
532
533 break;
534 }
535 case ARM::t2LDMIA_RET: {
536 Register BaseReg = MI->getOperand(1).getReg();
537 if (BaseReg != ARM::SP)
538 return false;
539 Opc = Entry.NarrowOpc2; // tPOP_RET
540 OpNum = 2;
541 isLdStMul = true;
542 break;
543 }
544 case ARM::t2LDMIA_UPD:
545 case ARM::t2STMIA_UPD:
546 case ARM::t2STMDB_UPD: {
547 OpNum = 0;
548
549 Register BaseReg = MI->getOperand(1).getReg();
550 if (BaseReg == ARM::SP &&
551 (Entry.WideOpc == ARM::t2LDMIA_UPD ||
552 Entry.WideOpc == ARM::t2STMDB_UPD)) {
553 Opc = Entry.NarrowOpc2; // tPOP or tPUSH
554 OpNum = 2;
555 } else if (!isARMLowRegister(BaseReg) ||
556 (Entry.WideOpc != ARM::t2LDMIA_UPD &&
557 Entry.WideOpc != ARM::t2STMIA_UPD)) {
558 return false;
559 }
560
561 isLdStMul = true;
562 break;
563 }
564 }
565
566 unsigned OffsetReg = 0;
567 bool OffsetKill = false;
568 bool OffsetInternal = false;
569 if (HasShift) {
570 OffsetReg = MI->getOperand(2).getReg();
571 OffsetKill = MI->getOperand(2).isKill();
572 OffsetInternal = MI->getOperand(2).isInternalRead();
573
574 if (MI->getOperand(3).getImm())
575 // Thumb1 addressing mode doesn't support shift.
576 return false;
577 }
578
579 unsigned OffsetImm = 0;
580 if (HasImmOffset) {
581 OffsetImm = MI->getOperand(2).getImm();
582 unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale;
583
584 if ((OffsetImm & (Scale - 1)) || OffsetImm > MaxOffset)
585 // Make sure the immediate field fits.
586 return false;
587 }
588
589 // Add the 16-bit load / store instruction.
590 DebugLoc dl = MI->getDebugLoc();
591 MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, TII->get(Opc));
592
593 // tSTMIA_UPD takes a defining register operand. We've already checked that
594 // the register is killed, so mark it as dead here.
595 if (Entry.WideOpc == ARM::t2STMIA)
596 MIB.addReg(MI->getOperand(0).getReg(), RegState::Define | RegState::Dead);
597
598 if (!isLdStMul) {
599 MIB.add(MI->getOperand(0));
600 MIB.add(MI->getOperand(1));
601
602 if (HasImmOffset)
603 MIB.addImm(OffsetImm / Scale);
604
605 assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!");
606
607 if (HasOffReg)
608 MIB.addReg(OffsetReg, getKillRegState(OffsetKill) |
609 getInternalReadRegState(OffsetInternal));
610 }
611
612 // Transfer the rest of operands.
613 for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), OpNum))
614 MIB.add(MO);
615
616 // Transfer memoperands.
617 MIB.setMemRefs(MI->memoperands());
618
619 // Transfer MI flags.
620 MIB.setMIFlags(MI->getFlags());
621
622 LLVM_DEBUG(dbgs() << "Converted 32-bit: " << *MI
623 << " to 16-bit: " << *MIB);
624
626 ++NumLdSts;
627 return true;
628}
629
630bool
631Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
632 const ReduceEntry &Entry,
633 bool LiveCPSR, bool IsSelfLoop) {
634 unsigned Opc = MI->getOpcode();
635 if (Opc == ARM::t2ADDri) {
636 // If the source register is SP, try to reduce to tADDrSPi, otherwise
637 // it's a normal reduce.
638 if (MI->getOperand(1).getReg() != ARM::SP) {
639 if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
640 return true;
641 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
642 }
643 // Try to reduce to tADDrSPi.
644 unsigned Imm = MI->getOperand(2).getImm();
645 // The immediate must be in range, the destination register must be a low
646 // reg, the predicate must be "always" and the condition flags must not
647 // be being set.
648 if (Imm & 3 || Imm > 1020)
649 return false;
650 if (!isARMLowRegister(MI->getOperand(0).getReg()))
651 return false;
652 if (MI->getOperand(3).getImm() != ARMCC::AL)
653 return false;
654 const MCInstrDesc &MCID = MI->getDesc();
655 if (MCID.hasOptionalDef() &&
656 MI->getOperand(MCID.getNumOperands()-1).getReg() == ARM::CPSR)
657 return false;
658
659 MachineInstrBuilder MIB =
660 BuildMI(MBB, MI, MI->getDebugLoc(),
661 TII->get(ARM::tADDrSPi))
662 .add(MI->getOperand(0))
663 .add(MI->getOperand(1))
664 .addImm(Imm / 4) // The tADDrSPi has an implied scale by four.
666
667 // Transfer MI flags.
668 MIB.setMIFlags(MI->getFlags());
669
670 LLVM_DEBUG(dbgs() << "Converted 32-bit: " << *MI
671 << " to 16-bit: " << *MIB);
672
674 ++NumNarrows;
675 return true;
676 }
677
678 if (Entry.LowRegs1 && !VerifyLowRegs(MI))
679 return false;
680
681 if (MI->mayLoadOrStore())
682 return ReduceLoadStore(MBB, MI, Entry);
683
684 switch (Opc) {
685 default: break;
686 case ARM::t2ADDSri:
687 case ARM::t2ADDSrr: {
688 Register PredReg;
689 if (getInstrPredicate(*MI, PredReg) == ARMCC::AL) {
690 switch (Opc) {
691 default: break;
692 case ARM::t2ADDSri:
693 if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
694 return true;
695 [[fallthrough]];
696 case ARM::t2ADDSrr:
697 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
698 }
699 }
700 break;
701 }
702 case ARM::t2RSBri:
703 case ARM::t2RSBSri:
704 case ARM::t2SXTB:
705 case ARM::t2SXTH:
706 case ARM::t2UXTB:
707 case ARM::t2UXTH:
708 if (MI->getOperand(2).getImm() == 0)
709 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
710 break;
711 case ARM::t2MOVi16:
712 // Can convert only 'pure' immediate operands, not immediates obtained as
713 // globals' addresses.
714 if (MI->getOperand(1).isImm())
715 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
716 break;
717 case ARM::t2CMPrr: {
718 // Try to reduce to the lo-reg only version first. Why there are two
719 // versions of the instruction is a mystery.
720 // It would be nice to just have two entries in the main table that
721 // are prioritized, but the table assumes a unique entry for each
722 // source insn opcode. So for now, we hack a local entry record to use.
723 static const ReduceEntry NarrowEntry =
724 { ARM::t2CMPrr,ARM::tCMPr, 0, 0, 0, 1, 1,2, 0, 0,1,0 };
725 if (ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR, IsSelfLoop))
726 return true;
727 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
728 }
729 case ARM::t2TEQrr: {
730 Register PredReg;
731 // Can only convert to eors if we're not in an IT block.
732 if (getInstrPredicate(*MI, PredReg) != ARMCC::AL)
733 break;
734 // TODO if Operand 0 is not killed but Operand 1 is, then we could write
735 // to Op1 instead.
736 if (MI->getOperand(0).isKill())
737 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
738 }
739 }
740 return false;
741}
742
743bool
744Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
745 const ReduceEntry &Entry,
746 bool LiveCPSR, bool IsSelfLoop) {
747 if (ReduceLimit2Addr != -1 && ((int)Num2Addrs >= ReduceLimit2Addr))
748 return false;
749
750 if (!OptimizeSize && Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
751 // Don't issue movs with shifter operand for some CPUs unless we
752 // are optimizing for size.
753 return false;
754
755 Register Reg0 = MI->getOperand(0).getReg();
756 Register Reg1 = MI->getOperand(1).getReg();
757 // t2MUL is "special". The tied source operand is second, not first.
758 if (MI->getOpcode() == ARM::t2MUL) {
759 // MULS can be slower than MUL
760 if (!MinimizeSize && STI->avoidMULS())
761 return false;
762 Register Reg2 = MI->getOperand(2).getReg();
763 // Early exit if the regs aren't all low regs.
764 if (!isARMLowRegister(Reg0) || !isARMLowRegister(Reg1)
765 || !isARMLowRegister(Reg2))
766 return false;
767 if (Reg0 != Reg2) {
768 // If the other operand also isn't the same as the destination, we
769 // can't reduce.
770 if (Reg1 != Reg0)
771 return false;
772 // Try to commute the operands to make it a 2-address instruction.
773 MachineInstr *CommutedMI = TII->commuteInstruction(*MI);
774 if (!CommutedMI)
775 return false;
776 }
777 } else if (Reg0 != Reg1) {
778 // Try to commute the operands to make it a 2-address instruction.
779 unsigned CommOpIdx1 = 1;
780 unsigned CommOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;
781 if (!TII->findCommutedOpIndices(*MI, CommOpIdx1, CommOpIdx2) ||
782 MI->getOperand(CommOpIdx2).getReg() != Reg0)
783 return false;
784 MachineInstr *CommutedMI =
785 TII->commuteInstruction(*MI, false, CommOpIdx1, CommOpIdx2);
786 if (!CommutedMI)
787 return false;
788 }
789 if (Entry.LowRegs2 && !isARMLowRegister(Reg0))
790 return false;
791 if (Entry.Imm2Limit) {
792 unsigned Imm = MI->getOperand(2).getImm();
793 unsigned Limit = (1 << Entry.Imm2Limit) - 1;
794 if (Imm > Limit)
795 return false;
796 } else {
797 Register Reg2 = MI->getOperand(2).getReg();
798 if (Entry.LowRegs2 && !isARMLowRegister(Reg2))
799 return false;
800 }
801
802 // Check if it's possible / necessary to transfer the predicate.
803 const MCInstrDesc &NewMCID = TII->get(Entry.NarrowOpc2);
804 Register PredReg;
805 ARMCC::CondCodes Pred = getInstrPredicate(*MI, PredReg);
806 bool SkipPred = false;
807 if (Pred != ARMCC::AL) {
808 if (!NewMCID.isPredicable())
809 // Can't transfer predicate, fail.
810 return false;
811 } else {
812 SkipPred = !NewMCID.isPredicable();
813 }
814
815 bool HasCC = false;
816 bool CCDead = false;
817 const MCInstrDesc &MCID = MI->getDesc();
818 if (MCID.hasOptionalDef()) {
819 unsigned NumOps = MCID.getNumOperands();
820 HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR);
821 if (HasCC && MI->getOperand(NumOps-1).isDead())
822 CCDead = true;
823 }
824 if (!VerifyPredAndCC(MI, Entry, true, Pred, LiveCPSR, HasCC, CCDead))
825 return false;
826
827 // Avoid adding a false dependency on partial flag update by some 16-bit
828 // instructions which has the 's' bit set.
829 if (Entry.PartFlag && NewMCID.hasOptionalDef() && HasCC &&
830 canAddPseudoFlagDep(MI, IsSelfLoop))
831 return false;
832
833 // Add the 16-bit instruction.
834 DebugLoc dl = MI->getDebugLoc();
835 MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, NewMCID);
836 MIB.add(MI->getOperand(0));
837 if (NewMCID.hasOptionalDef())
838 MIB.add(HasCC ? t1CondCodeOp(CCDead) : condCodeOp());
839
840 // Transfer the rest of operands.
841 unsigned NumOps = MCID.getNumOperands();
842 for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) {
843 if (i < NumOps && MCID.operands()[i].isOptionalDef())
844 continue;
845 if (SkipPred && MCID.operands()[i].isPredicate())
846 continue;
847 MIB.add(MI->getOperand(i));
848 }
849
850 // Transfer MI flags.
851 MIB.setMIFlags(MI->getFlags());
852
853 LLVM_DEBUG(dbgs() << "Converted 32-bit: " << *MI
854 << " to 16-bit: " << *MIB);
855
857 ++Num2Addrs;
858 return true;
859}
860
861bool
862Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI,
863 const ReduceEntry &Entry,
864 bool LiveCPSR, bool IsSelfLoop) {
865 if (ReduceLimit != -1 && ((int)NumNarrows >= ReduceLimit))
866 return false;
867
868 if (!OptimizeSize && Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
869 // Don't issue movs with shifter operand for some CPUs unless we
870 // are optimizing for size.
871 return false;
872
873 unsigned Limit = ~0U;
874 if (Entry.Imm1Limit)
875 Limit = (1 << Entry.Imm1Limit) - 1;
876
877 const MCInstrDesc &MCID = MI->getDesc();
878 for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) {
879 if (MCID.operands()[i].isPredicate())
880 continue;
881 const MachineOperand &MO = MI->getOperand(i);
882 if (MO.isReg()) {
883 Register Reg = MO.getReg();
884 if (!Reg || Reg == ARM::CPSR)
885 continue;
886 if (Entry.LowRegs1 && !isARMLowRegister(Reg))
887 return false;
888 } else if (MO.isImm() && !MCID.operands()[i].isPredicate()) {
889 if (((unsigned)MO.getImm()) > Limit)
890 return false;
891 }
892 }
893
894 // Check if it's possible / necessary to transfer the predicate.
895 const MCInstrDesc &NewMCID = TII->get(Entry.NarrowOpc1);
896 Register PredReg;
897 ARMCC::CondCodes Pred = getInstrPredicate(*MI, PredReg);
898 bool SkipPred = false;
899 if (Pred != ARMCC::AL) {
900 if (!NewMCID.isPredicable())
901 // Can't transfer predicate, fail.
902 return false;
903 } else {
904 SkipPred = !NewMCID.isPredicable();
905 }
906
907 bool HasCC = false;
908 bool CCDead = false;
909 if (MCID.hasOptionalDef()) {
910 unsigned NumOps = MCID.getNumOperands();
911 HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR);
912 if (HasCC && MI->getOperand(NumOps-1).isDead())
913 CCDead = true;
914 }
915 if (!VerifyPredAndCC(MI, Entry, false, Pred, LiveCPSR, HasCC, CCDead))
916 return false;
917
918 // Avoid adding a false dependency on partial flag update by some 16-bit
919 // instructions which has the 's' bit set.
920 if (Entry.PartFlag && NewMCID.hasOptionalDef() && HasCC &&
921 canAddPseudoFlagDep(MI, IsSelfLoop))
922 return false;
923
924 // Add the 16-bit instruction.
925 DebugLoc dl = MI->getDebugLoc();
926 MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, NewMCID);
927
928 // TEQ is special in that it doesn't define a register but we're converting
929 // it into an EOR which does. So add the first operand as a def and then
930 // again as a use.
931 if (MCID.getOpcode() == ARM::t2TEQrr) {
932 MIB.add(MI->getOperand(0));
933 MIB->getOperand(0).setIsKill(false);
934 MIB->getOperand(0).setIsDef(true);
935 MIB->getOperand(0).setIsDead(true);
936
937 if (NewMCID.hasOptionalDef())
938 MIB.add(HasCC ? t1CondCodeOp(CCDead) : condCodeOp());
939 MIB.add(MI->getOperand(0));
940 } else {
941 MIB.add(MI->getOperand(0));
942 if (NewMCID.hasOptionalDef())
943 MIB.add(HasCC ? t1CondCodeOp(CCDead) : condCodeOp());
944 }
945
946 // Transfer the rest of operands.
947 unsigned NumOps = MCID.getNumOperands();
948 for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) {
949 if (i < NumOps && MCID.operands()[i].isOptionalDef())
950 continue;
951 if ((MCID.getOpcode() == ARM::t2RSBSri ||
952 MCID.getOpcode() == ARM::t2RSBri ||
953 MCID.getOpcode() == ARM::t2SXTB ||
954 MCID.getOpcode() == ARM::t2SXTH ||
955 MCID.getOpcode() == ARM::t2UXTB ||
956 MCID.getOpcode() == ARM::t2UXTH) && i == 2)
957 // Skip the zero immediate operand, it's now implicit.
958 continue;
959 bool isPred = (i < NumOps && MCID.operands()[i].isPredicate());
960 if (SkipPred && isPred)
961 continue;
962 const MachineOperand &MO = MI->getOperand(i);
963 if (MO.isReg() && MO.isImplicit() && MO.getReg() == ARM::CPSR)
964 // Skip implicit def of CPSR. Either it's modeled as an optional
965 // def now or it's already an implicit def on the new instruction.
966 continue;
967 MIB.add(MO);
968 }
969 if (!MCID.isPredicable() && NewMCID.isPredicable())
970 MIB.add(predOps(ARMCC::AL));
971
972 // Transfer MI flags.
973 MIB.setMIFlags(MI->getFlags());
974
975 LLVM_DEBUG(dbgs() << "Converted 32-bit: " << *MI
976 << " to 16-bit: " << *MIB);
977
979 ++NumNarrows;
980 return true;
981}
982
983static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR, bool &DefCPSR) {
984 bool HasDef = false;
985 for (const MachineOperand &MO : MI.operands()) {
986 if (!MO.isReg() || MO.isUndef() || MO.isUse())
987 continue;
988 if (MO.getReg() != ARM::CPSR)
989 continue;
990
991 DefCPSR = true;
992 if (!MO.isDead())
993 HasDef = true;
994 }
995
996 return HasDef || LiveCPSR;
997}
998
999static bool UpdateCPSRUse(MachineInstr &MI, bool LiveCPSR) {
1000 for (const MachineOperand &MO : MI.operands()) {
1001 if (!MO.isReg() || MO.isUndef() || MO.isDef())
1002 continue;
1003 if (MO.getReg() != ARM::CPSR)
1004 continue;
1005 assert(LiveCPSR && "CPSR liveness tracking is wrong!");
1006 if (MO.isKill()) {
1007 LiveCPSR = false;
1008 break;
1009 }
1010 }
1011
1012 return LiveCPSR;
1013}
1014
1015bool Thumb2SizeReduce::ReduceMI(MachineBasicBlock &MBB, MachineInstr *MI,
1016 bool LiveCPSR, bool IsSelfLoop,
1017 bool SkipPrologueEpilogue) {
1018 unsigned Opcode = MI->getOpcode();
1019 auto OPI = ReduceOpcodeMap.find(Opcode);
1020 if (OPI == ReduceOpcodeMap.end())
1021 return false;
1022 if (SkipPrologueEpilogue && (MI->getFlag(MachineInstr::FrameSetup) ||
1023 MI->getFlag(MachineInstr::FrameDestroy)))
1024 return false;
1025 const ReduceEntry &Entry = ReduceTable[OPI->second];
1026
1027 // Don't attempt normal reductions on "special" cases for now.
1028 if (Entry.Special)
1029 return ReduceSpecial(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
1030
1031 // Try to transform to a 16-bit two-address instruction.
1032 if (Entry.NarrowOpc2 &&
1033 ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
1034 return true;
1035
1036 // Try to transform to a 16-bit non-two-address instruction.
1037 if (Entry.NarrowOpc1 &&
1038 ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
1039 return true;
1040
1041 return false;
1042}
1043
1044bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB,
1045 bool SkipPrologueEpilogue) {
1046 bool Modified = false;
1047
1048 // Yes, CPSR could be livein.
1049 bool LiveCPSR = MBB.isLiveIn(ARM::CPSR);
1050 MachineInstr *BundleMI = nullptr;
1051
1052 CPSRDef = nullptr;
1053 HighLatencyCPSR = false;
1054
1055 // Check predecessors for the latest CPSRDef.
1056 for (auto *Pred : MBB.predecessors()) {
1057 const MBBInfo &PInfo = BlockInfo[Pred->getNumber()];
1058 if (!PInfo.Visited) {
1059 // Since blocks are visited in RPO, this must be a back-edge.
1060 continue;
1061 }
1062 if (PInfo.HighLatencyCPSR) {
1063 HighLatencyCPSR = true;
1064 break;
1065 }
1066 }
1067
1068 // If this BB loops back to itself, conservatively avoid narrowing the
1069 // first instruction that does partial flag update.
1070 bool IsSelfLoop = MBB.isSuccessor(&MBB);
1073 for (; MII != E; MII = NextMII) {
1074 NextMII = std::next(MII);
1075
1076 MachineInstr *MI = &*MII;
1077 if (MI->isBundle()) {
1078 BundleMI = MI;
1079 continue;
1080 }
1081 if (MI->isDebugInstr())
1082 continue;
1083
1084 LiveCPSR = UpdateCPSRUse(*MI, LiveCPSR);
1085
1086 // Does NextMII belong to the same bundle as MI?
1087 bool NextInSameBundle = NextMII != E && NextMII->isBundledWithPred();
1088
1089 if (ReduceMI(MBB, MI, LiveCPSR, IsSelfLoop, SkipPrologueEpilogue)) {
1090 Modified = true;
1091 MachineBasicBlock::instr_iterator I = std::prev(NextMII);
1092 MI = &*I;
1093 // Removing and reinserting the first instruction in a bundle will break
1094 // up the bundle. Fix the bundling if it was broken.
1095 if (NextInSameBundle && !NextMII->isBundledWithPred())
1096 NextMII->bundleWithPred();
1097 }
1098
1099 if (BundleMI && !NextInSameBundle && MI->isInsideBundle()) {
1100 // FIXME: Since post-ra scheduler operates on bundles, the CPSR kill
1101 // marker is only on the BUNDLE instruction. Process the BUNDLE
1102 // instruction as we finish with the bundled instruction to work around
1103 // the inconsistency.
1104 if (BundleMI->killsRegister(ARM::CPSR, /*TRI=*/nullptr))
1105 LiveCPSR = false;
1106 MachineOperand *MO =
1107 BundleMI->findRegisterDefOperand(ARM::CPSR, /*TRI=*/nullptr);
1108 if (MO && !MO->isDead())
1109 LiveCPSR = true;
1110 MO = BundleMI->findRegisterUseOperand(ARM::CPSR, /*TRI=*/nullptr);
1111 if (MO && !MO->isKill())
1112 LiveCPSR = true;
1113 }
1114
1115 bool DefCPSR = false;
1116 LiveCPSR = UpdateCPSRDef(*MI, LiveCPSR, DefCPSR);
1117 if (MI->isCall()) {
1118 // Calls don't really set CPSR.
1119 CPSRDef = nullptr;
1120 HighLatencyCPSR = false;
1121 IsSelfLoop = false;
1122 } else if (DefCPSR) {
1123 // This is the last CPSR defining instruction.
1124 CPSRDef = MI;
1125 HighLatencyCPSR = isHighLatencyCPSR(CPSRDef);
1126 IsSelfLoop = false;
1127 }
1128 }
1129
1130 MBBInfo &Info = BlockInfo[MBB.getNumber()];
1131 Info.HighLatencyCPSR = HighLatencyCPSR;
1132 Info.Visited = true;
1133 return Modified;
1134}
1135
1136bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) {
1137 if (PredicateFtor && !PredicateFtor(MF.getFunction()))
1138 return false;
1139
1140 STI = &MF.getSubtarget<ARMSubtarget>();
1141 if (STI->isThumb1Only() || STI->prefers32BitThumb())
1142 return false;
1143
1144 TII = static_cast<const Thumb2InstrInfo *>(STI->getInstrInfo());
1145
1146 // Optimizing / minimizing size? Minimizing size implies optimizing for size.
1147 OptimizeSize = MF.getFunction().hasOptSize();
1148 MinimizeSize = STI->hasMinSize();
1149
1150 BlockInfo.clear();
1151 BlockInfo.resize(MF.getNumBlockIDs());
1152
1153 // Visit blocks in reverse post-order so LastCPSRDef is known for all
1154 // predecessors.
1155 ReversePostOrderTraversal<MachineFunction*> RPOT(&MF);
1156 bool Modified = false;
1157 bool NeedsWinCFI = MF.getTarget().getMCAsmInfo().usesWindowsCFI() &&
1159 for (MachineBasicBlock *MBB : RPOT)
1160 Modified |= ReduceMBB(*MBB, /*SkipPrologueEpilogue=*/NeedsWinCFI);
1161 return Modified;
1162}
1163
1164/// createThumb2SizeReductionPass - Returns an instance of the Thumb2 size
1165/// reduction pass.
1167 std::function<bool(const Function &)> Ftor) {
1168 return new Thumb2SizeReduce(std::move(Ftor));
1169}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
dot regions Print regions of function to dot true view regions View regions of function(with no function bodies)"
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallSet class.
This file defines the SmallVector class.
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
static cl::opt< int > ReduceLimit("t2-reduce-limit", cl::init(-1), cl::Hidden)
static cl::opt< int > ReduceLimitLdSt("t2-reduce-limit3", cl::init(-1), cl::Hidden)
static cl::opt< int > ReduceLimit2Addr("t2-reduce-limit2", cl::init(-1), cl::Hidden)
static bool HasImplicitCPSRDef(const MCInstrDesc &MCID)
static bool isHighLatencyCPSR(MachineInstr *Def)
static bool UpdateCPSRUse(MachineInstr &MI, bool LiveCPSR)
static bool VerifyLowRegs(MachineInstr *MI)
#define THUMB2_SIZE_REDUCE_NAME
static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR, bool &DefCPSR)
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
bool hasMinSize() const
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
iterator end()
Definition DenseMap.h:141
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Definition Function.h:691
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
Definition Function.h:666
bool usesWindowsCFI() const
Definition MCAsmInfo.h:675
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
bool isPredicable() const
Return true if this instruction has a predicate operand that controls execution.
unsigned getOpcode() const
Return the opcode number for this descriptor.
instr_iterator erase_instr(MachineInstr *I)
Remove an instruction from the instruction list and delete it.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Instructions::iterator instr_iterator
LLVM_ABI bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
iterator_range< pred_iterator > predecessors()
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
mop_range operands()
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr kills the specified register.
MachineOperand * findRegisterUseOperand(Register Reg, const TargetRegisterInfo *TRI, bool isKill=false)
Wrapper for findRegisterUseOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
const MachineOperand & getOperand(unsigned i) const
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
static const unsigned CommuteAnyOperandIndex
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ Entry
Definition COFF.h:862
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:578
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr RegState getKillRegState(bool B)
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
constexpr RegState getInternalReadRegState(bool B)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr RegState getDefRegState(bool B)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
FunctionPass * createThumb2SizeReductionPass(std::function< bool(const Function &)> Ftor=nullptr)
createThumb2SizeReductionPass - Returns an instance of the Thumb2 size reduction pass.
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878