26#define DEBUG_TYPE "packets"
45 StringRef getPassName()
const override {
return "R600 Packetizer"; }
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)
79 if (
TII->isPredicated(*BI))
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();
148 void initPacketizerState()
override {
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());
174 bool isLegalToPacketizeTogether(
SUnit *SUI,
SUnit *SUJ)
override {
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;
208 bool isLegalToPruneDependencies(
SUnit *SUI,
SUnit *SUJ)
override {
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);
305 endPacket(std::next(It)->
getParent(), std::next(It));
309 endPacket(
MI.getParent(),
MI);
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();
356 RegionEnd !=
MBB->begin();) {
360 for(;
I !=
MBB->begin(); --
I, --RemainingCount) {
361 if (
TII->isSchedulingBoundary(*std::prev(
I), &*
MBB, Fn))
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();
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
#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()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr > iterator
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.
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.
StringRef - 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