46 #define DEBUG_TYPE "a15-sd-optimizer"
55 StringRef getPassName()
const override {
return "ARM A15 S->D optimizer"; }
79 const DebugLoc &DL,
unsigned Ssub0,
unsigned Ssub1);
89 unsigned Lane,
unsigned ToInsert);
101 unsigned getDPRLaneFromSPR(
unsigned SReg);
114 unsigned optimizeAllLanesPattern(
MachineInstr *MI,
unsigned Reg);
116 unsigned getPrefSPRLane(
unsigned SReg);
126 std::map<MachineInstr*, unsigned> Replacements;
127 std::set<MachineInstr *> DeadInstr;
140 return MRI->getRegClass(Reg)->hasSuperClassEq(TRC);
145 unsigned A15SDOptimizer::getDPRLaneFromSPR(
unsigned SReg) {
146 unsigned DReg = TRI->getMatchingSuperReg(SReg, ARM::ssub_1,
148 if (DReg != ARM::NoRegister)
return ARM::ssub_1;
154 unsigned A15SDOptimizer::getPrefSPRLane(
unsigned SReg) {
155 if (!TRI->isVirtualRegister(SReg))
156 return getDPRLaneFromSPR(SReg);
159 if (!MI)
return ARM::ssub_0;
162 assert(MO->
isReg() &&
"Non-register operand found!");
163 if (!MO)
return ARM::ssub_0;
166 &ARM::SPRRegClass)) {
171 if (MO->
getSubReg() == ARM::ssub_1)
return ARM::ssub_1;
174 return getDPRLaneFromSPR(SReg);
179 void A15SDOptimizer::eraseInstrWithNoUses(
MachineInstr *MI) {
183 DEBUG(
dbgs() <<
"Deleting base instruction " << *MI <<
"\n");
186 while (Front.
size() != 0) {
196 unsigned Reg = MO.
getReg();
197 if (!TRI->isVirtualRegister(Reg))
208 if (DeadInstr.find(Def) != DeadInstr.end())
219 unsigned DefReg = MODef.
getReg();
220 if (!TRI->isVirtualRegister(DefReg)) {
225 II =
MRI->use_instr_begin(Reg), EE =
MRI->use_instr_end();
230 if (DeadInstr.find(&*II) == DeadInstr.end()) {
237 if (!IsDead)
continue;
239 DEBUG(
dbgs() <<
"Deleting instruction " << *Def <<
"\n");
240 DeadInstr.insert(Def);
247 unsigned A15SDOptimizer::optimizeSDPattern(
MachineInstr *MI) {
256 if (TRI->isVirtualRegister(DPRReg) && TRI->isVirtualRegister(SPRReg)) {
260 if (DPRMI && SPRMI) {
271 DEBUG(
dbgs() <<
"Found a subreg copy: " << *SPRMI);
279 DEBUG(
dbgs() <<
"Subreg copy is compatible - returning ");
281 eraseInstrWithNoUses(MI);
294 &ARM::SPRRegClass)) {
297 unsigned NumImplicit = 0, NumTotal = 0;
298 unsigned NonImplicitReg = ~0U;
306 if (!TRI->isVirtualRegister(OpReg))
318 if (NumImplicit == NumTotal - 1)
319 return optimizeAllLanesPattern(MI, NonImplicitReg);
329 bool A15SDOptimizer::hasPartialWrite(
MachineInstr *MI) {
355 return elideCopies(Def);
360 void A15SDOptimizer::elideCopiesAndPHIs(
MachineInstr *MI,
364 std::set<MachineInstr *> Reached;
367 while (Front.
size() != 0) {
372 if (Reached.find(MI) != Reached.end())
378 if (!TRI->isVirtualRegister(Reg)) {
394 DEBUG(
dbgs() <<
"Found partial copy" << *MI <<
"\n");
413 if (!usesRegClass(MO, &ARM::DPRRegClass) &&
414 !usesRegClass(MO, &ARM::QPRRegClass) &&
415 !usesRegClass(MO, &ARM::DPairRegClass))
427 unsigned Lane,
bool QPR) {
428 unsigned Out =
MRI->createVirtualRegister(QPR ? &ARM::QPRRegClass :
433 TII->get(QPR ? ARM::VDUPLN32q : ARM::VDUPLN32d),
442 unsigned A15SDOptimizer::createExtractSubreg(
444 const DebugLoc &DL,
unsigned DReg,
unsigned Lane,
446 unsigned Out =
MRI->createVirtualRegister(TRC);
450 TII->get(TargetOpcode::COPY), Out)
451 .addReg(DReg, 0, Lane);
457 unsigned A15SDOptimizer::createRegSequence(
459 const DebugLoc &DL,
unsigned Reg1,
unsigned Reg2) {
460 unsigned Out =
MRI->createVirtualRegister(&ARM::QPRRegClass);
464 TII->get(TargetOpcode::REG_SEQUENCE), Out)
478 unsigned Out =
MRI->createVirtualRegister(&ARM::DPRRegClass);
482 TII->get(ARM::VEXTd32), Out)
489 unsigned A15SDOptimizer::createInsertSubreg(
491 const DebugLoc &DL,
unsigned DReg,
unsigned Lane,
unsigned ToInsert) {
492 unsigned Out =
MRI->createVirtualRegister(&ARM::DPR_VFP2RegClass);
496 TII->get(TargetOpcode::INSERT_SUBREG), Out)
508 unsigned Out =
MRI->createVirtualRegister(&ARM::DPRRegClass);
512 TII->get(TargetOpcode::IMPLICIT_DEF), Out);
520 A15SDOptimizer::optimizeAllLanesPattern(
MachineInstr *MI,
unsigned Reg) {
529 if (
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::QPRRegClass) ||
530 MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPairRegClass)) {
531 unsigned DSub0 = createExtractSubreg(MBB, InsertPt, DL, Reg,
532 ARM::dsub_0, &ARM::DPRRegClass);
533 unsigned DSub1 = createExtractSubreg(MBB, InsertPt, DL, Reg,
534 ARM::dsub_1, &ARM::DPRRegClass);
536 unsigned Out1 = createDupLane(MBB, InsertPt, DL, DSub0, 0);
537 unsigned Out2 = createDupLane(MBB, InsertPt, DL, DSub0, 1);
538 Out = createVExt(MBB, InsertPt, DL, Out1, Out2);
540 unsigned Out3 = createDupLane(MBB, InsertPt, DL, DSub1, 0);
541 unsigned Out4 = createDupLane(MBB, InsertPt, DL, DSub1, 1);
542 Out2 = createVExt(MBB, InsertPt, DL, Out3, Out4);
544 Out = createRegSequence(MBB, InsertPt, DL, Out, Out2);
546 }
else if (
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPRRegClass)) {
547 unsigned Out1 = createDupLane(MBB, InsertPt, DL, Reg, 0);
548 unsigned Out2 = createDupLane(MBB, InsertPt, DL, Reg, 1);
549 Out = createVExt(MBB, InsertPt, DL, Out1, Out2);
552 assert(
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::SPRRegClass) &&
553 "Found unexpected regclass!");
555 unsigned PrefLane = getPrefSPRLane(Reg);
558 case ARM::ssub_0: Lane = 0;
break;
559 case ARM::ssub_1: Lane = 1;
break;
564 bool UsesQPR = usesRegClass(MI->
getOperand(0), &ARM::QPRRegClass) ||
565 usesRegClass(MI->
getOperand(0), &ARM::DPairRegClass);
567 Out = createImplicitDef(MBB, InsertPt, DL);
568 Out = createInsertSubreg(MBB, InsertPt, DL, Out, PrefLane, Reg);
569 Out = createDupLane(MBB, InsertPt, DL, Out, Lane, UsesQPR);
570 eraseInstrWithNoUses(MI);
575 bool A15SDOptimizer::runOnInstruction(
MachineInstr *MI) {
607 bool Modified =
false;
616 if (!TRI->isVirtualRegister(*
I))
622 elideCopiesAndPHIs(Def, DefSrcs);
625 EE = DefSrcs.
end(); II != EE; ++II) {
630 if (Replacements.find(MI) != Replacements.end())
634 if (!hasPartialWrite(MI))
641 E =
MRI->use_end();
I !=
E; ++
I)
645 unsigned NewReg = optimizeSDPattern(MI);
656 MRI->constrainRegClass(NewReg,
MRI->getRegClass((*I)->getReg()));
661 (*I)->substVirtReg(NewReg, 0, *TRI);
664 Replacements[
MI] = NewReg;
682 bool Modified =
false;
687 Replacements.clear();
694 Modified |= runOnInstruction(&*MI++);
699 for (std::set<MachineInstr *>::iterator
I = DeadInstr.begin(),
702 (*I)->eraseFromParent();
709 return new A15SDOptimizer();
void push_back(const T &Elt)
FunctionPass * createA15SDOptimizerPass()
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
MachineOperand * findRegisterDefOperand(unsigned Reg, bool isDead=false, const TargetRegisterInfo *TRI=nullptr)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
bool hasSuperClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
const ARMBaseInstrInfo * getInstrInfo() const override
static const MachineInstrBuilder & AddDefaultPred(const MachineInstrBuilder &MIB)
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
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Reg
All possible values of the reg field in the ModR/M byte.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
unsigned getNumOperands() const
Access to explicit operands of the instruction.
defusechain_iterator - This class provides iterator support for machine operands in the function that...
bool isCopyLike() const
Return true if the instruction behaves like a copy.
Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubRegIdx=0)
Prints virtual and physical registers with or without a TRI instance.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const MachineBasicBlock * getParent() const
bool isImplicitDef() const
bool isInsertSubreg() const
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
const MachineOperand & getOperand(unsigned i) const
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
FunctionPass class - This class is used to implement most global optimizations.
unsigned getSubReg() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
MachineOperand class - Representation of each machine instruction operand.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
iterator insert(iterator I, T &&Elt)
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
bool isRegSequence() const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
reg_begin/reg_end - Provide iteration support to walk over all definitions and uses of a register wit...
bool contains(unsigned Reg) const
Return true if the specified register is included in this register class.