46#define DEBUG_TYPE "thumb2-reduce-size"
47#define THUMB2_SIZE_REDUCE_NAME "Thumb2 instruction size reduce pass"
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");
70 unsigned LowRegs1 : 1;
71 unsigned LowRegs2 : 1;
76 unsigned PartFlag : 1;
78 unsigned AvoidMovs: 1;
81 static const ReduceEntry ReduceTable[] = {
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 },
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 },
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 },
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 },
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 },
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 }
161 const Thumb2InstrInfo *TII;
162 const ARMSubtarget *STI;
164 Thumb2SizeReduce(std::function<
bool(
const Function &)> Ftor =
nullptr);
166 bool runOnMachineFunction(MachineFunction &MF)
override;
168 MachineFunctionProperties getRequiredProperties()
const override {
169 return MachineFunctionProperties().setNoVRegs();
172 StringRef getPassName()
const override {
176 void getAnalysisUsage(AnalysisUsage &AU)
const override {
183 DenseMap<unsigned, unsigned> ReduceOpcodeMap;
185 bool canAddPseudoFlagDep(MachineInstr *Use,
bool IsSelfLoop);
187 bool VerifyPredAndCC(MachineInstr *
MI,
const ReduceEntry &Entry,
189 bool LiveCPSR,
bool &HasCC,
bool &CCDead);
191 bool ReduceLoadStore(MachineBasicBlock &
MBB, MachineInstr *
MI,
192 const ReduceEntry &Entry);
194 bool ReduceSpecial(MachineBasicBlock &
MBB, MachineInstr *
MI,
195 const ReduceEntry &Entry,
bool LiveCPSR,
bool IsSelfLoop);
199 bool ReduceTo2Addr(MachineBasicBlock &
MBB, MachineInstr *
MI,
200 const ReduceEntry &Entry,
bool LiveCPSR,
205 bool ReduceToNarrow(MachineBasicBlock &
MBB, MachineInstr *
MI,
206 const ReduceEntry &Entry,
bool LiveCPSR,
210 bool ReduceMI(MachineBasicBlock &
MBB, MachineInstr *
MI,
bool LiveCPSR,
211 bool IsSelfLoop,
bool SkipPrologueEpilogue);
214 bool ReduceMBB(MachineBasicBlock &
MBB,
bool SkipPrologueEpilogue);
220 MachineInstr *CPSRDef;
223 bool HighLatencyCPSR;
227 bool HighLatencyCPSR =
false;
229 bool Visited =
false;
236 std::function<bool(
const Function &)> PredicateFtor;
239 char Thumb2SizeReduce::ID = 0;
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)
262 switch(Def->getOpcode()) {
288Thumb2SizeReduce::canAddPseudoFlagDep(
MachineInstr *
Use,
bool FirstInSelfLoop) {
290 if (MinimizeSize || !STI->avoidCPSRPartialUpdate())
296 return HighLatencyCPSR || FirstInSelfLoop;
298 SmallSet<unsigned, 2> Defs;
299 for (
const MachineOperand &MO : CPSRDef->
operands()) {
300 if (!MO.isReg() || MO.isUndef() || MO.isUse())
303 if (
Reg == 0 ||
Reg == ARM::CPSR)
308 for (
const MachineOperand &MO :
Use->operands()) {
309 if (!MO.isReg() || MO.isUndef() || MO.isDef())
322 if (
Use->getOpcode() == ARM::t2MOVi ||
323 Use->getOpcode() == ARM::t2MOVi16)
331Thumb2SizeReduce::VerifyPredAndCC(MachineInstr *
MI,
const ReduceEntry &Entry,
333 bool LiveCPSR,
bool &HasCC,
bool &CCDead) {
334 if ((is2Addr &&
Entry.PredCC2 == 0) ||
335 (!is2Addr &&
Entry.PredCC1 == 0)) {
354 }
else if ((is2Addr &&
Entry.PredCC2 == 2) ||
355 (!is2Addr &&
Entry.PredCC1 == 2)) {
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) {
383 if (
Reg == 0 ||
Reg == ARM::CPSR)
385 if (isPCOk &&
Reg == ARM::PC)
387 if (isLROk &&
Reg == ARM::LR)
389 if (
Reg == ARM::SP) {
392 if (i == 1 && (
Opc == ARM::t2LDRi12 ||
Opc == ARM::t2STRi12))
403Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &
MBB, MachineInstr *
MI,
404 const ReduceEntry &Entry) {
409 bool HasImmOffset =
false;
410 bool HasShift =
false;
411 bool HasOffReg =
true;
412 bool isLdStMul =
false;
415 uint8_t ImmLimit =
Entry.Imm1Limit;
417 switch (
Entry.WideOpc) {
422 if (
MI->getOperand(1).getReg() == ARM::SP) {
424 ImmLimit =
Entry.Imm2Limit;
453 case ARM::t2LDR_POST:
454 case ARM::t2STR_POST: {
458 if (!
MI->hasOneMemOperand() ||
459 (*
MI->memoperands_begin())->getAlign() <
Align(4))
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();
480 .
addReg(Rn, RegState::Define)
493 MI->eraseFromBundle();
505 if (MO.getReg() == BaseReg) {
522 if (!
MI->getOperand(0).isKill())
530 if (MO.getReg() == BaseReg)
535 case ARM::t2LDMIA_RET: {
537 if (BaseReg != ARM::SP)
544 case ARM::t2LDMIA_UPD:
545 case ARM::t2STMIA_UPD:
546 case ARM::t2STMDB_UPD: {
550 if (BaseReg == ARM::SP &&
551 (
Entry.WideOpc == ARM::t2LDMIA_UPD ||
552 Entry.WideOpc == ARM::t2STMDB_UPD)) {
556 (
Entry.WideOpc != ARM::t2LDMIA_UPD &&
557 Entry.WideOpc != ARM::t2STMIA_UPD)) {
566 unsigned OffsetReg = 0;
567 bool OffsetKill =
false;
568 bool OffsetInternal =
false;
570 OffsetReg =
MI->getOperand(2).getReg();
571 OffsetKill =
MI->getOperand(2).isKill();
572 OffsetInternal =
MI->getOperand(2).isInternalRead();
574 if (
MI->getOperand(3).getImm())
579 unsigned OffsetImm = 0;
581 OffsetImm =
MI->getOperand(2).getImm();
582 unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale;
584 if ((OffsetImm & (Scale - 1)) || OffsetImm > MaxOffset)
595 if (
Entry.WideOpc == ARM::t2STMIA)
596 MIB.
addReg(
MI->getOperand(0).getReg(), RegState::Define | RegState::Dead);
599 MIB.
add(
MI->getOperand(0));
600 MIB.
add(
MI->getOperand(1));
603 MIB.
addImm(OffsetImm / Scale);
605 assert((!HasShift || OffsetReg) &&
"Invalid so_reg load / store address!");
623 <<
" to 16-bit: " << *MIB);
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) {
638 if (
MI->getOperand(1).getReg() != ARM::SP) {
639 if (ReduceTo2Addr(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
641 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
644 unsigned Imm =
MI->getOperand(2).getImm();
648 if (Imm & 3 || Imm > 1020)
654 const MCInstrDesc &MCID =
MI->getDesc();
659 MachineInstrBuilder MIB =
661 TII->get(ARM::tADDrSPi))
662 .
add(
MI->getOperand(0))
663 .
add(
MI->getOperand(1))
671 <<
" to 16-bit: " << *MIB);
681 if (
MI->mayLoadOrStore())
682 return ReduceLoadStore(
MBB,
MI, Entry);
687 case ARM::t2ADDSrr: {
693 if (ReduceTo2Addr(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
697 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
708 if (
MI->getOperand(2).getImm() == 0)
709 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
714 if (
MI->getOperand(1).isImm())
715 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
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))
727 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
736 if (
MI->getOperand(0).isKill())
737 return ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
744Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &
MBB, MachineInstr *
MI,
745 const ReduceEntry &Entry,
746 bool LiveCPSR,
bool IsSelfLoop) {
750 if (!OptimizeSize &&
Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
758 if (
MI->getOpcode() == ARM::t2MUL) {
760 if (!MinimizeSize && STI->avoidMULS())
773 MachineInstr *CommutedMI =
TII->commuteInstruction(*
MI);
777 }
else if (Reg0 != Reg1) {
779 unsigned CommOpIdx1 = 1;
781 if (!
TII->findCommutedOpIndices(*
MI, CommOpIdx1, CommOpIdx2) ||
782 MI->getOperand(CommOpIdx2).getReg() != Reg0)
784 MachineInstr *CommutedMI =
785 TII->commuteInstruction(*
MI,
false, CommOpIdx1, CommOpIdx2);
791 if (
Entry.Imm2Limit) {
792 unsigned Imm =
MI->getOperand(2).getImm();
793 unsigned Limit = (1 <<
Entry.Imm2Limit) - 1;
803 const MCInstrDesc &NewMCID =
TII->get(
Entry.NarrowOpc2);
806 bool SkipPred =
false;
817 const MCInstrDesc &MCID =
MI->getDesc();
821 if (HasCC &&
MI->getOperand(
NumOps-1).isDead())
824 if (!VerifyPredAndCC(
MI, Entry,
true, Pred, LiveCPSR, HasCC, CCDead))
830 canAddPseudoFlagDep(
MI, IsSelfLoop))
835 MachineInstrBuilder MIB =
BuildMI(
MBB,
MI, dl, NewMCID);
836 MIB.
add(
MI->getOperand(0));
842 for (
unsigned i = 1, e =
MI->getNumOperands(); i != e; ++i) {
845 if (SkipPred && MCID.
operands()[i].isPredicate())
847 MIB.
add(
MI->getOperand(i));
854 <<
" to 16-bit: " << *MIB);
862Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &
MBB, MachineInstr *
MI,
863 const ReduceEntry &Entry,
864 bool LiveCPSR,
bool IsSelfLoop) {
868 if (!OptimizeSize &&
Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
873 unsigned Limit = ~0
U;
875 Limit = (1 <<
Entry.Imm1Limit) - 1;
877 const MCInstrDesc &MCID =
MI->getDesc();
879 if (MCID.
operands()[i].isPredicate())
881 const MachineOperand &MO =
MI->getOperand(i);
884 if (!
Reg ||
Reg == ARM::CPSR)
888 }
else if (MO.
isImm() && !MCID.
operands()[i].isPredicate()) {
889 if (((
unsigned)MO.
getImm()) > Limit)
895 const MCInstrDesc &NewMCID =
TII->get(
Entry.NarrowOpc1);
898 bool SkipPred =
false;
912 if (HasCC &&
MI->getOperand(
NumOps-1).isDead())
915 if (!VerifyPredAndCC(
MI, Entry,
false, Pred, LiveCPSR, HasCC, CCDead))
921 canAddPseudoFlagDep(
MI, IsSelfLoop))
926 MachineInstrBuilder MIB =
BuildMI(
MBB,
MI, dl, NewMCID);
932 MIB.
add(
MI->getOperand(0));
939 MIB.
add(
MI->getOperand(0));
941 MIB.
add(
MI->getOperand(0));
948 for (
unsigned i = 1, e =
MI->getNumOperands(); i != e; ++i) {
951 if ((MCID.
getOpcode() == ARM::t2RSBSri ||
956 MCID.
getOpcode() == ARM::t2UXTH) && i == 2)
960 if (SkipPred && isPred)
962 const MachineOperand &MO =
MI->getOperand(i);
976 <<
" to 16-bit: " << *MIB);
988 if (MO.
getReg() != ARM::CPSR)
996 return HasDef || LiveCPSR;
1003 if (MO.
getReg() != ARM::CPSR)
1005 assert(LiveCPSR &&
"CPSR liveness tracking is wrong!");
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())
1025 const ReduceEntry &
Entry = ReduceTable[OPI->second];
1029 return ReduceSpecial(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop);
1032 if (
Entry.NarrowOpc2 &&
1033 ReduceTo2Addr(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
1037 if (
Entry.NarrowOpc1 &&
1038 ReduceToNarrow(
MBB,
MI, Entry, LiveCPSR, IsSelfLoop))
1044bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &
MBB,
1045 bool SkipPrologueEpilogue) {
1050 MachineInstr *BundleMI =
nullptr;
1053 HighLatencyCPSR =
false;
1057 const MBBInfo &PInfo = BlockInfo[Pred->getNumber()];
1058 if (!PInfo.Visited) {
1062 if (PInfo.HighLatencyCPSR) {
1063 HighLatencyCPSR =
true;
1073 for (; MII !=
E; MII = NextMII) {
1074 NextMII = std::next(MII);
1076 MachineInstr *
MI = &*MII;
1077 if (
MI->isBundle()) {
1081 if (
MI->isDebugInstr())
1087 bool NextInSameBundle = NextMII !=
E && NextMII->isBundledWithPred();
1089 if (ReduceMI(
MBB,
MI, LiveCPSR, IsSelfLoop, SkipPrologueEpilogue)) {
1095 if (NextInSameBundle && !NextMII->isBundledWithPred())
1096 NextMII->bundleWithPred();
1099 if (BundleMI && !NextInSameBundle &&
MI->isInsideBundle()) {
1106 MachineOperand *MO =
1115 bool DefCPSR =
false;
1120 HighLatencyCPSR =
false;
1122 }
else if (DefCPSR) {
1131 Info.HighLatencyCPSR = HighLatencyCPSR;
1132 Info.Visited =
true;
1136bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) {
1137 if (PredicateFtor && !PredicateFtor(MF.
getFunction()))
1155 ReversePostOrderTraversal<MachineFunction*> RPOT(&MF);
1159 for (MachineBasicBlock *
MBB : RPOT)
1167 std::function<
bool(
const Function &)> Ftor) {
1168 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
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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...
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.
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.