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"));
72 return "Hexagon Copy-To-Combine Pass";
92 unsigned I1DestReg,
unsigned I2DestReg,
113char HexagonCopyToCombine::ID = 0;
116 "Hexagon Copy-To-Combine Pass",
false,
false)
120 switch (
MI.getOpcode()) {
121 case Hexagon::A2_tfr: {
129 return Hexagon::IntRegsRegClass.contains(DestReg) &&
130 Hexagon::IntRegsRegClass.contains(SrcReg);
133 case Hexagon::A2_tfrsi: {
148 bool NotExt = Op1.
isImm() && isInt<8>(Op1.
getImm());
149 return Hexagon::IntRegsRegClass.contains(DestReg) &&
153 case Hexagon::V6_vassign:
164 if (
I.getOpcode() == Hexagon::TFRI64_V4 ||
165 I.getOpcode() == Hexagon::A2_tfrsi) {
167 return !
Op.isImm() || !isInt<N>(
Op.getImm());
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;
198 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
199 isGreaterThanNBitTFRI<6>(LowRegInst))
205 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
212 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
213 isGreaterThanNBitTFRI<8>(LowRegInst))
221 if (Hexagon::IntRegsRegClass.
contains(Reg))
222 return (Reg - Hexagon::R0) % 2 == 0;
223 if (Hexagon::HvxVRRegClass.
contains(Reg))
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;
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");
328 unsigned KilledOperand = 0;
348 if (
MI.isDebugInstr()) {
349 if (
MI.readsRegister(I1DestReg,
TRI))
350 DbgMItoMove.push_back(&
MI);
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;
387 if (
MI.isDebugInstr())
395 if (!
Op.isReg() || !
Op.isUse() || !
Op.getReg())
409 unsigned NumInstsToDef = 0;
410 while (&*It != &
MI) {
411 if (!It->isDebugInstr())
419 PotentiallyNewifiableTFR.insert(DefInst);
429 if (!
Op.isDef() || !
Op.getReg())
432 if (Hexagon::DoubleRegsRegClass.
contains(Reg)) {
435 }
else if (Hexagon::IntRegsRegClass.
contains(Reg))
437 }
else if (
Op.isRegMask()) {
438 for (
unsigned Reg : Hexagon::IntRegsRegClass)
439 if (
Op.clobbersPhysReg(Reg))
452 bool HasChanged =
false;
456 TRI =
ST->getRegisterInfo();
457 TII =
ST->getInstrInfo();
460 bool OptForSize =
F.hasOptSize();
467 if (!OptForSize &&
ST->isTinyCore())
472 PotentiallyNewifiableTFR.clear();
473 findPotentialNewifiableTFRs(
MBB);
480 if (
I1.isDebugInstr())
496 bool DoInsertAtI1 =
false;
498 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
501 combine(I1, *I2,
MI, DoInsertAtI1, OptForSize);
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))
564 bool DoInsertAtI1,
bool OptForSize) {
571 Register I1DestReg =
I1.getOperand(0).getReg();
573 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
574 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
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");
597 bool IsHiReg = HiOperand.
isReg();
598 bool IsLoReg = LoOperand.
isReg();
601 bool IsC64 = OptForSize && LoOperand.
isImm() && HiOperand.
isImm() &&
602 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
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) {
622 for (
auto *NewMI : DbgMItoMove) {
627 BB->
splice(InsertPt, BB, NewMI);
631 I1.eraseFromParent();
636 unsigned DoubleDestReg,
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,
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)
724 if (isInt<8>(LoOperand.
getImm())) {
725 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
732 if (isInt<8>(HiOperand.
getImm())) {
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,
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,
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,
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
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Represent the analysis usage information of a pass.
This class represents an Operation in the Expression.
Implements a dense probed hash-table based set.
FunctionPass class - This class is used to implement most global optimizations.
bool mayBeNewStore(const MachineInstr &MI) const
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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 '...
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
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.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
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.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
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...
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.
Reg
All possible values of the reg field in the ModR/M byte.
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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCopyToCombine()
unsigned getKillRegState(bool B)