33 #define DEBUG_TYPE "hexagon-copy-combine" 39 cl::desc(
"Disable merging into combines"));
44 cl::desc(
"Disable generation of const64"));
49 cl::desc(
"Maximum distance between a tfr feeding a store we " 50 "consider the store still to be newifiable"));
81 return "Hexagon Copy-To-Combine Pass";
102 unsigned I1DestReg,
unsigned I2DestReg,
126 "Hexagon Copy-To-Combine Pass",
false,
false)
129 bool ShouldCombineAggressively) {
130 switch (MI.getOpcode()) {
131 case Hexagon::A2_tfr: {
137 unsigned DestReg = Op0.
getReg();
138 unsigned SrcReg = Op1.
getReg();
139 return Hexagon::IntRegsRegClass.contains(DestReg) &&
140 Hexagon::IntRegsRegClass.contains(SrcReg);
143 case Hexagon::A2_tfrsi: {
150 unsigned DestReg = Op0.
getReg();
159 return Hexagon::IntRegsRegClass.contains(DestReg) &&
160 (ShouldCombineAggressively || NotExt);
163 case Hexagon::V6_vassign:
174 if (I.
getOpcode() == Hexagon::TFRI64_V4 ||
187 unsigned HiOpc = HighRegInst.
getOpcode();
190 auto verifyOpc = [](
unsigned Opc) ->
void {
192 case Hexagon::A2_tfr:
193 case Hexagon::A2_tfrsi:
194 case Hexagon::V6_vassign:
203 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
204 return HiOpc == LoOpc;
208 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
209 isGreaterThanNBitTFRI<6>(LowRegInst))
215 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
216 isGreaterThanNBitTFRI<16>(LowRegInst))
222 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
223 isGreaterThanNBitTFRI<8>(LowRegInst))
231 if (Hexagon::IntRegsRegClass.
contains(Reg))
232 return (Reg - Hexagon::R0) % 2 == 0;
233 if (Hexagon::HvxVRRegClass.
contains(Reg))
234 return (Reg - Hexagon::V0) % 2 == 0;
264 bool HexagonCopyToCombine::isSafeToMoveTogether(
MachineInstr &I1,
268 bool &DoInsertAtI1) {
286 if (!ShouldCombineAggressively)
291 unsigned KilledOperand = 0;
293 KilledOperand = I2UseReg;
296 for (;
I != End; ++
I) {
303 if (
I->isDebugInstr())
312 if (!KillingInstr && KilledOperand &&
313 I->readsRegister(KilledOperand, TRI))
321 assert(Added &&
"Must successfully update kill flag");
334 if (!ShouldCombineAggressively)
341 unsigned KilledOperand = 0;
374 assert(!KillingInstr &&
"Should only see one killing instruction");
375 KilledOperand = I1UseReg;
385 assert(Added &&
"Must successfully update kill flag");
387 DoInsertAtI1 =
false;
399 if (
MI.isDebugInstr())
405 for (
unsigned OpdIdx = 0, OpdE =
MI.getNumOperands(); OpdIdx != OpdE;
418 if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively))
424 unsigned NumInstsToDef = 0;
425 while (&*It != &
MI) {
426 if (!It->isDebugInstr())
434 PotentiallyNewifiableTFR.
insert(DefInst);
444 if (!
Op.isDef() || !
Op.getReg())
446 unsigned Reg =
Op.getReg();
447 if (Hexagon::DoubleRegsRegClass.
contains(Reg)) {
449 LastDef[*SubRegs] = &
MI;
450 }
else if (Hexagon::IntRegsRegClass.
contains(Reg))
452 }
else if (
Op.isRegMask()) {
453 for (
unsigned Reg : Hexagon::IntRegsRegClass)
454 if (
Op.clobbersPhysReg(
Reg))
467 bool HasChanged =
false;
478 ShouldCombineAggressively =
484 PotentiallyNewifiableTFR.
clear();
485 findPotentialNewifiableTFRs(*BI);
498 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.
count(&I1))
502 if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))
508 bool DoInsertAtI1 =
false;
510 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
513 combine(I1, *I2,
MI, DoInsertAtI1, OptForSize);
529 while (I2 != I1.
getParent()->
end() && I2->isDebugInstr())
537 if (I2->modifiesRegister(I1DestReg, TRI))
541 if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively))
545 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.
count(&*I2))
548 unsigned I2DestReg = I2->getOperand(0).getReg();
552 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
553 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
554 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
555 if ((!IsI1LowReg && !IsI2LowReg) || !
isEvenReg(FirstRegIndex))
565 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
576 bool DoInsertAtI1,
bool OptForSize) {
585 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
586 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
590 if (Hexagon::IntRegsRegClass.
contains(LoRegDef)) {
591 SuperRC = &Hexagon::DoubleRegsRegClass;
592 SubLo = Hexagon::isub_lo;
593 }
else if (Hexagon::HvxVRRegClass.
contains(LoRegDef)) {
595 SuperRC = &Hexagon::HvxWRRegClass;
596 SubLo = Hexagon::vsub_lo;
602 assert(DoubleRegDest != 0 &&
"Expect a valid register");
609 bool IsHiReg = HiOperand.
isReg();
610 bool IsLoReg = LoOperand.
isReg();
613 bool IsC64 = OptForSize && LoOperand.
isImm() && HiOperand.
isImm() &&
614 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
618 if (IsHiReg && IsLoReg)
619 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
621 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
623 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
625 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
627 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
631 if (!DoInsertAtI1 && DbgMItoMove.
size() != 0) {
634 for (
auto NewMI : DbgMItoMove) {
639 BB->
splice(InsertPt, BB, NewMI);
644 I2.eraseFromParent();
648 unsigned DoubleDestReg,
653 DebugLoc DL = InsertPt->getDebugLoc();
656 "Both operands must be immediate");
658 int64_t V = HiOperand.
getImm();
659 V = (V << 32) | (0x0ffffffffLL & LoOperand.
getImm());
660 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::CONST64), DoubleDestReg)
665 unsigned DoubleDestReg,
668 DebugLoc DL = InsertPt->getDebugLoc();
673 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
676 .addImm(LoOperand.
getImm());
680 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
681 .addImm(HiOperand.
getImm())
689 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
692 .addImm(LoOperand.
getImm());
696 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
697 .addImm(HiOperand.
getImm())
704 if (HiOperand.
isJTI()) {
705 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
707 .addImm(LoOperand.
getImm());
710 if (LoOperand.
isJTI()) {
711 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
712 .addImm(HiOperand.
getImm())
718 if (HiOperand.
isCPI()) {
719 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
722 .addImm(LoOperand.
getImm());
725 if (LoOperand.
isCPI()) {
726 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
727 .addImm(HiOperand.
getImm())
737 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
738 .addImm(HiOperand.
getImm())
739 .addImm(LoOperand.
getImm());
745 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
746 .addImm(HiOperand.
getImm())
747 .addImm(LoOperand.
getImm());
753 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
754 .addImm(HiOperand.
getImm())
755 .addImm(LoOperand.
getImm());
759 unsigned DoubleDestReg,
762 unsigned LoReg = LoOperand.
getReg();
765 DebugLoc DL = InsertPt->getDebugLoc();
770 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
773 .addReg(LoReg, LoRegKillFlag);
778 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
781 .addReg(LoReg, LoRegKillFlag);
785 if (HiOperand.
isJTI()) {
786 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
788 .addReg(LoReg, LoRegKillFlag);
792 if (HiOperand.
isCPI()) {
793 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
796 .addReg(LoReg, LoRegKillFlag);
801 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
802 .addImm(HiOperand.
getImm())
803 .addReg(LoReg, LoRegKillFlag);
807 unsigned DoubleDestReg,
811 unsigned HiReg = HiOperand.
getReg();
813 DebugLoc DL = InsertPt->getDebugLoc();
818 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
819 .addReg(HiReg, HiRegKillFlag)
826 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
827 .addReg(HiReg, HiRegKillFlag)
833 if (LoOperand.
isJTI()) {
834 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
835 .addReg(HiOperand.
getReg(), HiRegKillFlag)
840 if (LoOperand.
isCPI()) {
841 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
842 .addReg(HiOperand.
getReg(), HiRegKillFlag)
850 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
851 .addReg(HiReg, HiRegKillFlag)
856 unsigned DoubleDestReg,
861 unsigned LoReg = LoOperand.
getReg();
862 unsigned HiReg = HiOperand.
getReg();
864 DebugLoc DL = InsertPt->getDebugLoc();
870 if (Hexagon::DoubleRegsRegClass.
contains(DoubleDestReg)) {
871 NewOpc = Hexagon::A2_combinew;
872 }
else if (Hexagon::HvxWRRegClass.
contains(DoubleDestReg)) {
874 NewOpc = Hexagon::V6_vcombine;
878 BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg)
879 .addReg(HiReg, HiRegKillFlag)
880 .
addReg(LoReg, LoRegKillFlag);
884 return new HexagonCopyToCombine();
unsigned getTargetFlags() const
FunctionPass * createHexagonCopyToCombine()
bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register...
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)
unsigned getReg() const
getReg - Returns the register number.
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.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
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
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 MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned char TargetFlags=0) const
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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
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...
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.
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
const MachineBasicBlock * getParent() const
MachineFunctionProperties & set(Property P)
const HexagonInstrInfo bool ShouldCombineAggressively
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
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...
static unsigned UseReg(const MachineOperand &MO)
int64_t getOffset() const
Return the offset from the symbol in this operand.
const BlockAddress * getBlockAddress() const
bool mayBeNewStore(const MachineInstr &MI) const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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 addRegisterKilled(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
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...
const MachineOperand & getOperand(unsigned i) const
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.
static cl::opt< bool > IsConst64Disabled("disable-const64", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable generation of const64"))