45#define DEBUG_TYPE "thumb2-reduce-size"
46#define THUMB2_SIZE_REDUCE_NAME "Thumb2 instruction size reduce pass"
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");
69 unsigned LowRegs1 : 1;
70 unsigned LowRegs2 : 1;
75 unsigned PartFlag : 1;
77 unsigned AvoidMovs: 1;
80 static const ReduceEntry ReduceTable[] = {
82 { 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 { ARM::t2CMNrr, ARM::tCMN, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
92 { ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0,0,0 },
93 { ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 0,1,0 },
94 { ARM::t2EORrr, 0, ARM::tEOR, 0, 0, 0, 1, 0,0, 1,0,0 },
97 { ARM::t2LSLri, ARM::tLSLri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
98 { ARM::t2LSLrr, 0, ARM::tLSLrr, 0, 0, 0, 1, 0,0, 1,0,1 },
99 { ARM::t2LSRri, ARM::tLSRri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
100 { ARM::t2LSRrr, 0, ARM::tLSRrr, 0, 0, 0, 1, 0,0, 1,0,1 },
101 { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1,0,0 },
102 { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1,1,0 },
104 { ARM::t2MOVr,ARM::tMOVr, 0, 0, 0, 0, 0, 1,0, 0,0,0 },
105 { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 1,0,0 },
106 { ARM::t2MVNr, ARM::tMVN, 0, 0, 0, 1, 0, 0,0, 0,0,0 },
107 { ARM::t2ORRrr, 0, ARM::tORR, 0, 0, 0, 1, 0,0, 1,0,0 },
108 { ARM::t2REV, ARM::tREV, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
109 { ARM::t2REV16, ARM::tREV16, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
110 { ARM::t2REVSH, ARM::tREVSH, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
111 { ARM::t2RORrr, 0, ARM::tROR, 0, 0, 0, 1, 0,0, 1,0,0 },
112 { ARM::t2RSBri, ARM::tRSB, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
113 { ARM::t2RSBSri,ARM::tRSB, 0, 0, 0, 1, 0, 2,0, 0,1,0 },
114 { ARM::t2SBCrr, 0, ARM::tSBC, 0, 0, 0, 1, 0,0, 0,0,0 },
115 { ARM::t2SUBri, ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0,0,0 },
116 { ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0,0,0 },
117 { ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0,0,0 },
118 { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
119 { ARM::t2SXTB, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
120 { ARM::t2SXTH, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
121 { ARM::t2TEQrr, ARM::tEOR, 0, 0, 0, 1, 0, 2,0, 0,1,0 },
122 { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
123 { ARM::t2UXTB, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
124 { ARM::t2UXTH, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
128 { ARM::t2LDRi12,ARM::tLDRi, ARM::tLDRspi, 5, 8, 1, 0, 0,0, 0,1,0 },
129 { ARM::t2LDRs, ARM::tLDRr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
130 { ARM::t2LDRBi12,ARM::tLDRBi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
131 { ARM::t2LDRBs, ARM::tLDRBr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
132 { ARM::t2LDRHi12,ARM::tLDRHi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
133 { ARM::t2LDRHs, ARM::tLDRHr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
134 { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
135 { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
136 { ARM::t2LDR_POST,ARM::tLDMIA_UPD,0, 0, 0, 1, 0, 0,0, 0,1,0 },
137 { ARM::t2STRi12,ARM::tSTRi, ARM::tSTRspi, 5, 8, 1, 0, 0,0, 0,1,0 },
138 { ARM::t2STRs, ARM::tSTRr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
139 { ARM::t2STRBi12,ARM::tSTRBi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
140 { ARM::t2STRBs, ARM::tSTRBr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
141 { ARM::t2STRHi12,ARM::tSTRHi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
142 { ARM::t2STRHs, ARM::tSTRHr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
143 { ARM::t2STR_POST,ARM::tSTMIA_UPD,0, 0, 0, 1, 0, 0,0, 0,1,0 },
145 { ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
146 { ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 0,1,0 },
147 { ARM::t2LDMIA_UPD,ARM::tLDMIA_UPD,ARM::tPOP,0, 0, 1, 1, 1,1, 0,1,0 },
151 { ARM::t2STMIA, ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
152 { ARM::t2STMIA_UPD,ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
153 { ARM::t2STMDB_UPD, 0, ARM::tPUSH, 0, 0, 1, 1, 1,1, 0,1,0 }
160 const Thumb2InstrInfo *TII;
161 const ARMSubtarget *STI;
163 Thumb2SizeReduce(std::function<
bool(
const Function &)> Ftor =
nullptr);
165 bool runOnMachineFunction(MachineFunction &MF)
override;
167 MachineFunctionProperties getRequiredProperties()
const override {
168 return MachineFunctionProperties().setNoVRegs();
171 StringRef getPassName()
const override {
177 DenseMap<unsigned, unsigned> ReduceOpcodeMap;
179 bool canAddPseudoFlagDep(MachineInstr *Use,
bool IsSelfLoop);
181 bool VerifyPredAndCC(MachineInstr *
MI,
const ReduceEntry &Entry,
183 bool LiveCPSR,
bool &HasCC,
bool &CCDead);
185 bool ReduceLoadStore(MachineBasicBlock &
MBB, MachineInstr *
MI,
186 const ReduceEntry &Entry);
188 bool ReduceSpecial(MachineBasicBlock &
MBB, MachineInstr *
MI,
189 const ReduceEntry &Entry,
bool LiveCPSR,
bool IsSelfLoop);
193 bool ReduceTo2Addr(MachineBasicBlock &
MBB, MachineInstr *
MI,
194 const ReduceEntry &Entry,
bool LiveCPSR,
199 bool ReduceToNarrow(MachineBasicBlock &
MBB, MachineInstr *
MI,
200 const ReduceEntry &Entry,
bool LiveCPSR,
204 bool ReduceMI(MachineBasicBlock &
MBB, MachineInstr *
MI,
bool LiveCPSR,
205 bool IsSelfLoop,
bool SkipPrologueEpilogue);
208 bool ReduceMBB(MachineBasicBlock &
MBB,
bool SkipPrologueEpilogue);
214 MachineInstr *CPSRDef;
217 bool HighLatencyCPSR;
221 bool HighLatencyCPSR =
false;
223 bool Visited =
false;
230 std::function<bool(
const Function &)> PredicateFtor;
233 char Thumb2SizeReduce::ID = 0;
242 OptimizeSize = MinimizeSize =
false;
243 for (
unsigned i = 0, e = std::size(ReduceTable); i != e; ++i) {
244 unsigned FromOpc = ReduceTable[i].WideOpc;
245 if (!ReduceOpcodeMap.insert(std::make_pair(FromOpc, i)).second)
256 switch(Def->getOpcode()) {
282Thumb2SizeReduce::canAddPseudoFlagDep(
MachineInstr *
Use,
bool FirstInSelfLoop) {
284 if (MinimizeSize || !STI->avoidCPSRPartialUpdate())
290 return HighLatencyCPSR || FirstInSelfLoop;
292 SmallSet<unsigned, 2> Defs;
293 for (
const MachineOperand &MO : CPSRDef->
operands()) {
294 if (!MO.isReg() || MO.isUndef() || MO.isUse())
297 if (
Reg == 0 ||
Reg == ARM::CPSR)
302 for (
const MachineOperand &MO :
Use->operands()) {
303 if (!MO.isReg() || MO.isUndef() || MO.isDef())
316 if (
Use->getOpcode() == ARM::t2MOVi ||
317 Use->getOpcode() == ARM::t2MOVi16)
325Thumb2SizeReduce::VerifyPredAndCC(MachineInstr *
MI,
const ReduceEntry &Entry,
327 bool LiveCPSR,
bool &HasCC,
bool &CCDead) {
328 if ((is2Addr &&
Entry.PredCC2 == 0) ||
329 (!is2Addr &&
Entry.PredCC1 == 0)) {
348 }
else if ((is2Addr &&
Entry.PredCC2 == 2) ||
349 (!is2Addr &&
Entry.PredCC1 == 2)) {
368 unsigned Opc =
MI->getOpcode();
369 bool isPCOk = (
Opc == ARM::t2LDMIA_RET ||
Opc == ARM::t2LDMIA_UPD);
370 bool isLROk = (
Opc == ARM::t2STMDB_UPD);
371 bool isSPOk = isPCOk || isLROk;
372 for (
unsigned i = 0, e =
MI->getNumOperands(); i != e; ++i) {
377 if (
Reg == 0 ||
Reg == ARM::CPSR)
379 if (isPCOk &&
Reg == ARM::PC)
381 if (isLROk &&
Reg == ARM::LR)
383 if (
Reg == ARM::SP) {
386 if (i == 1 && (
Opc == ARM::t2LDRi12 ||
Opc == ARM::t2STRi12))
397Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &
MBB, MachineInstr *
MI,
398 const ReduceEntry &Entry) {
403 bool HasImmOffset =
false;
404 bool HasShift =
false;
405 bool HasOffReg =
true;
406 bool isLdStMul =
false;
409 uint8_t ImmLimit =
Entry.Imm1Limit;
411 switch (
Entry.WideOpc) {
416 if (
MI->getOperand(1).getReg() == ARM::SP) {
418 ImmLimit =
Entry.Imm2Limit;
447 case ARM::t2LDR_POST:
448 case ARM::t2STR_POST: {
452 if (!
MI->hasOneMemOperand() ||
453 (*
MI->memoperands_begin())->getAlign() <
Align(4))
459 bool IsStore =
Entry.WideOpc == ARM::t2STR_POST;
460 Register Rt =
MI->getOperand(IsStore ? 1 : 0).getReg();
461 Register Rn =
MI->getOperand(IsStore ? 0 : 1).getReg();
462 unsigned Offset =
MI->getOperand(3).getImm();
463 unsigned PredImm =
MI->getOperand(4).getImm();
464 Register PredReg =
MI->getOperand(5).getReg();
474 .
addReg(Rn, RegState::Define)
487 MI->eraseFromBundle();
499 if (MO.getReg() == BaseReg) {
516 if (!
MI->getOperand(0).isKill())
524 if (MO.getReg() == BaseReg)
529 case ARM::t2LDMIA_RET: {
531 if (BaseReg != ARM::SP)
538 case ARM::t2LDMIA_UPD:
539 case ARM::t2STMIA_UPD:
540 case ARM::t2STMDB_UPD: {
544 if (BaseReg == ARM::SP &&
545 (
Entry.WideOpc == ARM::t2LDMIA_UPD ||
546 Entry.WideOpc == ARM::t2STMDB_UPD)) {
550 (
Entry.WideOpc != ARM::t2LDMIA_UPD &&
551 Entry.WideOpc != ARM::t2STMIA_UPD)) {
560 unsigned OffsetReg = 0;
561 bool OffsetKill =
false;
562 bool OffsetInternal =
false;
564 OffsetReg =
MI->getOperand(2).getReg();
565 OffsetKill =
MI->getOperand(2).isKill();
566 OffsetInternal =
MI->getOperand(2).isInternalRead();
568 if (
MI->getOperand(3).getImm())
573 unsigned OffsetImm = 0;
575 OffsetImm =
MI->getOperand(2).getImm();
576 unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale;
578 if ((OffsetImm & (Scale - 1)) || OffsetImm > MaxOffset)
589 if (
Entry.WideOpc == ARM::t2STMIA)
590 MIB.
addReg(
MI->getOperand(0).getReg(), RegState::Define | RegState::Dead);
593 MIB.
add(
MI->getOperand(0));
594 MIB.
add(
MI->getOperand(1));
597 MIB.
addImm(OffsetImm / Scale);
599 assert((!HasShift || OffsetReg) &&
"Invalid so_reg load / store address!");
617 <<
" to 16-bit: " << *MIB);
625Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &
MBB, MachineInstr *
MI,
626 const ReduceEntry &Entry,
627 bool LiveCPSR,
bool IsSelfLoop) {
628 unsigned Opc =
MI->getOpcode();
629 if (
Opc == ARM::t2ADDri) {
632 if (
MI->getOperand(1).getReg() != ARM::SP) {
633 if (ReduceTo2Addr(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
635 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
638 unsigned Imm =
MI->getOperand(2).getImm();
642 if (Imm & 3 || Imm > 1020)
648 const MCInstrDesc &MCID =
MI->getDesc();
653 MachineInstrBuilder MIB =
655 TII->get(ARM::tADDrSPi))
656 .
add(
MI->getOperand(0))
657 .
add(
MI->getOperand(1))
665 <<
" to 16-bit: " << *MIB);
675 if (
MI->mayLoadOrStore())
676 return ReduceLoadStore(
MBB,
MI, Entry);
681 case ARM::t2ADDSrr: {
687 if (ReduceTo2Addr(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
691 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
702 if (
MI->getOperand(2).getImm() == 0)
703 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
708 if (
MI->getOperand(1).isImm())
709 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
717 static const ReduceEntry NarrowEntry =
718 { ARM::t2CMPrr,ARM::tCMPr, 0, 0, 0, 1, 1,2, 0, 0,1,0 };
719 if (ReduceToNarrow(
MBB,
MI, NarrowEntry, LiveCPSR, IsSelfLoop))
721 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
730 if (
MI->getOperand(0).isKill())
731 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
738Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &
MBB, MachineInstr *
MI,
739 const ReduceEntry &Entry,
740 bool LiveCPSR,
bool IsSelfLoop) {
744 if (!OptimizeSize &&
Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
752 if (
MI->getOpcode() == ARM::t2MUL) {
754 if (!MinimizeSize && STI->avoidMULS())
767 MachineInstr *CommutedMI =
TII->commuteInstruction(*
MI);
771 }
else if (Reg0 != Reg1) {
773 unsigned CommOpIdx1 = 1;
775 if (!
TII->findCommutedOpIndices(*
MI, CommOpIdx1, CommOpIdx2) ||
776 MI->getOperand(CommOpIdx2).getReg() != Reg0)
778 MachineInstr *CommutedMI =
779 TII->commuteInstruction(*
MI,
false, CommOpIdx1, CommOpIdx2);
785 if (
Entry.Imm2Limit) {
786 unsigned Imm =
MI->getOperand(2).getImm();
787 unsigned Limit = (1 <<
Entry.Imm2Limit) - 1;
797 const MCInstrDesc &NewMCID =
TII->get(
Entry.NarrowOpc2);
800 bool SkipPred =
false;
811 const MCInstrDesc &MCID =
MI->getDesc();
815 if (HasCC &&
MI->getOperand(
NumOps-1).isDead())
818 if (!VerifyPredAndCC(
MI, Entry,
true, Pred, LiveCPSR, HasCC, CCDead))
824 canAddPseudoFlagDep(
MI, IsSelfLoop))
829 MachineInstrBuilder MIB =
BuildMI(
MBB,
MI, dl, NewMCID);
830 MIB.
add(
MI->getOperand(0));
836 for (
unsigned i = 1, e =
MI->getNumOperands(); i != e; ++i) {
839 if (SkipPred && MCID.
operands()[i].isPredicate())
841 MIB.
add(
MI->getOperand(i));
848 <<
" to 16-bit: " << *MIB);
856Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &
MBB, MachineInstr *
MI,
857 const ReduceEntry &Entry,
858 bool LiveCPSR,
bool IsSelfLoop) {
862 if (!OptimizeSize &&
Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
867 unsigned Limit = ~0
U;
869 Limit = (1 <<
Entry.Imm1Limit) - 1;
871 const MCInstrDesc &MCID =
MI->getDesc();
873 if (MCID.
operands()[i].isPredicate())
875 const MachineOperand &MO =
MI->getOperand(i);
878 if (!
Reg ||
Reg == ARM::CPSR)
882 }
else if (MO.
isImm() && !MCID.
operands()[i].isPredicate()) {
883 if (((
unsigned)MO.
getImm()) > Limit)
889 const MCInstrDesc &NewMCID =
TII->get(
Entry.NarrowOpc1);
892 bool SkipPred =
false;
906 if (HasCC &&
MI->getOperand(
NumOps-1).isDead())
909 if (!VerifyPredAndCC(
MI, Entry,
false, Pred, LiveCPSR, HasCC, CCDead))
915 canAddPseudoFlagDep(
MI, IsSelfLoop))
920 MachineInstrBuilder MIB =
BuildMI(
MBB,
MI, dl, NewMCID);
926 MIB.
add(
MI->getOperand(0));
933 MIB.
add(
MI->getOperand(0));
935 MIB.
add(
MI->getOperand(0));
942 for (
unsigned i = 1, e =
MI->getNumOperands(); i != e; ++i) {
945 if ((MCID.
getOpcode() == ARM::t2RSBSri ||
950 MCID.
getOpcode() == ARM::t2UXTH) && i == 2)
954 if (SkipPred && isPred)
956 const MachineOperand &MO =
MI->getOperand(i);
970 <<
" to 16-bit: " << *MIB);
982 if (MO.
getReg() != ARM::CPSR)
990 return HasDef || LiveCPSR;
997 if (MO.
getReg() != ARM::CPSR)
999 assert(LiveCPSR &&
"CPSR liveness tracking is wrong!");
1009bool Thumb2SizeReduce::ReduceMI(MachineBasicBlock &
MBB, MachineInstr *
MI,
1010 bool LiveCPSR,
bool IsSelfLoop,
1011 bool SkipPrologueEpilogue) {
1012 unsigned Opcode =
MI->getOpcode();
1013 DenseMap<unsigned, unsigned>::iterator OPI = ReduceOpcodeMap.
find(Opcode);
1014 if (OPI == ReduceOpcodeMap.
end())
1019 const ReduceEntry &
Entry = ReduceTable[OPI->second];
1023 return ReduceSpecial(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
1026 if (
Entry.NarrowOpc2 &&
1027 ReduceTo2Addr(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
1031 if (
Entry.NarrowOpc1 &&
1032 ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
1038bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &
MBB,
1039 bool SkipPrologueEpilogue) {
1044 MachineInstr *BundleMI =
nullptr;
1047 HighLatencyCPSR =
false;
1051 const MBBInfo &PInfo = BlockInfo[Pred->getNumber()];
1052 if (!PInfo.Visited) {
1056 if (PInfo.HighLatencyCPSR) {
1057 HighLatencyCPSR =
true;
1067 for (; MII !=
E; MII = NextMII) {
1068 NextMII = std::next(MII);
1070 MachineInstr *
MI = &*MII;
1071 if (
MI->isBundle()) {
1075 if (
MI->isDebugInstr())
1081 bool NextInSameBundle = NextMII !=
E && NextMII->isBundledWithPred();
1083 if (ReduceMI(
MBB,
MI, LiveCPSR, IsSelfLoop, SkipPrologueEpilogue)) {
1089 if (NextInSameBundle && !NextMII->isBundledWithPred())
1090 NextMII->bundleWithPred();
1093 if (BundleMI && !NextInSameBundle &&
MI->isInsideBundle()) {
1100 MachineOperand *MO =
1109 bool DefCPSR =
false;
1114 HighLatencyCPSR =
false;
1116 }
else if (DefCPSR) {
1125 Info.HighLatencyCPSR = HighLatencyCPSR;
1126 Info.Visited =
true;
1130bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) {
1131 if (PredicateFtor && !PredicateFtor(MF.
getFunction()))
1149 ReversePostOrderTraversal<MachineFunction*> RPOT(&MF);
1153 for (MachineBasicBlock *
MBB : RPOT)
1161 std::function<
bool(
const Function &)> Ftor) {
1162 return new Thumb2SizeReduce(std::move(Ftor));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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 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)
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
iterator find(const_arg_type_t< KeyT > Val)
FunctionPass class - This class is used to implement most global optimizations.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
bool usesWindowsCFI() const
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 instr_begin()
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
instr_iterator instr_end()
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...
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.
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.
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.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
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.
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.
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.
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.