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