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"));
78 return "Hexagon Copy-To-Combine Pass";
85 MachineFunctionProperties::Property::NoVRegs);
99 unsigned I1DestReg,
unsigned I2DestReg,
120char HexagonCopyToCombine::ID = 0;
123 "Hexagon Copy-To-Combine Pass",
false,
false)
127 switch (
MI.getOpcode()) {
128 case Hexagon::A2_tfr: {
136 return Hexagon::IntRegsRegClass.contains(DestReg) &&
137 Hexagon::IntRegsRegClass.contains(SrcReg);
140 case Hexagon::A2_tfrsi: {
155 bool NotExt = Op1.
isImm() && isInt<8>(Op1.
getImm());
156 return Hexagon::IntRegsRegClass.contains(DestReg) &&
160 case Hexagon::V6_vassign:
171 if (
I.getOpcode() == Hexagon::TFRI64_V4 ||
172 I.getOpcode() == Hexagon::A2_tfrsi) {
174 return !Op.isImm() || !isInt<N>(Op.getImm());
184 unsigned HiOpc = HighRegInst.
getOpcode();
187 auto verifyOpc = [](
unsigned Opc) ->
void {
189 case Hexagon::A2_tfr:
190 case Hexagon::A2_tfrsi:
191 case Hexagon::V6_vassign:
200 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
201 return HiOpc == LoOpc;
205 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
206 isGreaterThanNBitTFRI<6>(LowRegInst))
212 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
219 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
220 isGreaterThanNBitTFRI<8>(LowRegInst))
228 if (Hexagon::IntRegsRegClass.
contains(Reg))
229 return (Reg - Hexagon::R0) % 2 == 0;
230 if (Hexagon::HvxVRRegClass.
contains(Reg))
231 return (Reg - Hexagon::V0) % 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;
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");
335 unsigned KilledOperand = 0;
355 if (
MI.isDebugInstr()) {
356 if (
MI.readsRegister(I1DestReg,
TRI))
357 DbgMItoMove.push_back(&
MI);
363 (!
MI.killsRegister(I1UseReg) &&
MI.killsRegister(I1UseReg,
TRI)))
367 if (I1UseReg &&
MI.killsRegister(I1UseReg)) {
368 assert(!KillingInstr &&
"Should only see one killing instruction");
369 KilledOperand = I1UseReg;
377 bool Added =
I1.addRegisterKilled(KilledOperand,
TRI);
379 assert(Added &&
"Must successfully update kill flag");
381 DoInsertAtI1 =
false;
393 if (
MI.isDebugInstr())
401 if (!
Op.isReg() || !
Op.isUse() || !
Op.getReg())
415 unsigned NumInstsToDef = 0;
416 while (&*It != &
MI) {
417 if (!It->isDebugInstr())
425 PotentiallyNewifiableTFR.insert(DefInst);
435 if (!
Op.isDef() || !
Op.getReg())
438 if (Hexagon::DoubleRegsRegClass.
contains(Reg)) {
441 }
else if (Hexagon::IntRegsRegClass.
contains(Reg))
443 }
else if (
Op.isRegMask()) {
444 for (
unsigned Reg : Hexagon::IntRegsRegClass)
445 if (
Op.clobbersPhysReg(Reg))
458 bool HasChanged =
false;
462 TRI =
ST->getRegisterInfo();
463 TII =
ST->getInstrInfo();
466 bool OptForSize =
F.hasFnAttribute(Attribute::OptimizeForSize);
473 if (!OptForSize &&
ST->isTinyCore())
478 PotentiallyNewifiableTFR.clear();
479 findPotentialNewifiableTFRs(
MBB);
486 if (
I1.isDebugInstr())
502 bool DoInsertAtI1 =
false;
504 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
507 combine(I1, *I2,
MI, DoInsertAtI1, OptForSize);
523 while (I2 !=
I1.getParent()->end() && I2->isDebugInstr())
526 Register I1DestReg =
I1.getOperand(0).getReg();
531 if (I2->modifiesRegister(I1DestReg,
TRI))
542 Register I2DestReg = I2->getOperand(0).getReg();
546 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
547 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
548 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
549 if ((!IsI1LowReg && !IsI2LowReg) || !
isEvenReg(FirstRegIndex))
559 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
570 bool DoInsertAtI1,
bool OptForSize) {
577 Register I1DestReg =
I1.getOperand(0).getReg();
579 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
580 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
584 if (Hexagon::IntRegsRegClass.
contains(LoRegDef)) {
585 SuperRC = &Hexagon::DoubleRegsRegClass;
586 SubLo = Hexagon::isub_lo;
587 }
else if (Hexagon::HvxVRRegClass.
contains(LoRegDef)) {
589 SuperRC = &Hexagon::HvxWRRegClass;
590 SubLo = Hexagon::vsub_lo;
595 unsigned DoubleRegDest =
TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
596 assert(DoubleRegDest != 0 &&
"Expect a valid register");
603 bool IsHiReg = HiOperand.
isReg();
604 bool IsLoReg = LoOperand.
isReg();
607 bool IsC64 = OptForSize && LoOperand.
isImm() && HiOperand.
isImm() &&
608 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
612 if (IsHiReg && IsLoReg)
613 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
615 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
617 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
619 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
621 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
625 if (!DoInsertAtI1 && DbgMItoMove.size() != 0) {
628 for (
auto *NewMI : DbgMItoMove) {
633 BB->
splice(InsertPt, BB, NewMI);
637 I1.eraseFromParent();
642 unsigned DoubleDestReg,
650 "Both operands must be immediate");
652 int64_t
V = HiOperand.
getImm();
653 V = (
V << 32) | (0x0ffffffffLL & LoOperand.
getImm());
654 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::CONST64), DoubleDestReg)
659 unsigned DoubleDestReg,
667 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
674 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
683 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
690 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
698 if (HiOperand.
isJTI()) {
699 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
704 if (LoOperand.
isJTI()) {
705 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
712 if (HiOperand.
isCPI()) {
713 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
719 if (LoOperand.
isCPI()) {
720 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
730 if (isInt<8>(LoOperand.
getImm())) {
731 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
738 if (isInt<8>(HiOperand.
getImm())) {
739 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
747 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
753 unsigned DoubleDestReg,
764 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
767 .
addReg(LoReg, LoRegKillFlag);
772 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
775 .
addReg(LoReg, LoRegKillFlag);
779 if (HiOperand.
isJTI()) {
780 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
782 .
addReg(LoReg, LoRegKillFlag);
786 if (HiOperand.
isCPI()) {
787 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
790 .
addReg(LoReg, LoRegKillFlag);
795 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
797 .
addReg(LoReg, LoRegKillFlag);
801 unsigned DoubleDestReg,
812 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
813 .
addReg(HiReg, HiRegKillFlag)
820 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
821 .
addReg(HiReg, HiRegKillFlag)
827 if (LoOperand.
isJTI()) {
828 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
834 if (LoOperand.
isCPI()) {
835 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
844 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
845 .
addReg(HiReg, HiRegKillFlag)
850 unsigned DoubleDestReg,
864 if (Hexagon::DoubleRegsRegClass.
contains(DoubleDestReg)) {
865 NewOpc = Hexagon::A2_combinew;
866 }
else if (Hexagon::HvxWRRegClass.
contains(DoubleDestReg)) {
868 NewOpc = Hexagon::V6_vcombine;
872 BuildMI(*BB, InsertPt,
DL,
TII->get(NewOpc), DoubleDestReg)
873 .
addReg(HiReg, HiRegKillFlag)
874 .
addReg(LoReg, LoRegKillFlag);
878 return new HexagonCopyToCombine();
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)
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Represent the analysis usage information of a pass.
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
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.
MachineFunctionProperties & set(Property P)
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 LLVMTargetMachine & 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.
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
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.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
static 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.
CodeGenOpt::Level 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...
ilist_iterator< OptionsT, !IsReverse, IsConst > getReverse() const
Get a reverse iterator to the same node.
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCopyToCombine()
unsigned getKillRegState(bool B)
void initializeHexagonCopyToCombinePass(PassRegistry &)