46#define DEBUG_TYPE "a15-sd-optimizer"
55 StringRef getPassName()
const override {
return "ARM A15 S->D optimizer"; }
84 const DebugLoc &
DL,
unsigned Ssub0,
unsigned Ssub1);
94 unsigned Lane,
unsigned ToInsert);
106 unsigned getDPRLaneFromSPR(
unsigned SReg);
121 unsigned getPrefSPRLane(
unsigned SReg);
131 std::map<MachineInstr*, unsigned> Replacements;
132 std::set<MachineInstr *> DeadInstr;
134 char A15SDOptimizer::ID = 0;
150unsigned A15SDOptimizer::getDPRLaneFromSPR(
unsigned SReg) {
152 TRI->getMatchingSuperReg(SReg, ARM::ssub_1, &ARM::DPRRegClass);
160unsigned A15SDOptimizer::getPrefSPRLane(
unsigned SReg) {
161 if (!Register::isVirtualRegister(SReg))
162 return getDPRLaneFromSPR(SReg);
165 if (!
MI)
return ARM::ssub_0;
166 MachineOperand *MO =
MI->findRegisterDefOperand(SReg,
nullptr);
167 if (!MO)
return ARM::ssub_0;
168 assert(MO->
isReg() &&
"Non-register operand found!");
170 if (
MI->isCopy() && usesRegClass(
MI->getOperand(1),
171 &ARM::SPRRegClass)) {
172 SReg =
MI->getOperand(1).getReg();
175 if (Register::isVirtualRegister(SReg)) {
176 if (MO->
getSubReg() == ARM::ssub_1)
return ARM::ssub_1;
179 return getDPRLaneFromSPR(SReg);
184void A15SDOptimizer::eraseInstrWithNoUses(MachineInstr *
MI) {
185 SmallVector<MachineInstr *, 8> Front;
186 DeadInstr.insert(
MI);
191 while (Front.
size() != 0) {
196 for (MachineOperand &MO :
MI->operands()) {
202 MachineOperand *
Op =
MI->findRegisterDefOperand(
Reg,
nullptr);
207 MachineInstr *
Def =
Op->getParent();
211 if (DeadInstr.find(Def) != DeadInstr.end())
218 for (MachineOperand &MODef :
Def->operands()) {
219 if ((!MODef.isReg()) || (!MODef.isDef()))
230 if (DeadInstr.find(&Use) == DeadInstr.end()) {
240 DeadInstr.insert(Def);
247unsigned A15SDOptimizer::optimizeSDPattern(MachineInstr *
MI) {
249 return optimizeAllLanesPattern(
MI,
MI->getOperand(1).getReg());
252 if (
MI->isInsertSubreg()) {
257 MachineInstr *DPRMI = MRI->
getVRegDef(
MI->getOperand(1).getReg());
258 MachineInstr *SPRMI = MRI->
getVRegDef(
MI->getOperand(2).getReg());
260 if (DPRMI && SPRMI) {
262 MachineInstr *ECDef = elideCopies(DPRMI);
267 MachineInstr *
EC = elideCopies(SPRMI);
269 if (EC &&
EC->isCopy() &&
270 EC->getOperand(1).getSubReg() == ARM::ssub_0) {
281 eraseInstrWithNoUses(
MI);
286 return optimizeAllLanesPattern(
MI,
MI->getOperand(2).getReg());
290 return optimizeAllLanesPattern(
MI,
MI->getOperand(0).getReg());
293 if (
MI->isRegSequence() && usesRegClass(
MI->getOperand(1),
294 &ARM::SPRRegClass)) {
297 unsigned NumImplicit = 0, NumTotal = 0;
298 unsigned NonImplicitReg = ~0
U;
312 if (
Def->isImplicitDef())
315 NonImplicitReg = MO.
getReg();
318 if (NumImplicit == NumTotal - 1)
319 return optimizeAllLanesPattern(
MI, NonImplicitReg);
321 return optimizeAllLanesPattern(
MI,
MI->getOperand(0).getReg());
329bool A15SDOptimizer::hasPartialWrite(MachineInstr *
MI) {
332 if (
MI->isCopy() && usesRegClass(
MI->getOperand(1), &ARM::SPRRegClass))
335 if (
MI->isInsertSubreg() && usesRegClass(
MI->getOperand(2),
339 if (
MI->isRegSequence() && usesRegClass(
MI->getOperand(1), &ARM::SPRRegClass))
347MachineInstr *A15SDOptimizer::elideCopies(MachineInstr *
MI) {
348 if (!
MI->isFullCopy())
350 if (!
MI->getOperand(1).getReg().isVirtual())
355 return elideCopies(Def);
360void A15SDOptimizer::elideCopiesAndPHIs(MachineInstr *
MI,
361 SmallVectorImpl<MachineInstr*> &Outs) {
364 std::set<MachineInstr *> Reached;
365 SmallVector<MachineInstr *, 8> Front;
367 while (Front.
size() != 0) {
371 if (!Reached.insert(
MI).second)
374 for (
unsigned I = 1,
E =
MI->getNumOperands();
I !=
E;
I += 2) {
384 }
else if (
MI->isFullCopy()) {
385 if (!
MI->getOperand(1).getReg().isVirtual())
387 MachineInstr *NewMI = MRI->
getVRegDef(
MI->getOperand(1).getReg());
400SmallVector<unsigned, 8> A15SDOptimizer::getReadDPRs(MachineInstr *
MI) {
401 if (
MI->isCopyLike() ||
MI->isInsertSubreg() ||
MI->isRegSequence() ||
403 return SmallVector<unsigned, 8>();
405 SmallVector<unsigned, 8> Defs;
406 for (MachineOperand &MO :
MI->operands()) {
409 if (!usesRegClass(MO, &ARM::DPRRegClass) &&
410 !usesRegClass(MO, &ARM::QPRRegClass) &&
411 !usesRegClass(MO, &ARM::DPairRegClass))
420unsigned A15SDOptimizer::createDupLane(MachineBasicBlock &
MBB,
423 unsigned Lane,
bool QPR) {
427 TII->get(QPR ? ARM::VDUPLN32q : ARM::VDUPLN32d), Out)
436unsigned A15SDOptimizer::createExtractSubreg(
438 const DebugLoc &
DL,
unsigned DReg,
unsigned Lane,
448unsigned A15SDOptimizer::createRegSequence(
450 const DebugLoc &
DL,
unsigned Reg1,
unsigned Reg2) {
455 TII->get(TargetOpcode::REG_SEQUENCE), Out)
465unsigned A15SDOptimizer::createVExt(MachineBasicBlock &
MBB,
478unsigned A15SDOptimizer::createInsertSubreg(
480 const DebugLoc &
DL,
unsigned DReg,
unsigned Lane,
unsigned ToInsert) {
485 TII->get(TargetOpcode::INSERT_SUBREG), Out)
494A15SDOptimizer::createImplicitDef(MachineBasicBlock &
MBB,
501 TII->get(TargetOpcode::IMPLICIT_DEF), Out);
509A15SDOptimizer::optimizeAllLanesPattern(MachineInstr *
MI,
unsigned Reg) {
512 MachineBasicBlock &
MBB = *
MI->getParent();
520 unsigned DSub0 = createExtractSubreg(
MBB, InsertPt,
DL,
Reg,
521 ARM::dsub_0, &ARM::DPRRegClass);
522 unsigned DSub1 = createExtractSubreg(
MBB, InsertPt,
DL,
Reg,
523 ARM::dsub_1, &ARM::DPRRegClass);
525 unsigned Out1 = createDupLane(
MBB, InsertPt,
DL, DSub0, 0);
526 unsigned Out2 = createDupLane(
MBB, InsertPt,
DL, DSub0, 1);
527 Out = createVExt(
MBB, InsertPt,
DL, Out1, Out2);
529 unsigned Out3 = createDupLane(
MBB, InsertPt,
DL, DSub1, 0);
530 unsigned Out4 = createDupLane(
MBB, InsertPt,
DL, DSub1, 1);
531 Out2 = createVExt(
MBB, InsertPt,
DL, Out3, Out4);
533 Out = createRegSequence(
MBB, InsertPt,
DL, Out, Out2);
536 unsigned Out1 = createDupLane(
MBB, InsertPt,
DL,
Reg, 0);
537 unsigned Out2 = createDupLane(
MBB, InsertPt,
DL,
Reg, 1);
538 Out = createVExt(
MBB, InsertPt,
DL, Out1, Out2);
542 "Found unexpected regclass!");
544 unsigned PrefLane = getPrefSPRLane(
Reg);
547 case ARM::ssub_0: Lane = 0;
break;
548 case ARM::ssub_1: Lane = 1;
break;
553 bool UsesQPR = usesRegClass(
MI->getOperand(0), &ARM::QPRRegClass) ||
554 usesRegClass(
MI->getOperand(0), &ARM::DPairRegClass);
556 Out = createImplicitDef(
MBB, InsertPt,
DL);
557 Out = createInsertSubreg(
MBB, InsertPt,
DL, Out, PrefLane,
Reg);
558 Out = createDupLane(
MBB, InsertPt,
DL, Out, Lane, UsesQPR);
559 eraseInstrWithNoUses(
MI);
564bool A15SDOptimizer::runOnInstruction(MachineInstr *
MI) {
595 SmallVector<unsigned, 8> Defs = getReadDPRs(
MI);
598 for (
unsigned I : Defs) {
603 SmallVector<MachineInstr *, 8> DefSrcs;
604 if (!Register::isVirtualRegister(
I))
610 elideCopiesAndPHIs(Def, DefSrcs);
612 for (MachineInstr *
MI : DefSrcs) {
615 if (Replacements.find(
MI) != Replacements.end())
619 if (!hasPartialWrite(
MI))
623 Register DPRDefReg =
MI->getOperand(0).getReg();
628 unsigned NewReg = optimizeSDPattern(
MI);
632 for (MachineOperand *Use :
Uses) {
642 Use->substVirtReg(NewReg, 0, *
TRI);
645 Replacements[
MI] = NewReg;
651bool A15SDOptimizer::runOnMachineFunction(MachineFunction &Fn) {
655 const ARMSubtarget &STI = Fn.
getSubtarget<ARMSubtarget>();
658 if (!(STI.useSplatVFPToNeon() && STI.hasNEON()))
669 Replacements.clear();
671 for (MachineBasicBlock &
MBB : Fn) {
672 for (MachineInstr &
MI :
MBB) {
677 for (MachineInstr *
MI : DeadInstr) {
678 MI->eraseFromParent();
685 return new A15SDOptimizer();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Remove Loads Into Fake Uses
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
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
MachineInstrBundleIterator< MachineInstr > iterator
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.
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
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,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
constexpr bool isVirtual() const
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...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
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 ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
NodeAddr< DefNode * > Def
NodeAddr< UseNode * > Use
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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionPass * createA15SDOptimizerPass()
DWARFExpression::Operation Op
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
LLVM_ABI 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.
MCRegisterClass TargetRegisterClass