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);
183 LLVM_DEBUG(
dbgs() <<
"Deleting base instruction " << *MI <<
"\n");
186 while (Front.
size() != 0) {
196 if (!
TRI->isVirtualRegister(Reg))
207 if (DeadInstr.find(Def) != DeadInstr.end())
215 if ((!MODef.isReg()) || (!MODef.isDef()))
217 unsigned DefReg = MODef.getReg();
218 if (!
TRI->isVirtualRegister(DefReg)) {
226 if (DeadInstr.find(&
Use) == DeadInstr.end()) {
233 if (!IsDead)
continue;
236 DeadInstr.insert(Def);
243 unsigned A15SDOptimizer::optimizeSDPattern(
MachineInstr *MI) {
252 if (
TRI->isVirtualRegister(DPRReg) &&
TRI->isVirtualRegister(SPRReg)) {
256 if (DPRMI && SPRMI) {
277 eraseInstrWithNoUses(MI);
290 &ARM::SPRRegClass)) {
293 unsigned NumImplicit = 0, NumTotal = 0;
294 unsigned NonImplicitReg = ~0U;
302 if (!
TRI->isVirtualRegister(OpReg))
314 if (NumImplicit == NumTotal - 1)
315 return optimizeAllLanesPattern(MI, NonImplicitReg);
325 bool A15SDOptimizer::hasPartialWrite(
MachineInstr *MI) {
351 return elideCopies(Def);
356 void A15SDOptimizer::elideCopiesAndPHIs(
MachineInstr *MI,
360 std::set<MachineInstr *> Reached;
363 while (Front.
size() != 0) {
368 if (Reached.find(MI) != Reached.end())
374 if (!
TRI->isVirtualRegister(Reg)) {
407 if (!usesRegClass(MO, &ARM::DPRRegClass) &&
408 !usesRegClass(MO, &ARM::QPRRegClass) &&
409 !usesRegClass(MO, &ARM::DPairRegClass))
421 unsigned Lane,
bool QPR) {
422 unsigned Out =
MRI->createVirtualRegister(QPR ? &ARM::QPRRegClass :
425 TII->get(QPR ? ARM::VDUPLN32q : ARM::VDUPLN32d), Out)
434 unsigned A15SDOptimizer::createExtractSubreg(
436 const DebugLoc &DL,
unsigned DReg,
unsigned Lane,
438 unsigned Out =
MRI->createVirtualRegister(TRC);
442 TII->get(TargetOpcode::COPY), Out)
443 .addReg(DReg, 0, Lane);
449 unsigned A15SDOptimizer::createRegSequence(
451 const DebugLoc &DL,
unsigned Reg1,
unsigned Reg2) {
452 unsigned Out =
MRI->createVirtualRegister(&ARM::QPRRegClass);
456 TII->get(TargetOpcode::REG_SEQUENCE), Out)
470 unsigned Out =
MRI->createVirtualRegister(&ARM::DPRRegClass);
471 BuildMI(MBB, InsertBefore, DL,
TII->get(ARM::VEXTd32), Out)
479 unsigned A15SDOptimizer::createInsertSubreg(
481 const DebugLoc &DL,
unsigned DReg,
unsigned Lane,
unsigned ToInsert) {
482 unsigned Out =
MRI->createVirtualRegister(&ARM::DPR_VFP2RegClass);
486 TII->get(TargetOpcode::INSERT_SUBREG), Out)
498 unsigned Out =
MRI->createVirtualRegister(&ARM::DPRRegClass);
502 TII->get(TargetOpcode::IMPLICIT_DEF), Out);
510 A15SDOptimizer::optimizeAllLanesPattern(
MachineInstr *MI,
unsigned Reg) {
519 if (
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::QPRRegClass) ||
520 MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPairRegClass)) {
521 unsigned DSub0 = createExtractSubreg(MBB, InsertPt, DL, Reg,
522 ARM::dsub_0, &ARM::DPRRegClass);
523 unsigned DSub1 = createExtractSubreg(MBB, InsertPt, DL, Reg,
524 ARM::dsub_1, &ARM::DPRRegClass);
526 unsigned Out1 = createDupLane(MBB, InsertPt, DL, DSub0, 0);
527 unsigned Out2 = createDupLane(MBB, InsertPt, DL, DSub0, 1);
528 Out = createVExt(MBB, InsertPt, DL, Out1, Out2);
530 unsigned Out3 = createDupLane(MBB, InsertPt, DL, DSub1, 0);
531 unsigned Out4 = createDupLane(MBB, InsertPt, DL, DSub1, 1);
532 Out2 = createVExt(MBB, InsertPt, DL, Out3, Out4);
534 Out = createRegSequence(MBB, InsertPt, DL, Out, Out2);
536 }
else if (
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPRRegClass)) {
537 unsigned Out1 = createDupLane(MBB, InsertPt, DL, Reg, 0);
538 unsigned Out2 = createDupLane(MBB, InsertPt, DL, Reg, 1);
539 Out = createVExt(MBB, InsertPt, DL, Out1, Out2);
542 assert(
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::SPRRegClass) &&
543 "Found unexpected regclass!");
545 unsigned PrefLane = getPrefSPRLane(Reg);
548 case ARM::ssub_0: Lane = 0;
break;
549 case ARM::ssub_1: Lane = 1;
break;
554 bool UsesQPR = usesRegClass(MI->
getOperand(0), &ARM::QPRRegClass) ||
555 usesRegClass(MI->
getOperand(0), &ARM::DPairRegClass);
557 Out = createImplicitDef(MBB, InsertPt, DL);
558 Out = createInsertSubreg(MBB, InsertPt, DL, Out, PrefLane, Reg);
559 Out = createDupLane(MBB, InsertPt, DL, Out, Lane, UsesQPR);
560 eraseInstrWithNoUses(MI);
565 bool A15SDOptimizer::runOnInstruction(
MachineInstr *MI) {
606 if (!
TRI->isVirtualRegister(*
I))
612 elideCopiesAndPHIs(Def, DefSrcs);
617 if (Replacements.find(MI) != Replacements.end())
621 if (!hasPartialWrite(MI))
628 E =
MRI->use_end();
I !=
E; ++
I)
632 unsigned NewReg = optimizeSDPattern(MI);
643 MRI->constrainRegClass(NewReg,
MRI->getRegClass((*I)->getReg()));
647 (*I)->substVirtReg(NewReg, 0, *
TRI);
650 Replacements[
MI] = NewReg;
674 Replacements.clear();
678 Modified |= runOnInstruction(&MI);
690 return new A15SDOptimizer();
const MachineInstrBuilder & add(const MachineOperand &MO) const
FunctionPass * createA15SDOptimizerPass()
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool contains(unsigned Reg) const
Return true if the specified register is included in this register class.
typename SuperClass::const_iterator const_iterator
This class represents lattice values for constants.
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...
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
unsigned getSubReg() const
bool isRegSequence() const
unsigned const TargetRegisterInfo * TRI
iterator_range< mop_iterator > operands()
bool isCopyLike() const
Return true if the instruction behaves like a copy.
const ARMBaseInstrInfo * getInstrInfo() const override
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
A Use represents the edge between a Value definition and its users.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
bool hasSuperClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
FunctionPass class - This class is used to implement most global optimizations.
bool isImplicitDef() 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.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
MachineOperand class - Representation of each machine instruction operand.
bool isInsertSubreg() const
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator insert(iterator I, T &&Elt)
const MachineBasicBlock * getParent() const
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()
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool useSplatVFPToNeon() const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
const MachineOperand & getOperand(unsigned i) const
reg_begin/reg_end - Provide iteration support to walk over all definitions and uses of a register wit...