32 #define DEBUG_TYPE "hexagon-copy-combine" 38 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"));
80 return "Hexagon Copy-To-Combine Pass";
101 unsigned I1DestReg,
unsigned I2DestReg,
125 "Hexagon Copy-To-Combine Pass",
false,
false)
128 bool ShouldCombineAggressively) {
129 switch (MI.getOpcode()) {
130 case Hexagon::A2_tfr: {
138 return Hexagon::IntRegsRegClass.contains(DestReg) &&
139 Hexagon::IntRegsRegClass.contains(SrcReg);
142 case Hexagon::A2_tfrsi: {
158 return Hexagon::IntRegsRegClass.contains(DestReg) &&
159 (ShouldCombineAggressively || NotExt);
162 case Hexagon::V6_vassign:
173 if (I.
getOpcode() == Hexagon::TFRI64_V4 ||
186 unsigned HiOpc = HighRegInst.
getOpcode();
189 auto verifyOpc = [](
unsigned Opc) ->
void {
191 case Hexagon::A2_tfr:
192 case Hexagon::A2_tfrsi:
193 case Hexagon::V6_vassign:
202 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
203 return HiOpc == LoOpc;
207 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
208 isGreaterThanNBitTFRI<6>(LowRegInst))
214 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
215 isGreaterThanNBitTFRI<16>(LowRegInst))
221 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
222 isGreaterThanNBitTFRI<8>(LowRegInst))
230 if (Hexagon::IntRegsRegClass.
contains(Reg))
231 return (Reg - Hexagon::R0) % 2 == 0;
232 if (Hexagon::HvxVRRegClass.
contains(Reg))
233 return (Reg - Hexagon::V0) % 2 == 0;
263 bool HexagonCopyToCombine::isSafeToMoveTogether(
MachineInstr &I1,
267 bool &DoInsertAtI1) {
285 if (!ShouldCombineAggressively)
290 unsigned KilledOperand = 0;
292 KilledOperand = I2UseReg;
295 for (;
I != End; ++
I) {
302 if (
I->isDebugInstr())
311 if (!KillingInstr && KilledOperand &&
312 I->readsRegister(KilledOperand, TRI))
320 assert(Added &&
"Must successfully update kill flag");
333 if (!ShouldCombineAggressively)
340 unsigned KilledOperand = 0;
373 assert(!KillingInstr &&
"Should only see one killing instruction");
374 KilledOperand = I1UseReg;
384 assert(Added &&
"Must successfully update kill flag");
386 DoInsertAtI1 =
false;
398 if (
MI.isDebugInstr())
404 for (
unsigned OpdIdx = 0, OpdE =
MI.getNumOperands(); OpdIdx != OpdE;
417 if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively))
423 unsigned NumInstsToDef = 0;
424 while (&*It != &
MI) {
425 if (!It->isDebugInstr())
433 PotentiallyNewifiableTFR.
insert(DefInst);
443 if (!
Op.isDef() || !
Op.getReg())
446 if (Hexagon::DoubleRegsRegClass.
contains(Reg)) {
448 LastDef[*SubRegs] = &
MI;
449 }
else if (Hexagon::IntRegsRegClass.
contains(Reg))
451 }
else if (
Op.isRegMask()) {
452 for (
unsigned Reg : Hexagon::IntRegsRegClass)
453 if (
Op.clobbersPhysReg(
Reg))
466 bool HasChanged =
false;
477 ShouldCombineAggressively =
483 PotentiallyNewifiableTFR.
clear();
484 findPotentialNewifiableTFRs(*BI);
497 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.
count(&I1))
501 if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))
507 bool DoInsertAtI1 =
false;
509 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
512 combine(I1, *I2,
MI, DoInsertAtI1, OptForSize);
528 while (I2 != I1.
getParent()->
end() && I2->isDebugInstr())
536 if (I2->modifiesRegister(I1DestReg, TRI))
540 if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively))
544 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.
count(&*I2))
547 Register I2DestReg = I2->getOperand(0).getReg();
551 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
552 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
553 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
554 if ((!IsI1LowReg && !IsI2LowReg) || !
isEvenReg(FirstRegIndex))
564 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
575 bool DoInsertAtI1,
bool OptForSize) {
584 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
585 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
589 if (Hexagon::IntRegsRegClass.
contains(LoRegDef)) {
590 SuperRC = &Hexagon::DoubleRegsRegClass;
591 SubLo = Hexagon::isub_lo;
592 }
else if (Hexagon::HvxVRRegClass.
contains(LoRegDef)) {
594 SuperRC = &Hexagon::HvxWRRegClass;
595 SubLo = Hexagon::vsub_lo;
601 assert(DoubleRegDest != 0 &&
"Expect a valid register");
608 bool IsHiReg = HiOperand.
isReg();
609 bool IsLoReg = LoOperand.
isReg();
612 bool IsC64 = OptForSize && LoOperand.
isImm() && HiOperand.
isImm() &&
613 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
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) {
633 for (
auto NewMI : DbgMItoMove) {
638 BB->
splice(InsertPt, BB, NewMI);
643 I2.eraseFromParent();
647 unsigned DoubleDestReg,
652 DebugLoc DL = InsertPt->getDebugLoc();
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,
667 DebugLoc DL = InsertPt->getDebugLoc();
672 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
675 .addImm(LoOperand.
getImm());
679 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
680 .addImm(HiOperand.
getImm())
688 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
691 .addImm(LoOperand.
getImm());
695 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
696 .addImm(HiOperand.
getImm())
703 if (HiOperand.
isJTI()) {
704 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
706 .addImm(LoOperand.
getImm());
709 if (LoOperand.
isJTI()) {
710 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
711 .addImm(HiOperand.
getImm())
717 if (HiOperand.
isCPI()) {
718 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
721 .addImm(LoOperand.
getImm());
724 if (LoOperand.
isCPI()) {
725 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
726 .addImm(HiOperand.
getImm())
736 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
737 .addImm(HiOperand.
getImm())
738 .addImm(LoOperand.
getImm());
744 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
745 .addImm(HiOperand.
getImm())
746 .addImm(LoOperand.
getImm());
752 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
753 .addImm(HiOperand.
getImm())
754 .addImm(LoOperand.
getImm());
758 unsigned DoubleDestReg,
764 DebugLoc DL = InsertPt->getDebugLoc();
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)
801 .addImm(HiOperand.
getImm())
802 .addReg(LoReg, LoRegKillFlag);
806 unsigned DoubleDestReg,
812 DebugLoc DL = InsertPt->getDebugLoc();
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)
834 .addReg(HiOperand.
getReg(), HiRegKillFlag)
839 if (LoOperand.
isCPI()) {
840 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
841 .addReg(HiOperand.
getReg(), HiRegKillFlag)
849 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
850 .addReg(HiReg, HiRegKillFlag)
855 unsigned DoubleDestReg,
863 DebugLoc DL = InsertPt->getDebugLoc();
869 if (Hexagon::DoubleRegsRegClass.
contains(DoubleDestReg)) {
870 NewOpc = Hexagon::A2_combinew;
871 }
else if (Hexagon::HvxWRRegClass.
contains(DoubleDestReg)) {
873 NewOpc = Hexagon::V6_vcombine;
877 BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg)
878 .addReg(HiReg, HiRegKillFlag)
879 .
addReg(LoReg, LoRegKillFlag);
883 return new HexagonCopyToCombine();
unsigned getTargetFlags() const
FunctionPass * createHexagonCopyToCombine()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
Implements a dense probed hash-table based set.
void push_back(const T &Elt)
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
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...
constexpr bool isInt< 8 >(int64_t x)
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
unsigned const TargetRegisterInfo * TRI
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
static bool isGreaterThanNBitTFRI(const MachineInstr &I)
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...
bool isMetaInstruction() const
Return true if this instruction doesn't produce any output in the form of executable instructions...
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
return AArch64::GPR64RegClass contains(Reg)
static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
const HexagonRegisterInfo * getRegisterInfo() const override
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void initializeHexagonCopyToCombinePass(PassRegistry &)
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
unsigned getKillRegState(bool B)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Register UseReg(const MachineOperand &MO)
const GlobalValue * getGlobal() const
std::pair< iterator, bool > insert(const ValueT &V)
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
self_iterator getIterator()
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
MCSubRegIterator enumerates all sub-registers of Reg.
bool isDebugInstr() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setIsKill(bool Val=true)
INITIALIZE_PASS(HexagonCopyToCombine, "hexagon-copy-combine", "Hexagon Copy-To-Combine Pass", false, false) static bool isCombinableInstType(MachineInstr &MI
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
Iterator for intrusive lists based on ilist_node.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register...
Promote Memory to Register
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"))
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
const MachineBasicBlock * getParent() const
MachineFunctionProperties & set(Property P)
const HexagonInstrInfo bool ShouldCombineAggressively
Representation of each machine instruction.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
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 '...
unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, const TargetRegisterClass *RC) const
Return a super-register of the specified register Reg so its sub-register of index SubIdx is Reg...
int64_t getOffset() const
Return the offset from the symbol in this operand.
const BlockAddress * getBlockAddress() const
bool mayBeNewStore(const MachineInstr &MI) const
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static bool isEvenReg(unsigned Reg)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const HexagonInstrInfo * getInstrInfo() const override
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
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"))
Properties which a MachineFunction may have at a given point in time.
Wrapper class representing virtual and physical registers.
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const
static cl::opt< bool > IsConst64Disabled("disable-const64", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable generation of const64"))