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";
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:
154 case Hexagon::LX_assign:
165 if (
I.getOpcode() == Hexagon::TFRI64_V4 ||
166 I.getOpcode() == Hexagon::A2_tfrsi) {
178 unsigned HiOpc = HighRegInst.
getOpcode();
181 auto verifyOpc = [](
unsigned Opc) ->
void {
183 case Hexagon::A2_tfr:
184 case Hexagon::A2_tfrsi:
185 case Hexagon::V6_vassign:
186 case Hexagon::LX_assign:
195 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
196 return HiOpc == LoOpc;
198 if (HiOpc == Hexagon::LX_assign || LoOpc == Hexagon::LX_assign)
199 return HiOpc == LoOpc;
227 return (
Reg - Hexagon::R0) % 2 == 0;
229 return (
Reg - Hexagon::V0) % 2 == 0;
231 return (
Reg - Hexagon::L0) % 2 == 0;
237 if (
Op.isReg() &&
Op.getReg() == RegNotKilled &&
Op.isKill())
247 MI.modifiesRegister(DestReg,
TRI) ||
MI.readsRegister(DestReg,
TRI) ||
248 MI.hasUnmodeledSideEffects() ||
MI.isInlineAsm() ||
249 MI.isMetaInstruction();
258bool HexagonCopyToCombine::isSafeToMoveTogether(
MachineInstr &I1,
262 bool &DoInsertAtI1) {
267 if (I2UseReg &&
I1.modifiesRegister(I2UseReg,
TRI))
281 End = ++
I1.getIterator().getReverse();
285 unsigned KilledOperand = 0;
287 KilledOperand = I2UseReg;
288 MachineInstr *KillingInstr =
nullptr;
290 for (;
I !=
End; ++
I) {
297 if (
I->isDebugInstr())
306 if (!KillingInstr && KilledOperand &&
307 I->readsRegister(KilledOperand,
TRI))
315 assert(Added &&
"Must successfully update kill flag");
334 MachineInstr *KillingInstr =
nullptr;
335 unsigned KilledOperand = 0;
338 MachineInstr &
MI = *
I;
355 if (
MI.isDebugInstr()) {
356 if (
MI.readsRegister(I1DestReg,
TRI))
363 (!
MI.killsRegister(I1UseReg,
nullptr) &&
364 MI.killsRegister(I1UseReg,
TRI)))
368 if (I1UseReg &&
MI.killsRegister(I1UseReg,
nullptr)) {
369 assert(!KillingInstr &&
"Should only see one killing instruction");
370 KilledOperand = I1UseReg;
378 bool Added =
I1.addRegisterKilled(KilledOperand,
TRI);
380 assert(Added &&
"Must successfully update kill flag");
382 DoInsertAtI1 =
false;
391HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {
392 DenseMap<unsigned, MachineInstr *> LastDef;
393 for (MachineInstr &
MI : BB) {
394 if (
MI.isDebugInstr())
400 for (
const MachineOperand &
Op :
MI.operands()) {
402 if (!
Op.isReg() || !
Op.isUse() || !
Op.getReg())
407 MachineInstr *DefInst = LastDef[
Reg];
416 unsigned NumInstsToDef = 0;
417 while (&*It != &
MI) {
418 if (!It->isDebugInstr())
426 PotentiallyNewifiableTFR.
insert(DefInst);
434 for (MachineOperand &
Op :
MI.operands()) {
436 if (!
Op.isDef() || !
Op.getReg())
441 LastDef[SubReg] = &
MI;
444 }
else if (
Op.isRegMask()) {
445 for (
unsigned Reg : Hexagon::IntRegsRegClass)
446 if (
Op.clobbersPhysReg(
Reg))
459 bool HasChanged =
false;
478 for (MachineBasicBlock &
MBB : MF) {
479 PotentiallyNewifiableTFR.
clear();
480 findPotentialNewifiableTFRs(
MBB);
485 MachineInstr &
I1 = *
MI++;
487 if (
I1.isDebugInstr())
503 bool DoInsertAtI1 =
false;
505 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
508 combine(I1, *I2,
MI, DoInsertAtI1, OptForSize);
520MachineInstr *HexagonCopyToCombine::findPairable(MachineInstr &I1,
524 while (I2 !=
I1.getParent()->end() && I2->isDebugInstr())
527 Register I1DestReg =
I1.getOperand(0).getReg();
532 if (I2->modifiesRegister(I1DestReg,
TRI))
543 Register I2DestReg = I2->getOperand(0).getReg();
547 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
548 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
549 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
550 if ((!IsI1LowReg && !IsI2LowReg) || !
isEvenReg(FirstRegIndex))
560 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
569void HexagonCopyToCombine::combine(MachineInstr &I1, MachineInstr &I2,
571 bool DoInsertAtI1,
bool OptForSize) {
578 Register I1DestReg =
I1.getOperand(0).getReg();
580 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
581 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
585 if (Hexagon::IntRegsRegClass.
contains(LoRegDef)) {
586 SuperRC = &Hexagon::DoubleRegsRegClass;
587 SubLo = Hexagon::isub_lo;
588 }
else if (Hexagon::HvxVRRegClass.
contains(LoRegDef)) {
590 SuperRC = &Hexagon::HvxWRRegClass;
591 SubLo = Hexagon::vsub_lo;
592 }
else if (Hexagon::HlxLRRegClass.
contains(LoRegDef)) {
594 SuperRC = &Hexagon::HlxLLRRegClass;
595 SubLo = Hexagon::vsub_lo;
600 MCRegister DoubleRegDest =
TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
601 assert(DoubleRegDest.
isValid() &&
"Expect a valid register");
604 MachineOperand &LoOperand = IsI1Loreg ?
I1.getOperand(1) : I2.
getOperand(1);
605 MachineOperand &HiOperand = IsI1Loreg ? I2.
getOperand(1) :
I1.getOperand(1);
608 bool IsHiReg = HiOperand.
isReg();
609 bool IsLoReg = LoOperand.
isReg();
612 bool IsC64 = OptForSize && LoOperand.
isImm() && HiOperand.
isImm() &&
617 if (IsHiReg && IsLoReg)
618 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
620 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
622 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
624 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
626 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
630 if (!DoInsertAtI1 && DbgMItoMove.
size() != 0) {
632 MachineBasicBlock *BB = InsertPt->getParent();
633 for (
auto *NewMI : DbgMItoMove) {
638 BB->
splice(InsertPt, BB, NewMI);
642 I1.eraseFromParent();
647 unsigned DoubleDestReg,
648 MachineOperand &HiOperand,
649 MachineOperand &LoOperand) {
653 MachineBasicBlock *BB = InsertPt->getParent();
655 "Both operands must be immediate");
657 int64_t
V = HiOperand.
getImm();
658 V = (
V << 32) | (0x0ffffffffLL & LoOperand.
getImm());
659 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::CONST64), DoubleDestReg)
664 unsigned DoubleDestReg,
665 MachineOperand &HiOperand,
666 MachineOperand &LoOperand) {
668 MachineBasicBlock *BB = InsertPt->getParent();
672 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
679 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
688 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
695 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
703 if (HiOperand.
isJTI()) {
704 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
709 if (LoOperand.
isJTI()) {
710 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
717 if (HiOperand.
isCPI()) {
718 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
724 if (LoOperand.
isCPI()) {
725 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
736 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
744 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
752 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
758 unsigned DoubleDestReg,
759 MachineOperand &HiOperand,
760 MachineOperand &LoOperand) {
765 MachineBasicBlock *BB = InsertPt->getParent();
769 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
772 .
addReg(LoReg, LoRegKillFlag);
777 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
780 .
addReg(LoReg, LoRegKillFlag);
784 if (HiOperand.
isJTI()) {
785 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
787 .
addReg(LoReg, LoRegKillFlag);
791 if (HiOperand.
isCPI()) {
792 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
795 .
addReg(LoReg, LoRegKillFlag);
800 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
802 .
addReg(LoReg, LoRegKillFlag);
806 unsigned DoubleDestReg,
807 MachineOperand &HiOperand,
808 MachineOperand &LoOperand) {
813 MachineBasicBlock *BB = InsertPt->getParent();
817 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
818 .
addReg(HiReg, HiRegKillFlag)
825 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
826 .
addReg(HiReg, HiRegKillFlag)
832 if (LoOperand.
isJTI()) {
833 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
839 if (LoOperand.
isCPI()) {
840 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
849 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
850 .
addReg(HiReg, HiRegKillFlag)
855 unsigned DoubleDestReg,
856 MachineOperand &HiOperand,
857 MachineOperand &LoOperand) {
864 MachineBasicBlock *BB = InsertPt->getParent();
869 if (Hexagon::DoubleRegsRegClass.
contains(DoubleDestReg)) {
870 NewOpc = Hexagon::A2_combinew;
871 }
else if (Hexagon::HvxWRRegClass.
contains(DoubleDestReg)) {
873 NewOpc = Hexagon::V6_vcombine;
874 }
else if (Hexagon::HlxLLRRegClass.
contains(DoubleDestReg)) {
876 NewOpc = Hexagon::LX_combine_w;
880 BuildMI(*BB, InsertPt,
DL,
TII->get(NewOpc), DoubleDestReg)
881 .
addReg(HiReg, HiRegKillFlag)
882 .
addReg(LoReg, LoRegKillFlag);
886 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 & 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 & 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 & 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 bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
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.
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.
RegState
Flags to represent properties of register accesses.
constexpr RegState getKillRegState(bool B)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCopyToCombine()
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
@ End
Run the machine verifier once, at the end of the pipeline.
MCRegisterClass TargetRegisterClass