blob: 1683fe6c9a571a5dcd286eeaa8edeb6b00f5ad0e [file] [log] [blame]
Vincent Lejeunef43bc572013-04-01 21:47:42 +00001//===-- R600EmitClauseMarkers.cpp - Emit CF_ALU ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file
11/// Add CF_ALU. R600 Alu instructions are grouped in clause which can hold
12/// 128 Alu instructions ; these instructions can access up to 4 prefetched
13/// 4 lines of 16 registers from constant buffers. Such ALU clauses are
14/// initiated by CF_ALU instructions.
15//===----------------------------------------------------------------------===//
16
17#include "AMDGPU.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "AMDGPUSubtarget.h"
Vincent Lejeunef43bc572013-04-01 21:47:42 +000019#include "R600Defines.h"
20#include "R600InstrInfo.h"
Vincent Lejeunef43bc572013-04-01 21:47:42 +000021#include "R600RegisterInfo.h"
Tom Stellard44b30b42018-05-22 02:03:23 +000022#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000023#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/CodeGen/MachineBasicBlock.h"
26#include "llvm/CodeGen/MachineFunction.h"
Vincent Lejeunef43bc572013-04-01 21:47:42 +000027#include "llvm/CodeGen/MachineFunctionPass.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000028#include "llvm/CodeGen/MachineInstr.h"
Vincent Lejeunef43bc572013-04-01 21:47:42 +000029#include "llvm/CodeGen/MachineInstrBuilder.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000030#include "llvm/CodeGen/MachineOperand.h"
31#include "llvm/Pass.h"
32#include "llvm/Support/ErrorHandling.h"
33#include <cassert>
34#include <cstdint>
35#include <utility>
36#include <vector>
Vincent Lejeunef43bc572013-04-01 21:47:42 +000037
Benjamin Kramerd78bb462013-05-23 17:10:37 +000038using namespace llvm;
39
Tom Stellard1de55822013-12-11 17:51:41 +000040namespace llvm {
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000041
Tom Stellard1de55822013-12-11 17:51:41 +000042 void initializeR600EmitClauseMarkersPass(PassRegistry&);
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000043
44} // end namespace llvm
Tom Stellard1de55822013-12-11 17:51:41 +000045
Benjamin Kramerd78bb462013-05-23 17:10:37 +000046namespace {
Vincent Lejeunef43bc572013-04-01 21:47:42 +000047
Tom Stellard1de55822013-12-11 17:51:41 +000048class R600EmitClauseMarkers : public MachineFunctionPass {
Vincent Lejeunef43bc572013-04-01 21:47:42 +000049private:
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000050 const R600InstrInfo *TII = nullptr;
51 int Address = 0;
Vincent Lejeunef43bc572013-04-01 21:47:42 +000052
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +000053 unsigned OccupiedDwords(MachineInstr &MI) const {
54 switch (MI.getOpcode()) {
Tom Stellardc5a154d2018-06-28 23:47:12 +000055 case R600::INTERP_PAIR_XY:
56 case R600::INTERP_PAIR_ZW:
57 case R600::INTERP_VEC_LOAD:
58 case R600::DOT_4:
Vincent Lejeunef43bc572013-04-01 21:47:42 +000059 return 4;
Tom Stellardc5a154d2018-06-28 23:47:12 +000060 case R600::KILL:
Vincent Lejeunef43bc572013-04-01 21:47:42 +000061 return 0;
62 default:
63 break;
64 }
65
Tom Stellard8f9fc202013-11-15 00:12:45 +000066 // These will be expanded to two ALU instructions in the
67 // ExpandSpecialInstructions pass.
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +000068 if (TII->isLDSRetInstr(MI.getOpcode()))
Tom Stellard8f9fc202013-11-15 00:12:45 +000069 return 2;
70
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +000071 if (TII->isVector(MI) || TII->isCubeOp(MI.getOpcode()) ||
72 TII->isReductionOp(MI.getOpcode()))
Vincent Lejeunef43bc572013-04-01 21:47:42 +000073 return 4;
74
75 unsigned NumLiteral = 0;
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +000076 for (MachineInstr::mop_iterator It = MI.operands_begin(),
77 E = MI.operands_end();
78 It != E; ++It) {
Vincent Lejeunef43bc572013-04-01 21:47:42 +000079 MachineOperand &MO = *It;
Tom Stellardc5a154d2018-06-28 23:47:12 +000080 if (MO.isReg() && MO.getReg() == R600::ALU_LITERAL_X)
Vincent Lejeunef43bc572013-04-01 21:47:42 +000081 ++NumLiteral;
82 }
83 return 1 + NumLiteral;
84 }
85
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +000086 bool isALU(const MachineInstr &MI) const {
87 if (TII->isALUInstr(MI.getOpcode()))
Vincent Lejeunef43bc572013-04-01 21:47:42 +000088 return true;
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +000089 if (TII->isVector(MI) || TII->isCubeOp(MI.getOpcode()))
Vincent Lejeunef43bc572013-04-01 21:47:42 +000090 return true;
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +000091 switch (MI.getOpcode()) {
Tom Stellardc5a154d2018-06-28 23:47:12 +000092 case R600::PRED_X:
93 case R600::INTERP_PAIR_XY:
94 case R600::INTERP_PAIR_ZW:
95 case R600::INTERP_VEC_LOAD:
96 case R600::COPY:
97 case R600::DOT_4:
Vincent Lejeunef43bc572013-04-01 21:47:42 +000098 return true;
99 default:
100 return false;
101 }
102 }
103
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000104 bool IsTrivialInst(MachineInstr &MI) const {
105 switch (MI.getOpcode()) {
Tom Stellardc5a154d2018-06-28 23:47:12 +0000106 case R600::KILL:
107 case R600::RETURN:
108 case R600::IMPLICIT_DEF:
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000109 return true;
110 default:
111 return false;
112 }
113 }
114
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000115 std::pair<unsigned, unsigned> getAccessedBankLine(unsigned Sel) const {
116 // Sel is (512 + (kc_bank << 12) + ConstIndex) << 2
117 // (See also R600ISelLowering.cpp)
118 // ConstIndex value is in [0, 4095];
119 return std::pair<unsigned, unsigned>(
120 ((Sel >> 2) - 512) >> 12, // KC_BANK
121 // Line Number of ConstIndex
122 // A line contains 16 constant registers however KCX bank can lock
123 // two line at the same time ; thus we want to get an even line number.
124 // Line number can be retrieved with (>>4), using (>>5) <<1 generates
125 // an even number.
126 ((((Sel >> 2) - 512) & 4095) >> 5) << 1);
127 }
128
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000129 bool
130 SubstituteKCacheBank(MachineInstr &MI,
131 std::vector<std::pair<unsigned, unsigned>> &CachedConsts,
132 bool UpdateInstr = true) const {
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000133 std::vector<std::pair<unsigned, unsigned>> UsedKCache;
Tom Stellard8f9fc202013-11-15 00:12:45 +0000134
Tom Stellardc5a154d2018-06-28 23:47:12 +0000135 if (!TII->isALUInstr(MI.getOpcode()) && MI.getOpcode() != R600::DOT_4)
Tom Stellard8f9fc202013-11-15 00:12:45 +0000136 return true;
137
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000138 const SmallVectorImpl<std::pair<MachineOperand *, int64_t>> &Consts =
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000139 TII->getSrcs(MI);
140 assert(
Tom Stellardc5a154d2018-06-28 23:47:12 +0000141 (TII->isALUInstr(MI.getOpcode()) || MI.getOpcode() == R600::DOT_4) &&
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000142 "Can't assign Const");
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000143 for (unsigned i = 0, n = Consts.size(); i < n; ++i) {
Tom Stellardc5a154d2018-06-28 23:47:12 +0000144 if (Consts[i].first->getReg() != R600::ALU_CONST)
Vincent Lejeune0fca91d2013-05-17 16:50:02 +0000145 continue;
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000146 unsigned Sel = Consts[i].second;
147 unsigned Chan = Sel & 3, Index = ((Sel >> 2) - 512) & 31;
148 unsigned KCacheIndex = Index * 4 + Chan;
149 const std::pair<unsigned, unsigned> &BankLine = getAccessedBankLine(Sel);
150 if (CachedConsts.empty()) {
151 CachedConsts.push_back(BankLine);
152 UsedKCache.push_back(std::pair<unsigned, unsigned>(0, KCacheIndex));
153 continue;
154 }
155 if (CachedConsts[0] == BankLine) {
156 UsedKCache.push_back(std::pair<unsigned, unsigned>(0, KCacheIndex));
157 continue;
158 }
159 if (CachedConsts.size() == 1) {
160 CachedConsts.push_back(BankLine);
161 UsedKCache.push_back(std::pair<unsigned, unsigned>(1, KCacheIndex));
162 continue;
163 }
164 if (CachedConsts[1] == BankLine) {
165 UsedKCache.push_back(std::pair<unsigned, unsigned>(1, KCacheIndex));
166 continue;
167 }
168 return false;
169 }
170
Tom Stellard8f9fc202013-11-15 00:12:45 +0000171 if (!UpdateInstr)
172 return true;
173
Vincent Lejeune0fca91d2013-05-17 16:50:02 +0000174 for (unsigned i = 0, j = 0, n = Consts.size(); i < n; ++i) {
Tom Stellardc5a154d2018-06-28 23:47:12 +0000175 if (Consts[i].first->getReg() != R600::ALU_CONST)
Vincent Lejeune0fca91d2013-05-17 16:50:02 +0000176 continue;
177 switch(UsedKCache[j].first) {
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000178 case 0:
Vincent Lejeune0fca91d2013-05-17 16:50:02 +0000179 Consts[i].first->setReg(
Tom Stellardc5a154d2018-06-28 23:47:12 +0000180 R600::R600_KC0RegClass.getRegister(UsedKCache[j].second));
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000181 break;
182 case 1:
Vincent Lejeune0fca91d2013-05-17 16:50:02 +0000183 Consts[i].first->setReg(
Tom Stellardc5a154d2018-06-28 23:47:12 +0000184 R600::R600_KC1RegClass.getRegister(UsedKCache[j].second));
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000185 break;
186 default:
187 llvm_unreachable("Wrong Cache Line");
188 }
Vincent Lejeune0fca91d2013-05-17 16:50:02 +0000189 j++;
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000190 }
191 return true;
192 }
193
Tom Stellard8f9fc202013-11-15 00:12:45 +0000194 bool canClauseLocalKillFitInClause(
195 unsigned AluInstCount,
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000196 std::vector<std::pair<unsigned, unsigned>> KCacheBanks,
Tom Stellard8f9fc202013-11-15 00:12:45 +0000197 MachineBasicBlock::iterator Def,
198 MachineBasicBlock::iterator BBEnd) {
199 const R600RegisterInfo &TRI = TII->getRegisterInfo();
Jan Vesely3ea17042017-03-06 20:10:05 +0000200 //TODO: change this to defs?
Tom Stellard8f9fc202013-11-15 00:12:45 +0000201 for (MachineInstr::const_mop_iterator
202 MOI = Def->operands_begin(),
203 MOE = Def->operands_end(); MOI != MOE; ++MOI) {
204 if (!MOI->isReg() || !MOI->isDef() ||
205 TRI.isPhysRegLiveAcrossClauses(MOI->getReg()))
206 continue;
207
208 // Def defines a clause local register, so check that its use will fit
209 // in the clause.
210 unsigned LastUseCount = 0;
211 for (MachineBasicBlock::iterator UseI = Def; UseI != BBEnd; ++UseI) {
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000212 AluInstCount += OccupiedDwords(*UseI);
Tom Stellard8f9fc202013-11-15 00:12:45 +0000213 // Make sure we won't need to end the clause due to KCache limitations.
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000214 if (!SubstituteKCacheBank(*UseI, KCacheBanks, false))
Tom Stellard8f9fc202013-11-15 00:12:45 +0000215 return false;
216
217 // We have reached the maximum instruction limit before finding the
218 // use that kills this register, so we cannot use this def in the
219 // current clause.
220 if (AluInstCount >= TII->getMaxAlusPerClause())
221 return false;
222
Jan Vesely3ea17042017-03-06 20:10:05 +0000223 // TODO: Is this true? kill flag appears to work OK below
Tom Stellard8f9fc202013-11-15 00:12:45 +0000224 // Register kill flags have been cleared by the time we get to this
225 // pass, but it is safe to assume that all uses of this register
226 // occur in the same basic block as its definition, because
227 // it is illegal for the scheduler to schedule them in
228 // different blocks.
Jan Vesely3ea17042017-03-06 20:10:05 +0000229 if (UseI->readsRegister(MOI->getReg()))
Tom Stellard8f9fc202013-11-15 00:12:45 +0000230 LastUseCount = AluInstCount;
231
Jan Vesely3ea17042017-03-06 20:10:05 +0000232 // Exit early if the current use kills the register
233 if (UseI != Def && UseI->killsRegister(MOI->getReg()))
Tom Stellard8f9fc202013-11-15 00:12:45 +0000234 break;
235 }
236 if (LastUseCount)
237 return LastUseCount <= TII->getMaxAlusPerClause();
238 llvm_unreachable("Clause local register live at end of clause.");
239 }
240 return true;
241 }
242
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000243 MachineBasicBlock::iterator
Vincent Lejeunece499742013-07-09 15:03:33 +0000244 MakeALUClause(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) {
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000245 MachineBasicBlock::iterator ClauseHead = I;
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000246 std::vector<std::pair<unsigned, unsigned>> KCacheBanks;
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000247 bool PushBeforeModifier = false;
248 unsigned AluInstCount = 0;
249 for (MachineBasicBlock::iterator E = MBB.end(); I != E; ++I) {
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000250 if (IsTrivialInst(*I))
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000251 continue;
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000252 if (!isALU(*I))
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000253 break;
Vincent Lejeunec3d3f9b2013-04-03 18:24:47 +0000254 if (AluInstCount > TII->getMaxAlusPerClause())
255 break;
Tom Stellardc5a154d2018-06-28 23:47:12 +0000256 if (I->getOpcode() == R600::PRED_X) {
Vincent Lejeune0b342d62013-10-01 19:32:49 +0000257 // We put PRED_X in its own clause to ensure that ifcvt won't create
258 // clauses with more than 128 insts.
259 // IfCvt is indeed checking that "then" and "else" branches of an if
260 // statement have less than ~60 insts thus converted clauses can't be
261 // bigger than ~121 insts (predicate setter needs to be in the same
262 // clause as predicated alus).
263 if (AluInstCount > 0)
264 break;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000265 if (TII->getFlagOp(*I).getImm() & MO_FLAG_PUSH)
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000266 PushBeforeModifier = true;
267 AluInstCount ++;
268 continue;
269 }
Tom Stellardce540332013-06-28 15:46:59 +0000270 // XXX: GROUP_BARRIER instructions cannot be in the same ALU clause as:
271 //
272 // * KILL or INTERP instructions
273 // * Any instruction that sets UPDATE_EXEC_MASK or UPDATE_PRED bits
274 // * Uses waterfalling (i.e. INDEX_MODE = AR.X)
275 //
276 // XXX: These checks have not been implemented yet.
277 if (TII->mustBeLastInClause(I->getOpcode())) {
Vincent Lejeune99312982013-04-03 16:24:04 +0000278 I++;
279 break;
280 }
Tom Stellard8f9fc202013-11-15 00:12:45 +0000281
282 // If this instruction defines a clause local register, make sure
283 // its use can fit in this clause.
284 if (!canClauseLocalKillFitInClause(AluInstCount, KCacheBanks, I, E))
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000285 break;
Tom Stellard8f9fc202013-11-15 00:12:45 +0000286
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000287 if (!SubstituteKCacheBank(*I, KCacheBanks))
Vincent Lejeunec6896792013-06-04 23:17:15 +0000288 break;
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000289 AluInstCount += OccupiedDwords(*I);
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000290 }
291 unsigned Opcode = PushBeforeModifier ?
Tom Stellardc5a154d2018-06-28 23:47:12 +0000292 R600::CF_ALU_PUSH_BEFORE : R600::CF_ALU;
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000293 BuildMI(MBB, ClauseHead, MBB.findDebugLoc(ClauseHead), TII->get(Opcode))
Vincent Lejeunece499742013-07-09 15:03:33 +0000294 // We don't use the ADDR field until R600ControlFlowFinalizer pass, where
295 // it is safe to assume it is 0. However if we always put 0 here, the ifcvt
Matt Arsenault37fefd62016-06-10 02:18:02 +0000296 // pass may assume that identical ALU clause starter at the beginning of a
Vincent Lejeunece499742013-07-09 15:03:33 +0000297 // true and false branch can be factorized which is not the case.
298 .addImm(Address++) // ADDR
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000299 .addImm(KCacheBanks.empty()?0:KCacheBanks[0].first) // KB0
300 .addImm((KCacheBanks.size() < 2)?0:KCacheBanks[1].first) // KB1
301 .addImm(KCacheBanks.empty()?0:2) // KM0
302 .addImm((KCacheBanks.size() < 2)?0:2) // KM1
303 .addImm(KCacheBanks.empty()?0:KCacheBanks[0].second) // KLINE0
304 .addImm((KCacheBanks.size() < 2)?0:KCacheBanks[1].second) // KLINE1
Vincent Lejeunece499742013-07-09 15:03:33 +0000305 .addImm(AluInstCount) // COUNT
306 .addImm(1); // Enabled
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000307 return I;
308 }
309
310public:
Tom Stellard1de55822013-12-11 17:51:41 +0000311 static char ID;
Tom Stellard1de55822013-12-11 17:51:41 +0000312
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000313 R600EmitClauseMarkers() : MachineFunctionPass(ID) {
Tom Stellard1de55822013-12-11 17:51:41 +0000314 initializeR600EmitClauseMarkersPass(*PassRegistry::getPassRegistry());
315 }
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000316
Craig Topper5656db42014-04-29 07:57:24 +0000317 bool runOnMachineFunction(MachineFunction &MF) override {
Matt Arsenault43e92fe2016-06-24 06:30:11 +0000318 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
319 TII = ST.getInstrInfo();
Bill Wendling37e9adb2013-06-07 20:28:55 +0000320
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000321 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
322 BB != BB_E; ++BB) {
323 MachineBasicBlock &MBB = *BB;
324 MachineBasicBlock::iterator I = MBB.begin();
Tom Stellardc5a154d2018-06-28 23:47:12 +0000325 if (I != MBB.end() && I->getOpcode() == R600::CF_ALU)
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000326 continue; // BB was already parsed
327 for (MachineBasicBlock::iterator E = MBB.end(); I != E;) {
Jan Vesely4b1243f2017-02-18 04:24:10 +0000328 if (isALU(*I)) {
329 auto next = MakeALUClause(MBB, I);
330 assert(next != I);
331 I = next;
332 } else
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000333 ++I;
334 }
335 }
336 return false;
337 }
338
Mehdi Amini117296c2016-10-01 02:56:57 +0000339 StringRef getPassName() const override {
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000340 return "R600 Emit Clause Markers Pass";
341 }
342};
343
Tom Stellard1de55822013-12-11 17:51:41 +0000344char R600EmitClauseMarkers::ID = 0;
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000345
Benjamin Kramerd78bb462013-05-23 17:10:37 +0000346} // end anonymous namespace
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000347
Tom Stellard1de55822013-12-11 17:51:41 +0000348INITIALIZE_PASS_BEGIN(R600EmitClauseMarkers, "emitclausemarkers",
349 "R600 Emit Clause Markters", false, false)
350INITIALIZE_PASS_END(R600EmitClauseMarkers, "emitclausemarkers",
351 "R600 Emit Clause Markters", false, false)
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000352
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000353FunctionPass *llvm::createR600EmitClauseMarkers() {
Tom Stellard1de55822013-12-11 17:51:41 +0000354 return new R600EmitClauseMarkers();
Vincent Lejeunef43bc572013-04-01 21:47:42 +0000355}