26#define DEBUG_TYPE "packets"
42 StringRef getPassName()
const override {
return "R600 Packetizer"; }
52 bool ConsideredInstUsesAlreadyWrittenVectorElement;
55 return TRI.getHWRegChan(
MI.getOperand(0).getReg());
64 if (!
TII->isALUInstr(
I->getOpcode()) && !
I->isBundle())
72 int BISlot = getSlot(*BI);
73 if (LastDstChan >= BISlot)
76 if (
TII->isPredicated(*BI))
78 int OperandIdx =
TII->getOperandIdx(BI->getOpcode(), R600::OpName::write);
79 if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0)
81 int DstIdx =
TII->getOperandIdx(BI->getOpcode(), R600::OpName::dst);
85 Register Dst = BI->getOperand(DstIdx).getReg();
86 if (isTrans ||
TII->isTransOnly(*BI)) {
87 Result[Dst] = R600::PS;
90 if (BI->getOpcode() == R600::DOT4_r600 ||
91 BI->getOpcode() == R600::DOT4_eg) {
92 Result[Dst] = R600::PV_X;
95 if (Dst == R600::OQAP) {
99 switch (
TRI.getHWRegChan(Dst)) {
116 }
while ((++BI)->isBundledWithPred());
122 const R600::OpName
Ops[] = {R600::OpName::src0, R600::OpName::src1,
124 for (R600::OpName
Op :
Ops) {
125 int OperandIdx =
TII->getOperandIdx(
MI.getOpcode(),
Op);
128 Register Src =
MI.getOperand(OperandIdx).getReg();
129 const auto It = PVs.
find(Src);
131 MI.getOperand(OperandIdx).setReg(It->second);
139 TII(ST.getInstrInfo()),
140 TRI(
TII->getRegisterInfo()) {
141 VLIW5 = !ST.hasCaymanISA();
145 void initPacketizerState()
override {
146 ConsideredInstUsesAlreadyWrittenVectorElement =
false;
158 if (
TII->isVector(
MI))
160 if (!
TII->isALUInstr(
MI.getOpcode()))
162 if (
MI.getOpcode() == R600::GROUP_BARRIER)
166 return TII->isLDSInstr(
MI.getOpcode());
171 bool isLegalToPacketizeTogether(
SUnit *SUI,
SUnit *SUJ)
override {
173 if (getSlot(*MII) == getSlot(*MIJ))
174 ConsideredInstUsesAlreadyWrittenVectorElement =
true;
176 int OpI =
TII->getOperandIdx(MII->
getOpcode(), R600::OpName::pred_sel),
177 OpJ =
TII->getOperandIdx(MIJ->getOpcode(), R600::OpName::pred_sel);
179 PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg() :
Register();
196 TII->definesAddressRegister(*MII) ||
TII->definesAddressRegister(*MIJ);
198 TII->usesAddressRegister(*MII) ||
TII->usesAddressRegister(*MIJ);
200 return !ARDef || !ARUse;
205 bool isLegalToPruneDependencies(
SUnit *SUI,
SUnit *SUJ)
override {
210 unsigned LastOp =
TII->getOperandIdx(
MI->getOpcode(), R600::OpName::last);
211 MI->getOperand(LastOp).setImm(Bit);
216 std::vector<R600InstrInfo::BankSwizzle> &BS,
218 isTransSlot =
TII->isTransOnly(
MI);
219 assert (!isTransSlot || VLIW5);
222 if (!isTransSlot && !CurrentPacketMIs.empty()) {
223 if (getSlot(
MI) <= getSlot(*CurrentPacketMIs.back())) {
224 if (ConsideredInstUsesAlreadyWrittenVectorElement &&
225 !
TII->isVectorOnly(
MI) && VLIW5) {
228 dbgs() <<
"Considering as Trans Inst :";
238 CurrentPacketMIs.push_back(&
MI);
239 if (!
TII->fitsConstReadLimitations(CurrentPacketMIs)) {
241 dbgs() <<
"Couldn't pack :\n";
243 dbgs() <<
"with the following packets :\n";
244 for (
unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
245 CurrentPacketMIs[i]->dump();
248 dbgs() <<
"because of Consts read limitations\n";
250 CurrentPacketMIs.pop_back();
255 if (!
TII->fitsReadPortLimitations(CurrentPacketMIs,
256 PV, BS, isTransSlot)) {
258 dbgs() <<
"Couldn't pack :\n";
260 dbgs() <<
"with the following packets :\n";
261 for (
unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
262 CurrentPacketMIs[i]->dump();
265 dbgs() <<
"because of Read port limitations\n";
267 CurrentPacketMIs.pop_back();
272 if (isTransSlot &&
TII->readsLDSSrcReg(
MI))
275 CurrentPacketMIs.pop_back();
281 CurrentPacketMIs.empty() ? &
MI : CurrentPacketMIs.front();
283 getPreviousVector(FirstInBundle);
284 std::vector<R600InstrInfo::BankSwizzle> BS;
287 if (isBundlableWithCurrentPMI(
MI, PV, BS, isTransSlot)) {
288 for (
unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) {
290 unsigned Op =
TII->getOperandIdx(
MI->getOpcode(),
291 R600::OpName::bank_swizzle);
292 MI->getOperand(
Op).setImm(BS[i]);
295 TII->getOperandIdx(
MI.getOpcode(), R600::OpName::bank_swizzle);
296 MI.getOperand(
Op).setImm(BS.back());
297 if (!CurrentPacketMIs.empty())
298 setIsLastBit(CurrentPacketMIs.back(), 0);
299 substitutePV(
MI, PV);
302 endPacket(std::next(It)->
getParent(), std::next(It));
306 endPacket(
MI.getParent(),
MI);
307 if (
TII->isTransOnly(
MI))
317 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
321 if (
II->Itineraries ==
nullptr)
331 if (
Packetizer.getResourceTracker()->getInstrItins()->isEmpty())
346 if (
MI.isKill() ||
MI.getOpcode() == R600::IMPLICIT_DEF ||
347 (
MI.getOpcode() == R600::CF_ALU && !
MI.getOperand(8).getImm()))
356 unsigned RemainingCount =
MBB->size();
358 RegionEnd !=
MBB->begin();) {
362 for(;
I !=
MBB->begin(); --
I, --RemainingCount) {
363 if (
TII->isSchedulingBoundary(*std::prev(
I), &*
MBB, Fn))
369 if (
I == RegionEnd) {
370 RegionEnd = std::prev(RegionEnd);
375 if (
I == std::prev(RegionEnd)) {
376 RegionEnd = std::prev(RegionEnd);
392 "R600 Packetizer",
false,
false)
396char R600Packetizer::
ID = 0;
401 return new R600Packetizer();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
#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.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
iterator find(const_arg_type_t< KeyT > Val)
FunctionPass class - This class is used to implement most global optimizations.
Itinerary data supplied by a subtarget to be used by a target.
Instructions::iterator instr_iterator
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.
BasicBlockListType::iterator iterator
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.
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.
Represent a constant reference to a string, i.e.
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()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DWARFExpression::Operation Op