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"));
64 bool ShouldCombineAggressively;
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:
164 case Hexagon::V6_vassign_128B:
175 if (I.
getOpcode() == Hexagon::TFRI64_V4 ||
188 unsigned HiOpc = HighRegInst.
getOpcode();
191 auto verifyOpc = [](
unsigned Opc) ->
void {
193 case Hexagon::A2_tfr:
194 case Hexagon::A2_tfrsi:
195 case Hexagon::V6_vassign:
204 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
205 return HiOpc == LoOpc;
209 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
210 isGreaterThanNBitTFRI<6>(LowRegInst))
216 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
217 isGreaterThanNBitTFRI<16>(LowRegInst))
223 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
224 isGreaterThanNBitTFRI<8>(LowRegInst))
232 if (Hexagon::IntRegsRegClass.
contains(Reg))
233 return (Reg - Hexagon::R0) % 2 == 0;
234 if (Hexagon::VectorRegsRegClass.
contains(Reg) ||
235 Hexagon::VectorRegs128BRegClass.
contains(Reg))
236 return (Reg - Hexagon::V0) % 2 == 0;
265 bool HexagonCopyToCombine::isSafeToMoveTogether(
MachineInstr &I1,
269 bool &DoInsertAtI1) {
287 if (!ShouldCombineAggressively)
292 unsigned KilledOperand = 0;
294 KilledOperand = I2UseReg;
297 for (;
I !=
End; ++
I) {
304 if (
I->isDebugValue())
313 if (!KillingInstr && KilledOperand &&
314 I->readsRegister(KilledOperand, TRI))
322 assert(Added &&
"Must successfully update kill flag");
335 if (!ShouldCombineAggressively)
342 unsigned KilledOperand = 0;
364 DbgMItoMove.push_back(&MI);
375 assert(!KillingInstr &&
"Should only see one killing instruction");
376 KilledOperand = I1UseReg;
386 assert(Added &&
"Must successfully update kill flag");
388 DoInsertAtI1 =
false;
404 if (TII->mayBeNewStore(MI)) {
406 for (
unsigned OpdIdx = 0, OpdE = MI.
getNumOperands(); OpdIdx != OpdE;
419 if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively))
425 unsigned NumInstsToDef = 0;
426 while (&*It != &MI) {
427 if (!It->isDebugValue())
435 PotentiallyNewifiableTFR.insert(DefInst);
447 unsigned Reg = Op.
getReg();
448 if (Hexagon::DoubleRegsRegClass.
contains(Reg)) {
450 LastDef[*SubRegs] = &
MI;
452 }
else if (Hexagon::IntRegsRegClass.
contains(Reg))
462 bool HasChanged =
false;
466 TRI =
ST->getRegisterInfo();
467 TII =
ST->getInstrInfo();
473 ShouldCombineAggressively =
479 PotentiallyNewifiableTFR.clear();
480 findPotentialNewifiableTFRs(*BI);
493 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&I1))
497 if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))
503 bool DoInsertAtI1 =
false;
505 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
508 combine(I1, *I2, MI, DoInsertAtI1, OptForSize);
524 while (I2 != I1.
getParent()->
end() && I2->isDebugValue())
532 if (I2->modifiesRegister(I1DestReg, TRI))
536 if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively))
540 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&*I2))
543 unsigned 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))
561 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
572 bool DoInsertAtI1,
bool OptForSize) {
581 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
582 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
586 if (Hexagon::IntRegsRegClass.
contains(LoRegDef)) {
587 SuperRC = &Hexagon::DoubleRegsRegClass;
588 SubLo = Hexagon::isub_lo;
589 }
else if (Hexagon::VectorRegsRegClass.
contains(LoRegDef)) {
591 if (
ST->useHVXSglOps())
592 SuperRC = &Hexagon::VecDblRegsRegClass;
594 SuperRC = &Hexagon::VecDblRegs128BRegClass;
595 SubLo = Hexagon::vsub_lo;
600 unsigned DoubleRegDest = TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
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);
647 unsigned DoubleDestReg,
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,
761 unsigned LoReg = LoOperand.
getReg();
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,
810 unsigned HiReg = HiOperand.
getReg();
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,
860 unsigned LoReg = LoOperand.
getReg();
861 unsigned HiReg = HiOperand.
getReg();
863 DebugLoc DL = InsertPt->getDebugLoc();
869 if (Hexagon::DoubleRegsRegClass.
contains(DoubleDestReg)) {
870 NewOpc = Hexagon::A2_combinew;
871 }
else if (Hexagon::VecDblRegsRegClass.
contains(DoubleDestReg)) {
873 if (
ST->useHVXSglOps())
874 NewOpc = Hexagon::V6_vcombine;
876 NewOpc = Hexagon::V6_vcombine_128B;
880 BuildMI(*BB, InsertPt, DL, TII->
get(NewOpc), DoubleDestReg)
881 .addReg(HiReg, HiRegKillFlag)
882 .
addReg(LoReg, LoRegKillFlag);
886 return new HexagonCopyToCombine();
FunctionPass * createHexagonCopyToCombine()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
Implements a dense probed hash-table based set.
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 isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
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...
return AArch64::GPR64RegClass contains(Reg)
static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled)
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.
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.
void initializeHexagonCopyToCombinePass(PassRegistry &)
const MachineInstrBuilder & addImm(int64_t Val) const
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const MachineBasicBlock * getParent() const
bool isDebugValue() const
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)
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 const unsigned End
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.
self_iterator getIterator()
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
MCSubRegIterator enumerates all sub-registers of Reg.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setIsKill(bool Val=true)
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
Iterator for intrusive lists based on ilist_node.
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...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
MachineFunctionProperties & set(Property P)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
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 '...
INITIALIZE_PASS(HexagonCopyToCombine,"hexagon-copy-combine","Hexagon Copy-To-Combine Pass", false, false) static bool isCombinableInstType(MachineInstr &MI
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
bool addRegisterKilled(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
StringRef - Represent a constant reference to a string, i.e.
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
Add a new virtual register operand.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
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...
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"))