45#define DEBUG_TYPE "a15-sd-optimizer"
68 const DebugLoc &
DL,
unsigned Reg,
unsigned Lane,
78 const DebugLoc &
DL,
unsigned Ssub0,
unsigned Ssub1);
88 unsigned Lane,
unsigned ToInsert);
100 unsigned getDPRLaneFromSPR(
unsigned SReg);
115 unsigned getPrefSPRLane(
unsigned SReg);
125 std::map<MachineInstr*, unsigned> Replacements;
126 std::set<MachineInstr *> DeadInstr;
128 char A15SDOptimizer::ID = 0;
139 return MRI->getRegClass(Reg)->hasSuperClassEq(TRC);
144unsigned A15SDOptimizer::getDPRLaneFromSPR(
unsigned SReg) {
145 unsigned DReg =
TRI->getMatchingSuperReg(SReg, ARM::ssub_1,
147 if (DReg != ARM::NoRegister)
return ARM::ssub_1;
153unsigned A15SDOptimizer::getPrefSPRLane(
unsigned SReg) {
155 return getDPRLaneFromSPR(SReg);
158 if (!
MI)
return ARM::ssub_0;
160 if (!MO)
return ARM::ssub_0;
161 assert(MO->
isReg() &&
"Non-register operand found!");
163 if (
MI->isCopy() && usesRegClass(
MI->getOperand(1),
164 &ARM::SPRRegClass)) {
165 SReg =
MI->getOperand(1).getReg();
169 if (MO->
getSubReg() == ARM::ssub_1)
return ARM::ssub_1;
172 return getDPRLaneFromSPR(SReg);
184 while (Front.
size() != 0) {
193 if (!
Reg.isVirtual())
204 if (DeadInstr.find(Def) != DeadInstr.end())
212 if ((!MODef.isReg()) || (!MODef.isDef()))
223 if (DeadInstr.find(&
Use) == DeadInstr.end()) {
233 DeadInstr.insert(Def);
242 return optimizeAllLanesPattern(
MI,
MI->getOperand(1).getReg());
245 if (
MI->isInsertSubreg()) {
253 if (DPRMI && SPRMI) {
262 if (EC &&
EC->isCopy() &&
263 EC->getOperand(1).getSubReg() == ARM::ssub_0) {
270 MRI->getRegClass(
MI->getOperand(1).getReg());
274 eraseInstrWithNoUses(
MI);
279 return optimizeAllLanesPattern(
MI,
MI->getOperand(2).getReg());
283 return optimizeAllLanesPattern(
MI,
MI->getOperand(0).getReg());
286 if (
MI->isRegSequence() && usesRegClass(
MI->getOperand(1),
287 &ARM::SPRRegClass)) {
290 unsigned NumImplicit = 0, NumTotal = 0;
291 unsigned NonImplicitReg = ~0
U;
305 if (
Def->isImplicitDef())
308 NonImplicitReg = MO.
getReg();
311 if (NumImplicit == NumTotal - 1)
312 return optimizeAllLanesPattern(
MI, NonImplicitReg);
314 return optimizeAllLanesPattern(
MI,
MI->getOperand(0).getReg());
325 if (
MI->isCopy() && usesRegClass(
MI->getOperand(1), &ARM::SPRRegClass))
328 if (
MI->isInsertSubreg() && usesRegClass(
MI->getOperand(2),
332 if (
MI->isRegSequence() && usesRegClass(
MI->getOperand(1), &ARM::SPRRegClass))
341 if (!
MI->isFullCopy())
343 if (!
MI->getOperand(1).getReg().isVirtual())
348 return elideCopies(Def);
357 std::set<MachineInstr *> Reached;
360 while (Front.
size() != 0) {
364 if (!Reached.insert(
MI).second)
367 for (
unsigned I = 1, E =
MI->getNumOperands();
I != E;
I += 2) {
369 if (!
Reg.isVirtual()) {
377 }
else if (
MI->isFullCopy()) {
378 if (!
MI->getOperand(1).getReg().isVirtual())
394 if (
MI->isCopyLike() ||
MI->isInsertSubreg() ||
MI->isRegSequence() ||
402 if (!usesRegClass(MO, &ARM::DPRRegClass) &&
403 !usesRegClass(MO, &ARM::QPRRegClass) &&
404 !usesRegClass(MO, &ARM::DPairRegClass))
416 unsigned Lane,
bool QPR) {
418 MRI->createVirtualRegister(QPR ? &ARM::QPRRegClass : &ARM::DPRRegClass);
420 TII->get(QPR ? ARM::VDUPLN32q : ARM::VDUPLN32d), Out)
429unsigned A15SDOptimizer::createExtractSubreg(
431 const DebugLoc &
DL,
unsigned DReg,
unsigned Lane,
437 TII->get(TargetOpcode::COPY), Out)
444unsigned A15SDOptimizer::createRegSequence(
446 const DebugLoc &
DL,
unsigned Reg1,
unsigned Reg2) {
447 Register Out =
MRI->createVirtualRegister(&ARM::QPRRegClass);
451 TII->get(TargetOpcode::REG_SEQUENCE), Out)
465 Register Out =
MRI->createVirtualRegister(&ARM::DPRRegClass);
474unsigned A15SDOptimizer::createInsertSubreg(
476 const DebugLoc &
DL,
unsigned DReg,
unsigned Lane,
unsigned ToInsert) {
477 Register Out =
MRI->createVirtualRegister(&ARM::DPR_VFP2RegClass);
481 TII->get(TargetOpcode::INSERT_SUBREG), Out)
493 Register Out =
MRI->createVirtualRegister(&ARM::DPRRegClass);
497 TII->get(TargetOpcode::IMPLICIT_DEF), Out);
505A15SDOptimizer::optimizeAllLanesPattern(
MachineInstr *
MI,
unsigned Reg) {
514 if (
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::QPRRegClass) ||
515 MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPairRegClass)) {
516 unsigned DSub0 = createExtractSubreg(
MBB, InsertPt,
DL, Reg,
517 ARM::dsub_0, &ARM::DPRRegClass);
518 unsigned DSub1 = createExtractSubreg(
MBB, InsertPt,
DL, Reg,
519 ARM::dsub_1, &ARM::DPRRegClass);
521 unsigned Out1 = createDupLane(
MBB, InsertPt,
DL, DSub0, 0);
522 unsigned Out2 = createDupLane(
MBB, InsertPt,
DL, DSub0, 1);
523 Out = createVExt(
MBB, InsertPt,
DL, Out1, Out2);
525 unsigned Out3 = createDupLane(
MBB, InsertPt,
DL, DSub1, 0);
526 unsigned Out4 = createDupLane(
MBB, InsertPt,
DL, DSub1, 1);
527 Out2 = createVExt(
MBB, InsertPt,
DL, Out3, Out4);
529 Out = createRegSequence(
MBB, InsertPt,
DL, Out, Out2);
531 }
else if (
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPRRegClass)) {
532 unsigned Out1 = createDupLane(
MBB, InsertPt,
DL, Reg, 0);
533 unsigned Out2 = createDupLane(
MBB, InsertPt,
DL, Reg, 1);
534 Out = createVExt(
MBB, InsertPt,
DL, Out1, Out2);
537 assert(
MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::SPRRegClass) &&
538 "Found unexpected regclass!");
540 unsigned PrefLane = getPrefSPRLane(Reg);
543 case ARM::ssub_0: Lane = 0;
break;
544 case ARM::ssub_1: Lane = 1;
break;
549 bool UsesQPR = usesRegClass(
MI->getOperand(0), &ARM::QPRRegClass) ||
550 usesRegClass(
MI->getOperand(0), &ARM::DPairRegClass);
552 Out = createImplicitDef(
MBB, InsertPt,
DL);
553 Out = createInsertSubreg(
MBB, InsertPt,
DL, Out, PrefLane, Reg);
554 Out = createDupLane(
MBB, InsertPt,
DL, Out, Lane, UsesQPR);
555 eraseInstrWithNoUses(
MI);
594 for (
unsigned I : Defs) {
606 elideCopiesAndPHIs(Def, DefSrcs);
611 if (Replacements.find(
MI) != Replacements.end())
615 if (!hasPartialWrite(
MI))
620 Register DPRDefReg =
MI->getOperand(0).getReg();
625 unsigned NewReg = optimizeSDPattern(
MI);
635 MRI->constrainRegClass(NewReg,
MRI->getRegClass(
Use->getReg()));
639 Use->substVirtReg(NewReg, 0, *
TRI);
642 Replacements[
MI] = NewReg;
655 if (!(STI.useSplatVFPToNeon() && STI.hasNEON()))
666 Replacements.clear();
675 MI->eraseFromParent();
682 return new A15SDOptimizer();
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Rewrite Partial Register Uses
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
const ARMBaseInstrInfo * getInstrInfo() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
bool isImplicitDef() const
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
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.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
bool hasSuperClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A Use represents the edge between a Value definition and its users.
#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.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createA15SDOptimizerPass()
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.