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());
130 for (
unsigned Op : Ops) {
131 int OperandIdx =
TII->getOperandIdx(
MI.getOpcode(),
Op);
134 Register Src =
MI.getOperand(OperandIdx).getReg();
137 MI.getOperand(OperandIdx).setReg(It->second);
145 TII(ST.getInstrInfo()),
146 TRI(
TII->getRegisterInfo()) {
147 VLIW5 = !ST.hasCaymanISA();
152 ConsideredInstUsesAlreadyWrittenVectorElement =
false;
164 if (
TII->isVector(
MI))
166 if (!
TII->isALUInstr(
MI.getOpcode()))
168 if (
MI.getOpcode() == R600::GROUP_BARRIER)
172 return TII->isLDSInstr(
MI.getOpcode());
179 if (getSlot(*MII) == getSlot(*MIJ))
180 ConsideredInstUsesAlreadyWrittenVectorElement =
true;
182 int OpI =
TII->getOperandIdx(MII->
getOpcode(), R600::OpName::pred_sel),
183 OpJ =
TII->getOperandIdx(MIJ->getOpcode(), R600::OpName::pred_sel);
185 PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg() :
Register();
202 TII->definesAddressRegister(*MII) ||
TII->definesAddressRegister(*MIJ);
204 TII->usesAddressRegister(*MII) ||
TII->usesAddressRegister(*MIJ);
206 return !ARDef || !ARUse;
216 unsigned LastOp =
TII->getOperandIdx(
MI->getOpcode(), R600::OpName::last);
217 MI->getOperand(LastOp).setImm(Bit);
222 std::vector<R600InstrInfo::BankSwizzle> &BS,
224 isTransSlot =
TII->isTransOnly(
MI);
225 assert (!isTransSlot || VLIW5);
228 if (!isTransSlot && !CurrentPacketMIs.empty()) {
229 if (getSlot(
MI) <= getSlot(*CurrentPacketMIs.back())) {
230 if (ConsideredInstUsesAlreadyWrittenVectorElement &&
231 !
TII->isVectorOnly(
MI) && VLIW5) {
234 dbgs() <<
"Considering as Trans Inst :";
244 CurrentPacketMIs.push_back(&
MI);
245 if (!
TII->fitsConstReadLimitations(CurrentPacketMIs)) {
247 dbgs() <<
"Couldn't pack :\n";
249 dbgs() <<
"with the following packets :\n";
250 for (
unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
251 CurrentPacketMIs[i]->dump();
254 dbgs() <<
"because of Consts read limitations\n";
256 CurrentPacketMIs.pop_back();
261 if (!
TII->fitsReadPortLimitations(CurrentPacketMIs,
262 PV, BS, isTransSlot)) {
264 dbgs() <<
"Couldn't pack :\n";
266 dbgs() <<
"with the following packets :\n";
267 for (
unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
268 CurrentPacketMIs[i]->dump();
271 dbgs() <<
"because of Read port limitations\n";
273 CurrentPacketMIs.pop_back();
278 if (isTransSlot &&
TII->readsLDSSrcReg(
MI))
281 CurrentPacketMIs.pop_back();
287 CurrentPacketMIs.empty() ? &
MI : CurrentPacketMIs.front();
289 getPreviousVector(FirstInBundle);
290 std::vector<R600InstrInfo::BankSwizzle> BS;
293 if (isBundlableWithCurrentPMI(
MI, PV, BS, isTransSlot)) {
294 for (
unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) {
296 unsigned Op =
TII->getOperandIdx(
MI->getOpcode(),
297 R600::OpName::bank_swizzle);
298 MI->getOperand(
Op).setImm(BS[i]);
301 TII->getOperandIdx(
MI.getOpcode(), R600::OpName::bank_swizzle);
302 MI.getOperand(
Op).setImm(BS.back());
303 if (!CurrentPacketMIs.empty())
304 setIsLastBit(CurrentPacketMIs.back(), 0);
305 substitutePV(
MI, PV);
313 if (
TII->isTransOnly(
MI))
323 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
332 if (
Packetizer.getResourceTracker()->getInstrItins()->isEmpty())
347 if (
MI.isKill() ||
MI.getOpcode() == R600::IMPLICIT_DEF ||
348 (
MI.getOpcode() == R600::CF_ALU && !
MI.getOperand(8).getImm()))
357 unsigned RemainingCount =
MBB->
size();
363 for(;
I !=
MBB->
begin(); --
I, --RemainingCount) {
370 if (
I == RegionEnd) {
371 RegionEnd = std::prev(RegionEnd);
376 if (
I == std::prev(RegionEnd)) {
377 RegionEnd = std::prev(RegionEnd);
393 "R600 Packetizer",
false,
false)
397char R600Packetizer::
ID = 0;
402 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.