10 #define DEBUG_TYPE "t2-reduce-size"
29 STATISTIC(NumNarrows,
"Number of 32-bit instrs reduced to 16-bit ones");
30 STATISTIC(Num2Addrs,
"Number of 32-bit instrs reduced to 2addr 16-bit ones");
31 STATISTIC(NumLdSts,
"Number of 32-bit load / store reduced to 16-bit ones");
49 unsigned LowRegs1 : 1;
50 unsigned LowRegs2 : 1;
55 unsigned PartFlag : 1;
57 unsigned AvoidMovs: 1;
60 static const ReduceEntry ReduceTable[] = {
62 { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0,0,0 },
63 { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,1,0 },
64 { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0,0,0 },
65 { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 0,1,0 },
66 { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 0,1,0 },
67 { ARM::t2ANDrr, 0, ARM::tAND, 0, 0, 0, 1, 0,0, 1,0,0 },
68 { ARM::t2ASRri, ARM::tASRri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
69 { ARM::t2ASRrr, 0, ARM::tASRrr, 0, 0, 0, 1, 0,0, 1,0,1 },
70 { ARM::t2BICrr, 0, ARM::tBIC, 0, 0, 0, 1, 0,0, 1,0,0 },
73 { ARM::t2CMNzrr, ARM::tCMNz, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
74 { ARM::t2CMPri, ARM::tCMPi8, 0, 8, 0, 1, 0, 2,0, 0,0,0 },
75 { ARM::t2CMPrr, ARM::tCMPhir, 0, 0, 0, 0, 0, 2,0, 0,1,0 },
76 { ARM::t2EORrr, 0, ARM::tEOR, 0, 0, 0, 1, 0,0, 1,0,0 },
79 { ARM::t2LSLri, ARM::tLSLri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
80 { ARM::t2LSLrr, 0, ARM::tLSLrr, 0, 0, 0, 1, 0,0, 1,0,1 },
81 { ARM::t2LSRri, ARM::tLSRri, 0, 5, 0, 1, 0, 0,0, 1,0,1 },
82 { ARM::t2LSRrr, 0, ARM::tLSRrr, 0, 0, 0, 1, 0,0, 1,0,1 },
83 { ARM::t2MOVi, ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1,0,0 },
84 { ARM::t2MOVi16,ARM::tMOVi8, 0, 8, 0, 1, 0, 0,0, 1,1,0 },
86 { ARM::t2MOVr,ARM::tMOVr, 0, 0, 0, 0, 0, 1,0, 0,0,0 },
87 { ARM::t2MUL, 0, ARM::tMUL, 0, 0, 0, 1, 0,0, 1,0,0 },
88 { ARM::t2MVNr, ARM::tMVN, 0, 0, 0, 1, 0, 0,0, 0,0,0 },
89 { ARM::t2ORRrr, 0, ARM::tORR, 0, 0, 0, 1, 0,0, 1,0,0 },
90 { ARM::t2REV, ARM::tREV, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
91 { ARM::t2REV16, ARM::tREV16, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
92 { ARM::t2REVSH, ARM::tREVSH, 0, 0, 0, 1, 0, 1,0, 0,0,0 },
93 { ARM::t2RORrr, 0, ARM::tROR, 0, 0, 0, 1, 0,0, 1,0,0 },
94 { ARM::t2RSBri, ARM::tRSB, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
95 { ARM::t2RSBSri,ARM::tRSB, 0, 0, 0, 1, 0, 2,0, 0,1,0 },
96 { ARM::t2SBCrr, 0, ARM::tSBC, 0, 0, 0, 1, 0,0, 0,0,0 },
97 { ARM::t2SUBri, ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0,0,0 },
98 { ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0,0,0 },
99 { ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0,0,0 },
100 { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
101 { ARM::t2SXTB, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
102 { ARM::t2SXTH, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
103 { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0,0,0 },
104 { ARM::t2UXTB, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
105 { ARM::t2UXTH, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 },
109 { ARM::t2LDRi12,ARM::tLDRi, ARM::tLDRspi, 5, 8, 1, 0, 0,0, 0,1,0 },
110 { ARM::t2LDRs, ARM::tLDRr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
111 { ARM::t2LDRBi12,ARM::tLDRBi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
112 { ARM::t2LDRBs, ARM::tLDRBr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
113 { ARM::t2LDRHi12,ARM::tLDRHi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
114 { ARM::t2LDRHs, ARM::tLDRHr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
115 { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
116 { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
117 { ARM::t2STRi12,ARM::tSTRi, ARM::tSTRspi, 5, 8, 1, 0, 0,0, 0,1,0 },
118 { ARM::t2STRs, ARM::tSTRr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
119 { ARM::t2STRBi12,ARM::tSTRBi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
120 { ARM::t2STRBs, ARM::tSTRBr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
121 { ARM::t2STRHi12,ARM::tSTRHi, 0, 5, 0, 1, 0, 0,0, 0,1,0 },
122 { ARM::t2STRHs, ARM::tSTRHr, 0, 0, 0, 1, 0, 0,0, 0,1,0 },
124 { ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
125 { ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 0,1,0 },
126 { ARM::t2LDMIA_UPD,ARM::tLDMIA_UPD,ARM::tPOP,0, 0, 1, 1, 1,1, 0,1,0 },
128 { ARM::t2STMIA_UPD,ARM::tSTMIA_UPD, 0, 0, 0, 1, 1, 1,1, 0,1,0 },
129 { ARM::t2STMDB_UPD, 0, ARM::tPUSH, 0, 0, 1, 1, 1,1, 0,1,0 }
142 virtual const char *getPassName()
const {
143 return "Thumb2 instruction size reduction pass";
154 bool LiveCPSR,
bool &HasCC,
bool &CCDead);
157 const ReduceEntry &Entry);
160 const ReduceEntry &Entry,
bool LiveCPSR,
bool IsSelfLoop);
165 const ReduceEntry &Entry,
bool LiveCPSR,
171 const ReduceEntry &Entry,
bool LiveCPSR,
176 bool LiveCPSR,
bool IsSelfLoop);
188 bool HighLatencyCPSR;
192 bool HighLatencyCPSR;
196 MBBInfo() : HighLatencyCPSR(
false), Visited(
false) {}
205 OptimizeSize = MinimizeSize =
false;
206 for (
unsigned i = 0, e =
array_lengthof(ReduceTable); i != e; ++i) {
207 unsigned FromOpc = ReduceTable[i].WideOpc;
208 if (!ReduceOpcodeMap.insert(std::make_pair(FromOpc, i)).second)
209 assert(
false &&
"Duplicated entries?");
215 if (*Regs == ARM::CPSR)
248 Thumb2SizeReduce::canAddPseudoFlagDep(
MachineInstr *
Use,
bool FirstInSelfLoop) {
250 if (MinimizeSize || !STI->avoidCPSRPartialUpdate())
256 return HighLatencyCPSR || FirstInSelfLoop;
259 for (
unsigned i = 0, e = CPSRDef->getNumOperands(); i != e; ++i) {
264 if (Reg == 0 || Reg == ARM::CPSR)
273 unsigned Reg = MO.
getReg();
293 Thumb2SizeReduce::VerifyPredAndCC(
MachineInstr *
MI,
const ReduceEntry &Entry,
295 bool LiveCPSR,
bool &HasCC,
bool &CCDead) {
296 if ((is2Addr && Entry.PredCC2 == 0) ||
297 (!is2Addr && Entry.PredCC1 == 0)) {
316 }
else if ((is2Addr && Entry.PredCC2 == 2) ||
317 (!is2Addr && Entry.PredCC1 == 2)) {
337 bool isPCOk = (Opc == ARM::t2LDMIA_RET || Opc == ARM::t2LDMIA ||
338 Opc == ARM::t2LDMDB || Opc == ARM::t2LDMIA_UPD ||
339 Opc == ARM::t2LDMDB_UPD);
340 bool isLROk = (Opc == ARM::t2STMIA_UPD || Opc == ARM::t2STMDB_UPD);
341 bool isSPOk = isPCOk || isLROk;
346 unsigned Reg = MO.
getReg();
347 if (Reg == 0 || Reg == ARM::CPSR)
349 if (isPCOk && Reg == ARM::PC)
351 if (isLROk && Reg == ARM::LR)
353 if (Reg == ARM::SP) {
356 if (i == 1 && (Opc == ARM::t2LDRi12 || Opc == ARM::t2STRi12))
368 const ReduceEntry &Entry) {
373 bool HasImmOffset =
false;
374 bool HasShift =
false;
375 bool HasOffReg =
true;
376 bool isLdStMul =
false;
377 unsigned Opc = Entry.NarrowOpc1;
379 uint8_t ImmLimit = Entry.Imm1Limit;
381 switch (Entry.WideOpc) {
387 Opc = Entry.NarrowOpc2;
388 ImmLimit = Entry.Imm2Limit;
441 case ARM::t2LDMIA_RET: {
443 if (BaseReg != ARM::SP)
445 Opc = Entry.NarrowOpc2;
450 case ARM::t2LDMIA_UPD:
451 case ARM::t2LDMDB_UPD:
452 case ARM::t2STMIA_UPD:
453 case ARM::t2STMDB_UPD: {
457 if (BaseReg == ARM::SP &&
458 (Entry.WideOpc == ARM::t2LDMIA_UPD ||
459 Entry.WideOpc == ARM::t2STMDB_UPD)) {
460 Opc = Entry.NarrowOpc2;
463 (Entry.WideOpc != ARM::t2LDMIA_UPD &&
464 Entry.WideOpc != ARM::t2STMIA_UPD)) {
473 unsigned OffsetReg = 0;
474 bool OffsetKill =
false;
484 unsigned OffsetImm = 0;
487 unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale;
489 if ((OffsetImm & (Scale - 1)) || OffsetImm > MaxOffset)
502 MIB.
addImm(OffsetImm / Scale);
504 assert((!HasShift || OffsetReg) &&
"Invalid so_reg load / store address!");
520 DEBUG(
errs() <<
"Converted 32-bit: " << *MI <<
" to 16-bit: " << *MIB);
529 const ReduceEntry &Entry,
530 bool LiveCPSR,
bool IsSelfLoop) {
532 if (Opc == ARM::t2ADDri) {
536 if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
538 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
545 if (Imm & 3 || Imm > 1020)
557 TII->get(ARM::tADDrSPi))
566 DEBUG(
errs() <<
"Converted 32-bit: " << *MI <<
" to 16-bit: " <<*MIB);
577 return ReduceLoadStore(MBB, MI, Entry);
582 case ARM::t2ADDSrr: {
583 unsigned PredReg = 0;
587 case ARM::t2ADDSri: {
588 if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
593 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
605 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
611 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
619 static const ReduceEntry NarrowEntry =
620 { ARM::t2CMPrr,ARM::tCMPr, 0, 0, 0, 1, 1,2, 0, 0,1,0 };
621 if (ReduceToNarrow(MBB, MI, NarrowEntry, LiveCPSR, IsSelfLoop))
623 return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
631 const ReduceEntry &Entry,
632 bool LiveCPSR,
bool IsSelfLoop) {
637 if (!MinimizeSize && !OptimizeSize && Entry.AvoidMovs &&
638 STI->avoidMOVsShifterOperand())
662 }
else if (Reg0 != Reg1) {
664 unsigned CommOpIdx1, CommOpIdx2;
665 if (!
TII->findCommutedOpIndices(MI, CommOpIdx1, CommOpIdx2) ||
674 if (Entry.Imm2Limit) {
676 unsigned Limit = (1 << Entry.Imm2Limit) - 1;
687 unsigned PredReg = 0;
689 bool SkipPred =
false;
707 if (!VerifyPredAndCC(MI, Entry,
true, Pred, LiveCPSR, HasCC, CCDead))
713 canAddPseudoFlagDep(MI, IsSelfLoop))
740 DEBUG(
errs() <<
"Converted 32-bit: " << *MI <<
" to 16-bit: " << *MIB);
749 const ReduceEntry &Entry,
750 bool LiveCPSR,
bool IsSelfLoop) {
754 if (!MinimizeSize && !OptimizeSize && Entry.AvoidMovs &&
755 STI->avoidMOVsShifterOperand())
760 unsigned Limit = ~0U;
762 Limit = (1 << Entry.Imm1Limit) - 1;
770 unsigned Reg = MO.
getReg();
771 if (!Reg || Reg == ARM::CPSR)
775 }
else if (MO.
isImm() &&
777 if (((
unsigned)MO.
getImm()) > Limit)
784 unsigned PredReg = 0;
786 bool SkipPred =
false;
803 if (!VerifyPredAndCC(MI, Entry,
false, Pred, LiveCPSR, HasCC, CCDead))
809 canAddPseudoFlagDep(MI, IsSelfLoop))
828 if ((MCID.
getOpcode() == ARM::t2RSBSri ||
833 MCID.
getOpcode() == ARM::t2UXTH) && i == 2)
837 if (SkipPred && isPred)
852 DEBUG(
errs() <<
"Converted 32-bit: " << *MI <<
" to 16-bit: " << *MIB);
865 if (MO.
getReg() != ARM::CPSR)
873 return HasDef || LiveCPSR;
881 if (MO.
getReg() != ARM::CPSR)
883 assert(LiveCPSR &&
"CPSR liveness tracking is wrong!");
894 bool LiveCPSR,
bool IsSelfLoop) {
897 if (OPI == ReduceOpcodeMap.
end())
899 const ReduceEntry &Entry = ReduceTable[OPI->second];
903 return ReduceSpecial(MBB, MI, Entry, LiveCPSR, IsSelfLoop);
906 if (Entry.NarrowOpc2 &&
907 ReduceTo2Addr(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
911 if (Entry.NarrowOpc1 &&
912 ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop))
919 bool Modified =
false;
922 bool LiveCPSR = MBB.
isLiveIn(ARM::CPSR);
926 HighLatencyCPSR =
false;
931 const MBBInfo &PInfo = BlockInfo[(*I)->getNumber()];
932 if (!PInfo.Visited) {
936 if (PInfo.HighLatencyCPSR) {
937 HighLatencyCPSR =
true;
947 for (; MII != E; MII = NextMII) {
961 bool NextInSameBundle = NextMII != E && NextMII->isBundledWithPred();
963 if (ReduceMI(MBB, MI, LiveCPSR, IsSelfLoop)) {
969 if (NextInSameBundle && !NextMII->isBundledWithPred())
970 NextMII->bundleWithPred();
985 bool DefCPSR =
false;
990 HighLatencyCPSR =
false;
992 }
else if (DefCPSR) {
1000 MBBInfo &Info = BlockInfo[MBB.
getNumber()];
1001 Info.HighLatencyCPSR = HighLatencyCPSR;
1002 Info.Visited =
true;
1013 OptimizeSize = FnAttrs.
hasAttribute(AttributeSet::FunctionIndex,
1014 Attribute::OptimizeForSize);
1015 MinimizeSize = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
1016 Attribute::MinSize);
1024 bool Modified =
false;
1026 I = RPOT.begin(), E = RPOT.end(); I != E; ++
I)
1027 Modified |= ReduceMBB(**I);
1034 return new Thumb2SizeReduce();
static bool VerifyLowRegs(MachineInstr *MI)
bool isInsideBundle() const
FunctionPass * createThumb2SizeReductionPass()
const uint16_t * getImplicitDefs() const
instr_iterator instr_begin()
instr_iterator instr_end()
STATISTIC(NumNarrows,"Number of 32-bit instrs reduced to 16-bit ones")
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g. ARM instructions which can set condition cod...
bool mayStore(QueryType Type=AnyInBundle) const
const MCInstrDesc & getDesc() const
const Function * getFunction() const
static cl::opt< int > ReduceLimit2Addr("t2-reduce-limit2", cl::init(-1), cl::Hidden)
Instructions::iterator instr_iterator
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
static const MachineInstrBuilder & AddNoT1CC(const MachineInstrBuilder &MIB)
static const MachineInstrBuilder & AddDefaultPred(const MachineInstrBuilder &MIB)
unsigned getNumBlockIDs() const
const HexagonInstrInfo * TII
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool mayLoad(QueryType Type=AnyInBundle) const
ID
LLVM Calling Convention Representation.
const MachineInstrBuilder & addImm(int64_t Val) const
unsigned getNumOperands() const
bool isPredicable() const
Return true if this instruction has a predicate operand that controls execution. It may be set to 'al...
size_t array_lengthof(T(&)[N])
Find the length of an array.
std::vector< MachineBasicBlock * >::iterator pred_iterator
unsigned getKillRegState(bool B)
bool isDebugValue() const
mmo_iterator memoperands_end() const
MachineOperand * findRegisterDefOperand(unsigned Reg, bool isDead=false, const TargetRegisterInfo *TRI=NULL)
initializer< Ty > init(const Ty &Val)
instr_iterator erase_instr(MachineInstr *I)
bool isOptionalDef() const
ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg)
const MachineOperand & getOperand(unsigned i) const
ItTy next(ItTy it, Dist n)
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
pred_iterator pred_begin()
static bool UpdateCPSRUse(MachineInstr &MI, bool LiveCPSR)
std::vector< NodeType * >::reverse_iterator rpo_iterator
unsigned getOpcode() const
Return the opcode number for this descriptor.
virtual const TargetInstrInfo * getInstrInfo() const
const STC & getSubtarget() const
static cl::opt< int > ReduceLimit("t2-reduce-limit", cl::init(-1), cl::Hidden)
bool isSuccessor(const MachineBasicBlock *MBB) const
bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI=NULL) const
static cl::opt< int > ReduceLimitLdSt("t2-reduce-limit3", cl::init(-1), cl::Hidden)
static bool HasImplicitCPSRDef(const MCInstrDesc &MCID)
AttributeSet getAttributes() const
Return the attribute list for this Function.
static bool isHighLatencyCPSR(MachineInstr *Def)
static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR, bool &DefCPSR)
bool count(const T &V) const
count - Return true if the element is in the set.
static bool isARMLowRegister(unsigned Reg)
bool isLiveIn(unsigned Reg) const
bool isCall(QueryType Type=AnyInBundle) const
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
uint8_t getFlags() const
getFlags - Return the MI flags bitvector.
const TargetMachine & getTarget() const
unsigned getReg() const
getReg - Returns the register number.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction. Note that variadic (isVari...
const MCOperandInfo * OpInfo
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
ItTy prior(ItTy it, Dist n)
iterator find(const KeyT &Val)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd)
DebugLoc getDebugLoc() const
static const MachineInstrBuilder & AddDefaultT1CC(const MachineInstrBuilder &MIB, bool isDead=false)
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.