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,
nullptr) &&
364 MI.killsRegister(I1UseReg,
TRI)))
368 if (I1UseReg &&
MI.killsRegister(I1UseReg,
nullptr)) {
369 assert(!KillingInstr &&
"Should only see one killing instruction");
370 KilledOperand = I1UseReg;
378 bool Added =
I1.addRegisterKilled(KilledOperand,
TRI);
380 assert(Added &&
"Must successfully update kill flag");
382 DoInsertAtI1 =
false;
394 if (
MI.isDebugInstr())
402 if (!
Op.isReg() || !
Op.isUse() || !
Op.getReg())
416 unsigned NumInstsToDef = 0;
417 while (&*It != &
MI) {
418 if (!It->isDebugInstr())
426 PotentiallyNewifiableTFR.insert(DefInst);
436 if (!
Op.isDef() || !
Op.getReg())
439 if (Hexagon::DoubleRegsRegClass.
contains(Reg)) {
442 }
else if (Hexagon::IntRegsRegClass.
contains(Reg))
444 }
else if (
Op.isRegMask()) {
445 for (
unsigned Reg : Hexagon::IntRegsRegClass)
446 if (
Op.clobbersPhysReg(Reg))
459 bool HasChanged =
false;
463 TRI =
ST->getRegisterInfo();
464 TII =
ST->getInstrInfo();
467 bool OptForSize =
F.hasFnAttribute(Attribute::OptimizeForSize);
474 if (!OptForSize &&
ST->isTinyCore())
479 PotentiallyNewifiableTFR.clear();
480 findPotentialNewifiableTFRs(
MBB);
487 if (
I1.isDebugInstr())
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->isDebugInstr())
527 Register I1DestReg =
I1.getOperand(0).getReg();
532 if (I2->modifiesRegister(I1DestReg,
TRI))
543 Register 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))
560 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
571 bool DoInsertAtI1,
bool OptForSize) {
578 Register I1DestReg =
I1.getOperand(0).getReg();
580 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
581 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
585 if (Hexagon::IntRegsRegClass.
contains(LoRegDef)) {
586 SuperRC = &Hexagon::DoubleRegsRegClass;
587 SubLo = Hexagon::isub_lo;
588 }
else if (Hexagon::HvxVRRegClass.
contains(LoRegDef)) {
590 SuperRC = &Hexagon::HvxWRRegClass;
591 SubLo = Hexagon::vsub_lo;
596 unsigned DoubleRegDest =
TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
597 assert(DoubleRegDest != 0 &&
"Expect a valid register");
604 bool IsHiReg = HiOperand.
isReg();
605 bool IsLoReg = LoOperand.
isReg();
608 bool IsC64 = OptForSize && LoOperand.
isImm() && HiOperand.
isImm() &&
609 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
613 if (IsHiReg && IsLoReg)
614 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
616 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
618 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
620 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
622 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
626 if (!DoInsertAtI1 && DbgMItoMove.size() != 0) {
629 for (
auto *NewMI : DbgMItoMove) {
634 BB->
splice(InsertPt, BB, NewMI);
638 I1.eraseFromParent();
643 unsigned DoubleDestReg,
651 "Both operands must be immediate");
653 int64_t
V = HiOperand.
getImm();
654 V = (
V << 32) | (0x0ffffffffLL & LoOperand.
getImm());
655 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::CONST64), DoubleDestReg)
660 unsigned DoubleDestReg,
668 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
675 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
684 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
691 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
699 if (HiOperand.
isJTI()) {
700 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
705 if (LoOperand.
isJTI()) {
706 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
713 if (HiOperand.
isCPI()) {
714 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
720 if (LoOperand.
isCPI()) {
721 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
731 if (isInt<8>(LoOperand.
getImm())) {
732 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
739 if (isInt<8>(HiOperand.
getImm())) {
740 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineii), DoubleDestReg)
748 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A2_combineii), DoubleDestReg)
754 unsigned DoubleDestReg,
765 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
768 .
addReg(LoReg, LoRegKillFlag);
773 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
776 .
addReg(LoReg, LoRegKillFlag);
780 if (HiOperand.
isJTI()) {
781 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
783 .
addReg(LoReg, LoRegKillFlag);
787 if (HiOperand.
isCPI()) {
788 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
791 .
addReg(LoReg, LoRegKillFlag);
796 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineir), DoubleDestReg)
798 .
addReg(LoReg, LoRegKillFlag);
802 unsigned DoubleDestReg,
813 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
814 .
addReg(HiReg, HiRegKillFlag)
821 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
822 .
addReg(HiReg, HiRegKillFlag)
828 if (LoOperand.
isJTI()) {
829 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
835 if (LoOperand.
isCPI()) {
836 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
845 BuildMI(*BB, InsertPt,
DL,
TII->get(Hexagon::A4_combineri), DoubleDestReg)
846 .
addReg(HiReg, HiRegKillFlag)
851 unsigned DoubleDestReg,
865 if (Hexagon::DoubleRegsRegClass.
contains(DoubleDestReg)) {
866 NewOpc = Hexagon::A2_combinew;
867 }
else if (Hexagon::HvxWRRegClass.
contains(DoubleDestReg)) {
869 NewOpc = Hexagon::V6_vcombine;
873 BuildMI(*BB, InsertPt,
DL,
TII->get(NewOpc), DoubleDestReg)
874 .
addReg(HiReg, HiRegKillFlag)
875 .
addReg(LoReg, LoRegKillFlag);
879 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.
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
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.
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.
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 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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCopyToCombine()
unsigned getKillRegState(bool B)
void initializeHexagonCopyToCombinePass(PassRegistry &)