26#define DEBUG_TYPE "packets"
55 bool ConsideredInstUsesAlreadyWrittenVectorElement;
58 return TRI.getHWRegChan(
MI.getOperand(0).getReg());
67 if (!
TII->isALUInstr(
I->getOpcode()) && !
I->isBundle())
75 int BISlot = getSlot(*BI);
76 if (LastDstChan >= BISlot)
81 int OperandIdx =
TII->getOperandIdx(BI->getOpcode(), R600::OpName::write);
82 if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0)
84 int DstIdx =
TII->getOperandIdx(BI->getOpcode(), R600::OpName::dst);
88 Register Dst = BI->getOperand(DstIdx).getReg();
89 if (isTrans ||
TII->isTransOnly(*BI)) {
90 Result[Dst] = R600::PS;
93 if (BI->getOpcode() == R600::DOT4_r600 ||
94 BI->getOpcode() == R600::DOT4_eg) {
95 Result[Dst] = R600::PV_X;
98 if (Dst == R600::OQAP) {
102 switch (
TRI.getHWRegChan(Dst)) {
119 }
while ((++BI)->isBundledWithPred());
125 const R600::OpName Ops[] = {R600::OpName::src0, R600::OpName::src1,
127 for (R600::OpName
Op : Ops) {
128 int OperandIdx =
TII->getOperandIdx(
MI.getOpcode(),
Op);
131 Register Src =
MI.getOperand(OperandIdx).getReg();
134 MI.getOperand(OperandIdx).setReg(It->second);
142 TII(ST.getInstrInfo()),
143 TRI(
TII->getRegisterInfo()) {
144 VLIW5 = !ST.hasCaymanISA();
149 ConsideredInstUsesAlreadyWrittenVectorElement =
false;
161 if (
TII->isVector(
MI))
163 if (!
TII->isALUInstr(
MI.getOpcode()))
165 if (
MI.getOpcode() == R600::GROUP_BARRIER)
169 return TII->isLDSInstr(
MI.getOpcode());
176 if (getSlot(*MII) == getSlot(*MIJ))
177 ConsideredInstUsesAlreadyWrittenVectorElement =
true;
179 int OpI =
TII->getOperandIdx(MII->
getOpcode(), R600::OpName::pred_sel),
180 OpJ =
TII->getOperandIdx(MIJ->getOpcode(), R600::OpName::pred_sel);
182 PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg() :
Register();
199 TII->definesAddressRegister(*MII) ||
TII->definesAddressRegister(*MIJ);
201 TII->usesAddressRegister(*MII) ||
TII->usesAddressRegister(*MIJ);
203 return !ARDef || !ARUse;
213 unsigned LastOp =
TII->getOperandIdx(
MI->getOpcode(), R600::OpName::last);
214 MI->getOperand(LastOp).setImm(Bit);
219 std::vector<R600InstrInfo::BankSwizzle> &BS,
221 isTransSlot =
TII->isTransOnly(
MI);
222 assert (!isTransSlot || VLIW5);
225 if (!isTransSlot && !CurrentPacketMIs.empty()) {
226 if (getSlot(
MI) <= getSlot(*CurrentPacketMIs.back())) {
227 if (ConsideredInstUsesAlreadyWrittenVectorElement &&
228 !
TII->isVectorOnly(
MI) && VLIW5) {
231 dbgs() <<
"Considering as Trans Inst :";
241 CurrentPacketMIs.push_back(&
MI);
242 if (!
TII->fitsConstReadLimitations(CurrentPacketMIs)) {
244 dbgs() <<
"Couldn't pack :\n";
246 dbgs() <<
"with the following packets :\n";
247 for (
unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
248 CurrentPacketMIs[i]->dump();
251 dbgs() <<
"because of Consts read limitations\n";
253 CurrentPacketMIs.pop_back();
258 if (!
TII->fitsReadPortLimitations(CurrentPacketMIs,
259 PV, BS, isTransSlot)) {
261 dbgs() <<
"Couldn't pack :\n";
263 dbgs() <<
"with the following packets :\n";
264 for (
unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
265 CurrentPacketMIs[i]->dump();
268 dbgs() <<
"because of Read port limitations\n";
270 CurrentPacketMIs.pop_back();
275 if (isTransSlot &&
TII->readsLDSSrcReg(
MI))
278 CurrentPacketMIs.pop_back();
284 CurrentPacketMIs.empty() ? &
MI : CurrentPacketMIs.front();
286 getPreviousVector(FirstInBundle);
287 std::vector<R600InstrInfo::BankSwizzle> BS;
290 if (isBundlableWithCurrentPMI(
MI, PV, BS, isTransSlot)) {
291 for (
unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) {
293 unsigned Op =
TII->getOperandIdx(
MI->getOpcode(),
294 R600::OpName::bank_swizzle);
295 MI->getOperand(
Op).setImm(BS[i]);
298 TII->getOperandIdx(
MI.getOpcode(), R600::OpName::bank_swizzle);
299 MI.getOperand(
Op).setImm(BS.back());
300 if (!CurrentPacketMIs.empty())
301 setIsLastBit(CurrentPacketMIs.back(), 0);
302 substitutePV(
MI, PV);
310 if (
TII->isTransOnly(
MI))
320 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
329 if (
Packetizer.getResourceTracker()->getInstrItins()->isEmpty())
344 if (
MI.isKill() ||
MI.getOpcode() == R600::IMPLICIT_DEF ||
345 (
MI.getOpcode() == R600::CF_ALU && !
MI.getOperand(8).getImm()))
354 unsigned RemainingCount =
MBB->
size();
360 for(;
I !=
MBB->
begin(); --
I, --RemainingCount) {
367 if (
I == RegionEnd) {
368 RegionEnd = std::prev(RegionEnd);
373 if (
I == std::prev(RegionEnd)) {
374 RegionEnd = std::prev(RegionEnd);
390 "R600 Packetizer",
false,
false)
394char R600Packetizer::
ID = 0;
399 return new R600Packetizer();
static const Function * getParent(const Value *V)
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Provides R600 specific target descriptions.
AMDGPU R600 specific subclass of TargetSubtarget.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
FunctionPass class - This class is used to implement most global optimizations.
bool isPredicated(const MachineInstr &MI) const override
Returns true if the instruction is already predicated.
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
Test if the given instruction should be considered a scheduling boundary.
Instructions::iterator instr_iterator
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
Analysis pass which computes a MachineDominatorTree.
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.
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.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
Kind getKind() const
Returns an enum value representing the kind of the dependence.
@ Output
A register output-dependence (aka WAW).
@ Anti
A register anti-dependence (aka WAR).
Scheduling unit. This is a node in the scheduling DAG.
bool isSucc(const SUnit *N) const
Tests if node N is a successor of this node.
SmallVector< SDep, 4 > Succs
All sunit successors.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
StringRef - Represent a constant reference to a string, i.e.
virtual bool isSoloInstruction(const MachineInstr &MI)
virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ)
const TargetInstrInfo * TII
virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ)
virtual void initPacketizerState()
virtual void endPacket(MachineBasicBlock *MBB, MachineBasicBlock::iterator MI)
virtual bool ignorePseudoInstruction(const MachineInstr &I, const MachineBasicBlock *MBB)
virtual MachineBasicBlock::iterator addToPacket(MachineInstr &MI)
#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.
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
FunctionPass * createR600Packetizer()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.