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.
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