34#define DEBUG_TYPE "hexagon-copy-combine"
39 cl::desc(
"Disable merging into combines"));
43 cl::desc(
"Disable generation of const64"));
48 cl::desc(
"Maximum distance between a tfr feeding a store we "
49 "consider the store still to be newifiable"));
67 void getAnalysisUsage(AnalysisUsage &AU)
const override {
71 StringRef getPassName()
const override {
72 return "Hexagon Copy-To-Combine Pass";
75 bool runOnMachineFunction(MachineFunction &Fn)
override;
77 MachineFunctionProperties getRequiredProperties()
const override {
78 return MachineFunctionProperties().setNoVRegs();
82 MachineInstr *findPairable(MachineInstr &I1,
bool &DoInsertAtI1,
85 void findPotentialNewifiableTFRs(MachineBasicBlock &);
87 void combine(MachineInstr &I1, MachineInstr &I2,
91 bool isSafeToMoveTogether(MachineInstr &I1, MachineInstr &I2,
92 unsigned I1DestReg,
unsigned I2DestReg,
96 MachineOperand &HiOperand, MachineOperand &LoOperand);
99 MachineOperand &HiOperand, MachineOperand &LoOperand);
102 MachineOperand &HiOperand, MachineOperand &LoOperand);
105 MachineOperand &HiOperand, MachineOperand &LoOperand);
108 MachineOperand &HiOperand, MachineOperand &LoOperand);
113char HexagonCopyToCombine::ID = 0;
116 "Hexagon Copy-To-Combine Pass",
false,
false)
120 switch (
MI.getOpcode()) {
121 case Hexagon::A2_tfr: {
123 const MachineOperand &Op0 = MI.getOperand(0);
124 const MachineOperand &Op1 = MI.getOperand(1);
125 assert(Op0.isReg() && Op1.isReg());
127 Register DestReg = Op0.getReg();
128 Register SrcReg = Op1.getReg();
129 return Hexagon::IntRegsRegClass.contains(DestReg) &&
130 Hexagon::IntRegsRegClass.contains(SrcReg);
133 case Hexagon::A2_tfrsi: {
136 const MachineOperand &Op0 = MI.getOperand(0);
137 const MachineOperand &Op1 = MI.getOperand(1);
140 Register DestReg = Op0.getReg();
144 if (!Op1.isImm() && Op1.getTargetFlags() != HexagonII::MO_NO_FLAG)
148 bool NotExt = Op1.isImm() && isInt<8>(Op1.getImm());
149 return Hexagon::IntRegsRegClass.contains(DestReg) &&
150 (ShouldCombineAggressively || NotExt);
153 case Hexagon::V6_vassign:
164 if (
I.getOpcode() == Hexagon::TFRI64_V4 ||
165 I.getOpcode() == Hexagon::A2_tfrsi) {
177 unsigned HiOpc = HighRegInst.
getOpcode();
180 auto verifyOpc = [](
unsigned Opc) ->
void {
182 case Hexagon::A2_tfr:
183 case Hexagon::A2_tfrsi:
184 case Hexagon::V6_vassign:
193 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
194 return HiOpc == LoOpc;
222 return (
Reg - Hexagon::R0) % 2 == 0;
224 return (
Reg - Hexagon::V0) % 2 == 0;
230 if (
Op.isReg() &&
Op.getReg() == RegNotKilled &&
Op.isKill())
240 MI.modifiesRegister(DestReg,
TRI) ||
MI.readsRegister(DestReg,
TRI) ||
241 MI.hasUnmodeledSideEffects() ||
MI.isInlineAsm() ||
242 MI.isMetaInstruction();
251bool HexagonCopyToCombine::isSafeToMoveTogether(
MachineInstr &I1,
255 bool &DoInsertAtI1) {
260 if (I2UseReg &&
I1.modifiesRegister(I2UseReg,
TRI))
274 End = ++
I1.getIterator().getReverse();
278 unsigned KilledOperand = 0;
280 KilledOperand = I2UseReg;
281 MachineInstr *KillingInstr =
nullptr;
283 for (;
I != End; ++
I) {
290 if (
I->isDebugInstr())
299 if (!KillingInstr && KilledOperand &&
300 I->readsRegister(KilledOperand,
TRI))
308 assert(Added &&
"Must successfully update kill flag");
327 MachineInstr *KillingInstr =
nullptr;
328 unsigned KilledOperand = 0;
331 MachineInstr &
MI = *
I;
348 if (
MI.isDebugInstr()) {
349 if (
MI.readsRegister(I1DestReg,
TRI))
356 (!
MI.killsRegister(I1UseReg,
nullptr) &&
357 MI.killsRegister(I1UseReg,
TRI)))
361 if (I1UseReg &&
MI.killsRegister(I1UseReg,
nullptr)) {
362 assert(!KillingInstr &&
"Should only see one killing instruction");
363 KilledOperand = I1UseReg;
371 bool Added =
I1.addRegisterKilled(KilledOperand,
TRI);
373 assert(Added &&
"Must successfully update kill flag");
375 DoInsertAtI1 =
false;
384HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {
385 DenseMap<unsigned, MachineInstr *> LastDef;
386 for (MachineInstr &
MI : BB) {
387 if (
MI.isDebugInstr())
393 for (
const MachineOperand &
Op :
MI.operands()) {
395 if (!
Op.isReg() || !
Op.isUse() || !
Op.getReg())
400 MachineInstr *DefInst = LastDef[
Reg];
409 unsigned NumInstsToDef = 0;
410 while (&*It != &
MI) {
411 if (!It->isDebugInstr())
419 PotentiallyNewifiableTFR.
insert(DefInst);
427 for (MachineOperand &
Op :
MI.operands()) {
429 if (!
Op.isDef() || !
Op.getReg())
437 }
else if (
Op.isRegMask()) {
438 for (
unsigned Reg : Hexagon::IntRegsRegClass)
439 if (
Op.clobbersPhysReg(
Reg))
446bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {
452 bool HasChanged =
false;
471 for (MachineBasicBlock &
MBB : MF) {
472 PotentiallyNewifiableTFR.
clear();
473 findPotentialNewifiableTFRs(
MBB);
478 MachineInstr &
I1 = *
MI++;
480 if (
I1.isDebugInstr())
496 bool DoInsertAtI1 =
false;
498 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
501 combine(I1, *I2,
MI, DoInsertAtI1, OptForSize);
513MachineInstr *HexagonCopyToCombine::findPairable(MachineInstr &I1,
517 while (I2 !=
I1.getParent()->end() && I2->isDebugInstr())
520 Register I1DestReg =
I1.getOperand(0).getReg();
525 if (I2->modifiesRegister(I1DestReg,
TRI))
536 Register I2DestReg = I2->getOperand(0).getReg();
540 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
541 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
542 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
543 if ((!IsI1LowReg && !IsI2LowReg) || !
isEvenReg(FirstRegIndex))
553 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
562void HexagonCopyToCombine::combine(MachineInstr &I1, MachineInstr &I2,
564 bool DoInsertAtI1,
bool OptForSize) {
571 Register I1DestReg =
I1.getOperand(0).getReg();
573 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
574 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
577 const TargetRegisterClass *SuperRC =
nullptr;
578 if (Hexagon::IntRegsRegClass.
contains(LoRegDef)) {
579 SuperRC = &Hexagon::DoubleRegsRegClass;
580 SubLo = Hexagon::isub_lo;
581 }
else if (Hexagon::HvxVRRegClass.
contains(LoRegDef)) {
583 SuperRC = &Hexagon::HvxWRRegClass;
584 SubLo = Hexagon::vsub_lo;
589 MCRegister DoubleRegDest =
TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
590 assert(DoubleRegDest.
isValid() &&
"Expect a valid register");
593 MachineOperand &LoOperand = IsI1Loreg ?
I1.getOperand(1) : I2.
getOperand(1);
594 MachineOperand &HiOperand = IsI1Loreg ? I2.
getOperand(1) :
I1.getOperand(1);
597 bool IsHiReg = HiOperand.
isReg();
598 bool IsLoReg = LoOperand.
isReg();
601 bool IsC64 = OptForSize && LoOperand.
isImm() && HiOperand.
isImm() &&
606 if (IsHiReg && IsLoReg)
607 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
609 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
611 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
613 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
615 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
619 if (!DoInsertAtI1 && DbgMItoMove.
size() != 0) {
621 MachineBasicBlock *BB = InsertPt->getParent();
622 for (
auto *NewMI : DbgMItoMove) {
627 BB->
splice(InsertPt, BB, NewMI);
631 I1.eraseFromParent();
636 unsigned DoubleDestReg,
637 MachineOperand &HiOperand,
638 MachineOperand &LoOperand) {
642 MachineBasicBlock *BB = InsertPt->getParent();
644 "Both operands must be immediate");
646 int64_t
V = HiOperand.
getImm();
647 V = (
V << 32) | (0x0ffffffffLL & LoOperand.
getImm());
648 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::CONST64), DoubleDestReg)
653 unsigned DoubleDestReg,
654 MachineOperand &HiOperand,
655 MachineOperand &LoOperand) {
657 MachineBasicBlock *BB = InsertPt->getParent();
661 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
668 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
677 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
684 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
692 if (HiOperand.
isJTI()) {
693 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
698 if (LoOperand.
isJTI()) {
699 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
706 if (HiOperand.
isCPI()) {
707 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
713 if (LoOperand.
isCPI()) {
714 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
725 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
733 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
741 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
747 unsigned DoubleDestReg,
748 MachineOperand &HiOperand,
749 MachineOperand &LoOperand) {
754 MachineBasicBlock *BB = InsertPt->getParent();
758 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
761 .
addReg(LoReg, LoRegKillFlag);
766 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
769 .
addReg(LoReg, LoRegKillFlag);
773 if (HiOperand.
isJTI()) {
774 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
776 .
addReg(LoReg, LoRegKillFlag);
780 if (HiOperand.
isCPI()) {
781 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
784 .
addReg(LoReg, LoRegKillFlag);
789 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
791 .
addReg(LoReg, LoRegKillFlag);
795 unsigned DoubleDestReg,
796 MachineOperand &HiOperand,
797 MachineOperand &LoOperand) {
802 MachineBasicBlock *BB = InsertPt->getParent();
806 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
807 .
addReg(HiReg, HiRegKillFlag)
814 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
815 .
addReg(HiReg, HiRegKillFlag)
821 if (LoOperand.
isJTI()) {
822 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
828 if (LoOperand.
isCPI()) {
829 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
838 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
839 .
addReg(HiReg, HiRegKillFlag)
844 unsigned DoubleDestReg,
845 MachineOperand &HiOperand,
846 MachineOperand &LoOperand) {
853 MachineBasicBlock *BB = InsertPt->getParent();
858 if (Hexagon::DoubleRegsRegClass.
contains(DoubleDestReg)) {
859 NewOpc = Hexagon::A2_combinew;
860 }
else if (Hexagon::HvxWRRegClass.
contains(DoubleDestReg)) {
862 NewOpc = Hexagon::V6_vcombine;
866 BuildMI(*BB, InsertPt,
DL,
TII->get(NewOpc), DoubleDestReg)
867 .
addReg(HiReg, HiRegKillFlag)
868 .
addReg(LoReg, LoRegKillFlag);
872 return new HexagonCopyToCombine();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
static cl::opt< bool > IsConst64Disabled("disable-const64", cl::Hidden, cl::desc("Disable generation of const64"))
static bool isEvenReg(unsigned Reg)
static bool isUnsafeToMoveAcross(MachineInstr &MI, unsigned UseReg, unsigned DestReg, const TargetRegisterInfo *TRI)
Returns true if it is unsafe to move a copy instruction from UseReg to DestReg over the instruction M...
static cl::opt< bool > IsCombinesDisabled("disable-merge-into-combines", cl::Hidden, cl::desc("Disable merging into combines"))
const HexagonInstrInfo bool ShouldCombineAggressively
static bool areCombinableOperations(const TargetRegisterInfo *TRI, MachineInstr &HighRegInst, MachineInstr &LowRegInst, bool AllowC64)
areCombinableOperations - Returns true if the two instruction can be merge into a combine (ignoring r...
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"))
static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled)
static bool isGreaterThanNBitTFRI(const MachineInstr &I)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Implements a dense probed hash-table based set.
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 mayBeNewStore(const MachineInstr &MI) const
const HexagonInstrInfo * getInstrInfo() const override
const HexagonRegisterInfo * getRegisterInfo() const override
constexpr bool isValid() const
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
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.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr kills the specified register.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
int64_t getOffset() const
Return the offset from the symbol in this operand.
Wrapper class representing virtual and physical registers.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCopyToCombine()
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op