37 #define DEBUG_TYPE "hexagon-copy-combine"
43 cl::desc(
"Disable merging into combines"));
48 cl::desc(
"Maximum distance between a tfr feeding a store we "
49 "consider the store still to be newifiable"));
62 bool ShouldCombineAggressively;
76 const char *getPassName()
const override {
77 return "Hexagon Copy-To-Combine Pass";
91 unsigned I1DestReg,
unsigned I2DestReg,
112 "Hexagon Copy-To-Combine Pass",
false,
false)
116 bool ShouldCombineAggressively) {
117 switch(MI->getOpcode()) {
118 case Hexagon::A2_tfr: {
124 unsigned DestReg = Op0.
getReg();
125 unsigned SrcReg = Op1.
getReg();
126 return Hexagon::IntRegsRegClass.contains(DestReg) &&
127 Hexagon::IntRegsRegClass.contains(SrcReg);
130 case Hexagon::A2_tfrsi: {
137 unsigned DestReg = Op0.
getReg();
146 return Hexagon::IntRegsRegClass.contains(DestReg) &&
147 (ShouldCombineAggressively || NotExt);
157 template <
unsigned N>
159 if (I->
getOpcode() == Hexagon::TFRI64_V4 ||
172 unsigned HiOpc = HighRegInst->
getOpcode();
173 unsigned LoOpc = LowRegInst->
getOpcode();
176 assert((HiOpc == Hexagon::A2_tfr || HiOpc == Hexagon::A2_tfrsi) &&
177 (LoOpc == Hexagon::A2_tfr || LoOpc == Hexagon::A2_tfrsi) &&
178 "Assume individual instructions are of a combinable type");
181 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
182 isGreaterThanNBitTFRI<6>(LowRegInst))
190 Hexagon::IntRegsRegClass.
contains(Reg));
191 return (Reg - Hexagon::R0) % 2 == 0;
221 bool HexagonCopyToCombine::isSafeToMoveTogether(
MachineInstr *I1,
225 bool &DoInsertAtI1) {
243 if (!ShouldCombineAggressively)
248 unsigned KilledOperand = 0;
250 KilledOperand = I2UseReg;
253 for (;
I != End; ++
I) {
266 if (!KillingInstr && KilledOperand &&
267 I->readsRegister(KilledOperand, TRI))
275 assert(Added &&
"Must successfully update kill flag");
288 if (!ShouldCombineAggressively)
295 unsigned KilledOperand = 0;
316 (!
I->killsRegister(I1UseReg) &&
I->killsRegister(I1UseReg, TRI)))
320 if (I1UseReg &&
I->killsRegister(I1UseReg)) {
321 assert(!KillingInstr &&
"Should only see one killing instruction");
322 KilledOperand = I1UseReg;
332 assert(Added &&
"Must successfully update kill flag");
334 DoInsertAtI1 =
false;
350 for (
unsigned OpdIdx = 0, OpdE = MI->
getNumOperands(); OpdIdx != OpdE;
363 if (!isCombinableInstType(DefInst, TII, ShouldCombineAggressively))
368 unsigned NumInstsToDef = 0;
375 PotentiallyNewifiableTFR.insert(DefInst);
387 unsigned Reg = Op.
getReg();
388 if (Hexagon::DoubleRegsRegClass.
contains(Reg)) {
390 LastDef[*SubRegs] =
MI;
392 }
else if (Hexagon::IntRegsRegClass.
contains(Reg))
402 bool HasChanged =
false;
409 ShouldCombineAggressively =
415 PotentiallyNewifiableTFR.clear();
416 findPotentialNewifiableTFRs(*BI);
425 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(I1))
429 if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))
434 bool DoInsertAtI1 =
false;
438 combine(I1, I2, MI, DoInsertAtI1);
451 bool &DoInsertAtI1) {
458 if (I2->modifiesRegister(I1DestReg, TRI))
462 if (!isCombinableInstType(I2, TII, ShouldCombineAggressively))
466 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(I2))
469 unsigned I2DestReg = I2->getOperand(0).getReg();
473 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
474 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
475 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
476 if ((!IsI1LowReg && !IsI2LowReg) || !
isEvenReg(FirstRegIndex))
487 if (isSafeToMoveTogether(I1, I2, I1DestReg, I2DestReg,
507 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
508 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
511 unsigned DoubleRegDest =
512 TRI->getMatchingSuperReg(LoRegDef, Hexagon::subreg_loreg,
513 &Hexagon::DoubleRegsRegClass);
514 assert(DoubleRegDest != 0 &&
"Expect a valid register");
524 bool IsHiReg = HiOperand.
isReg();
525 bool IsLoReg = LoOperand.
isReg();
529 if (IsHiReg && IsLoReg)
530 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
532 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
534 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
536 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
543 unsigned DoubleDestReg,
551 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
554 .addImm(LoOperand.
getImm());
558 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
559 .addImm(HiOperand.
getImm())
567 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
570 .addImm(LoOperand.
getImm());
574 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
575 .addImm(HiOperand.
getImm())
582 if (HiOperand.
isJTI()) {
583 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
585 .addImm(LoOperand.
getImm());
588 if (LoOperand.
isJTI()) {
589 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
590 .addImm(HiOperand.
getImm())
596 if (HiOperand.
isCPI()) {
597 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
600 .addImm(LoOperand.
getImm());
603 if (LoOperand.
isCPI()) {
604 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
605 .addImm(HiOperand.
getImm())
615 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
616 .addImm(HiOperand.
getImm())
617 .addImm(LoOperand.
getImm());
623 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
624 .addImm(HiOperand.
getImm())
625 .addImm(LoOperand.
getImm());
631 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
632 .addImm(HiOperand.
getImm())
633 .addImm(LoOperand.
getImm());
637 unsigned DoubleDestReg,
640 unsigned LoReg = LoOperand.
getReg();
643 DebugLoc DL = InsertPt->getDebugLoc();
648 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
651 .addReg(LoReg, LoRegKillFlag);
656 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
659 .addReg(LoReg, LoRegKillFlag);
663 if (HiOperand.
isJTI()) {
664 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
666 .addReg(LoReg, LoRegKillFlag);
670 if (HiOperand.
isCPI()) {
671 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
674 .addReg(LoReg, LoRegKillFlag);
679 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
680 .addImm(HiOperand.
getImm())
681 .addReg(LoReg, LoRegKillFlag);
685 unsigned DoubleDestReg,
689 unsigned HiReg = HiOperand.
getReg();
691 DebugLoc DL = InsertPt->getDebugLoc();
696 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
697 .addReg(HiReg, HiRegKillFlag)
704 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
705 .addReg(HiReg, HiRegKillFlag)
711 if (LoOperand.
isJTI()) {
712 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
713 .addReg(HiOperand.
getReg(), HiRegKillFlag)
718 if (LoOperand.
isCPI()) {
719 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
720 .addReg(HiOperand.
getReg(), HiRegKillFlag)
728 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
729 .addReg(HiReg, HiRegKillFlag)
734 unsigned DoubleDestReg,
739 unsigned LoReg = LoOperand.
getReg();
740 unsigned HiReg = HiOperand.
getReg();
742 DebugLoc DL = InsertPt->getDebugLoc();
747 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combinew), DoubleDestReg)
748 .addReg(HiReg, HiRegKillFlag)
749 .
addReg(LoReg, LoRegKillFlag);
753 return new HexagonCopyToCombine();
FunctionPass * createHexagonCopyToCombine()
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
INITIALIZE_PASS(HexagonCopyToCombine,"hexagon-copy-combine","Hexagon Copy-To-Combine Pass", false, false) static bool isCombinableInstType(MachineInstr *MI
const GlobalValue * getGlobal() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
DenseSet - This implements a dense probed hash-table based set.
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isInt< 8 >(int64_t x)
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Reg
All possible values of the reg field in the ModR/M byte.
static bool areCombinableOperations(const TargetRegisterInfo *TRI, MachineInstr *HighRegInst, MachineInstr *LowRegInst)
areCombinableOperations - Returns true if the two instruction can be merge into a combine (ignoring r...
void initializeHexagonCopyToCombinePass(PassRegistry &)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static bool isGreaterThanNBitTFRI(const MachineInstr *I)
const MachineInstrBuilder & addImm(int64_t Val) const
addImm - Add a new immediate operand.
unsigned getNumOperands() const
Access to explicit operands of the instruction.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static cl::opt< unsigned > MaxNumOfInstsBetweenNewValueStoreAndTFR("max-num-inst-between-tfr-and-nv-store", cl::Hidden, cl::init(4), cl::desc("Maximum distance between a tfr feeding a store we ""consider the store still to be newifiable"))
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
unsigned getKillRegState(bool B)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool isDebugValue() const
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
unsigned getTargetFlags() const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
static bool isUnsafeToMoveAcross(MachineInstr *I, unsigned UseReg, unsigned DestReg, const TargetRegisterInfo *TRI)
isUnsafeToMoveAcross - Returns true if it is unsafe to move a copy instruction from UseReg to DestReg...
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
Return the offset from the symbol in this operand.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
static void removeKillInfo(MachineInstr *MI, unsigned RegNotKilled)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
MCSubRegIterator enumerates all sub-registers of Reg.
void setIsKill(bool Val=true)
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
MachineOperand class - Representation of each machine instruction operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
isPhysicalRegister - Return true if the specified register number is in the physical register namespa...
static unsigned UseReg(const MachineOperand &MO)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
static bool isEvenReg(unsigned Reg)
unsigned getReg() const
getReg - Returns the register number.
bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
std::reverse_iterator< iterator > reverse_iterator
BasicBlockListType::iterator iterator
bool addRegisterKilled(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
const BlockAddress * getBlockAddress() const
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
addReg - Add a new virtual register operand...
static cl::opt< bool > IsCombinesDisabled("disable-merge-into-combines", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable merging into combines"))
bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register...
bool mayBeNewStore(const MachineInstr *MI) const