46 #define DEBUG_TYPE "a15-sd-optimizer"
55 const char *getPassName()
const override {
56 return "ARM A15 S->D optimizer";
72 unsigned Reg,
unsigned Lane,
78 unsigned DReg,
unsigned Lane,
84 unsigned Ssub0,
unsigned Ssub1);
89 unsigned Reg1,
unsigned Reg2);
93 DebugLoc DL,
unsigned DReg,
unsigned Lane,
106 unsigned getDPRLaneFromSPR(
unsigned SReg);
119 unsigned optimizeAllLanesPattern(
MachineInstr *MI,
unsigned Reg);
121 unsigned getPrefSPRLane(
unsigned SReg);
131 std::map<MachineInstr*, unsigned> Replacements;
132 std::set<MachineInstr *> DeadInstr;
145 return MRI->getRegClass(Reg)->hasSuperClassEq(TRC);
150 unsigned A15SDOptimizer::getDPRLaneFromSPR(
unsigned SReg) {
151 unsigned DReg = TRI->getMatchingSuperReg(SReg, ARM::ssub_1,
153 if (DReg != ARM::NoRegister)
return ARM::ssub_1;
159 unsigned A15SDOptimizer::getPrefSPRLane(
unsigned SReg) {
160 if (!TRI->isVirtualRegister(SReg))
161 return getDPRLaneFromSPR(SReg);
164 if (!MI)
return ARM::ssub_0;
167 assert(MO->
isReg() &&
"Non-register operand found!");
168 if (!MO)
return ARM::ssub_0;
171 &ARM::SPRRegClass)) {
176 if (MO->
getSubReg() == ARM::ssub_1)
return ARM::ssub_1;
179 return getDPRLaneFromSPR(SReg);
184 void A15SDOptimizer::eraseInstrWithNoUses(
MachineInstr *MI) {
188 DEBUG(
dbgs() <<
"Deleting base instruction " << *MI <<
"\n");
191 while (Front.
size() != 0) {
201 unsigned Reg = MO.
getReg();
202 if (!TRI->isVirtualRegister(Reg))
213 if (DeadInstr.find(Def) != DeadInstr.end())
224 unsigned DefReg = MODef.
getReg();
225 if (!TRI->isVirtualRegister(DefReg)) {
230 II = MRI->use_instr_begin(Reg), EE = MRI->use_instr_end();
235 if (DeadInstr.find(&*II) == DeadInstr.end()) {
242 if (!IsDead)
continue;
244 DEBUG(
dbgs() <<
"Deleting instruction " << *Def <<
"\n");
245 DeadInstr.insert(Def);
252 unsigned A15SDOptimizer::optimizeSDPattern(
MachineInstr *MI) {
261 if (TRI->isVirtualRegister(DPRReg) && TRI->isVirtualRegister(SPRReg)) {
265 if (DPRMI && SPRMI) {
276 DEBUG(
dbgs() <<
"Found a subreg copy: " << *SPRMI);
284 DEBUG(
dbgs() <<
"Subreg copy is compatible - returning ");
286 eraseInstrWithNoUses(MI);
299 &ARM::SPRRegClass)) {
302 unsigned NumImplicit = 0, NumTotal = 0;
303 unsigned NonImplicitReg = ~0U;
311 if (!TRI->isVirtualRegister(OpReg))
323 if (NumImplicit == NumTotal - 1)
324 return optimizeAllLanesPattern(MI, NonImplicitReg);
334 bool A15SDOptimizer::hasPartialWrite(
MachineInstr *MI) {
360 return elideCopies(Def);
365 void A15SDOptimizer::elideCopiesAndPHIs(
MachineInstr *MI,
369 std::set<MachineInstr *> Reached;
372 while (Front.
size() != 0) {
377 if (Reached.find(MI) != Reached.end())
383 if (!TRI->isVirtualRegister(Reg)) {
399 DEBUG(
dbgs() <<
"Found partial copy" << *MI <<
"\n");
418 if (!usesRegClass(MO, &ARM::DPRRegClass) &&
419 !usesRegClass(MO, &ARM::QPRRegClass) &&
420 !usesRegClass(MO, &ARM::DPairRegClass))
433 unsigned Reg,
unsigned Lane,
bool QPR) {
434 unsigned Out = MRI->createVirtualRegister(QPR ? &ARM::QPRRegClass :
439 TII->get(QPR ? ARM::VDUPLN32q : ARM::VDUPLN32d),
452 unsigned DReg,
unsigned Lane,
454 unsigned Out = MRI->createVirtualRegister(TRC);
459 .addReg(DReg, 0, Lane);
469 unsigned Reg1,
unsigned Reg2) {
470 unsigned Out = MRI->createVirtualRegister(&ARM::QPRRegClass);
488 unsigned Ssub0,
unsigned Ssub1) {
489 unsigned Out = MRI->createVirtualRegister(&ARM::DPRRegClass);
493 TII->get(ARM::VEXTd32), Out)
503 DebugLoc DL,
unsigned DReg,
unsigned Lane,
505 unsigned Out = MRI->createVirtualRegister(&ARM::DPR_VFP2RegClass);
521 unsigned Out = MRI->createVirtualRegister(&ARM::DPRRegClass);
533 A15SDOptimizer::optimizeAllLanesPattern(
MachineInstr *MI,
unsigned Reg) {
542 if (MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::QPRRegClass) ||
543 MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPairRegClass)) {
544 unsigned DSub0 = createExtractSubreg(MBB, InsertPt, DL, Reg,
545 ARM::dsub_0, &ARM::DPRRegClass);
546 unsigned DSub1 = createExtractSubreg(MBB, InsertPt, DL, Reg,
547 ARM::dsub_1, &ARM::DPRRegClass);
549 unsigned Out1 = createDupLane(MBB, InsertPt, DL, DSub0, 0);
550 unsigned Out2 = createDupLane(MBB, InsertPt, DL, DSub0, 1);
551 Out = createVExt(MBB, InsertPt, DL, Out1, Out2);
553 unsigned Out3 = createDupLane(MBB, InsertPt, DL, DSub1, 0);
554 unsigned Out4 = createDupLane(MBB, InsertPt, DL, DSub1, 1);
555 Out2 = createVExt(MBB, InsertPt, DL, Out3, Out4);
557 Out = createRegSequence(MBB, InsertPt, DL, Out, Out2);
559 }
else if (MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::DPRRegClass)) {
560 unsigned Out1 = createDupLane(MBB, InsertPt, DL, Reg, 0);
561 unsigned Out2 = createDupLane(MBB, InsertPt, DL, Reg, 1);
562 Out = createVExt(MBB, InsertPt, DL, Out1, Out2);
565 assert(MRI->getRegClass(Reg)->hasSuperClassEq(&ARM::SPRRegClass) &&
566 "Found unexpected regclass!");
568 unsigned PrefLane = getPrefSPRLane(Reg);
571 case ARM::ssub_0: Lane = 0;
break;
572 case ARM::ssub_1: Lane = 1;
break;
577 bool UsesQPR = usesRegClass(MI->
getOperand(0), &ARM::QPRRegClass) ||
578 usesRegClass(MI->
getOperand(0), &ARM::DPairRegClass);
580 Out = createImplicitDef(MBB, InsertPt, DL);
581 Out = createInsertSubreg(MBB, InsertPt, DL, Out, PrefLane, Reg);
582 Out = createDupLane(MBB, InsertPt, DL, Out, Lane, UsesQPR);
583 eraseInstrWithNoUses(MI);
588 bool A15SDOptimizer::runOnInstruction(
MachineInstr *MI) {
620 bool Modified =
false;
629 if (!TRI->isVirtualRegister(*
I))
635 elideCopiesAndPHIs(Def, DefSrcs);
638 EE = DefSrcs.
end(); II != EE; ++II) {
643 if (Replacements.find(MI) != Replacements.end())
647 if (!hasPartialWrite(MI))
654 E = MRI->use_end();
I != E; ++
I)
658 unsigned NewReg = optimizeSDPattern(MI);
663 E = Uses.
end();
I != E; ++
I) {
669 MRI->constrainRegClass(NewReg, MRI->getRegClass((*I)->getReg()));
674 (*I)->substVirtReg(NewReg, 0, *TRI);
677 Replacements[
MI] = NewReg;
692 bool Modified =
false;
697 Replacements.clear();
704 Modified |= runOnInstruction(MI++);
709 for (std::set<MachineInstr *>::iterator
I = DeadInstr.begin(),
712 (*I)->eraseFromParent();
719 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)
isVirtualRegister - Return true if the specified register number is in the virtual register namespace...
bool hasSuperClassEq(const TargetRegisterClass *RC) const
hasSuperClassEq - Returns true if RC is a super-class of or equal to this class.
const ARMBaseInstrInfo * getInstrInfo() const override
COPY - Target-independent register copy.
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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
addImm - 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...
PrintReg - Helper class for printing registers on a raw_ostream.
bool isCopyLike() const
Return true if the instruction behaves like a copy.
const MachineBasicBlock * getParent() const
bool isImplicitDef() const
bool isInsertSubreg() const
IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef.
bundle_iterator< MachineInstr, instr_iterator > iterator
const MachineOperand & getOperand(unsigned i) const
INSERT_SUBREG - This instruction takes three operands: a register that has subregisters, a register providing an insert value, and a subregister index.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
unsigned getSubReg() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
REG_SEQUENCE - This variadic instruction is used to form a register that represents a consecutive seq...
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const ARMBaseRegisterInfo * getRegisterInfo() const override
unsigned getReg() const
getReg - Returns the register number.
BasicBlockListType::iterator iterator
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
addReg - 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
contains - Return true if the specified register is included in this register class.