Bug Summary

File:lib/Target/AMDGPU/R600InstrInfo.cpp
Warning:line 407, column 5
Undefined or garbage value returned to caller

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name R600InstrInfo.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-9/lib/clang/9.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-9~svn359999/build-llvm/lib/Target/AMDGPU -I /build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU -I /build/llvm-toolchain-snapshot-9~svn359999/build-llvm/include -I /build/llvm-toolchain-snapshot-9~svn359999/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/9.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-9/lib/clang/9.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-9~svn359999/build-llvm/lib/Target/AMDGPU -fdebug-prefix-map=/build/llvm-toolchain-snapshot-9~svn359999=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2019-05-06-051613-19774-1 -x c++ /build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp -faddrsig
1//===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// R600 Implementation of TargetInstrInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "R600InstrInfo.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPUSubtarget.h"
18#include "R600Defines.h"
19#include "R600FrameLowering.h"
20#include "R600RegisterInfo.h"
21#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
22#include "Utils/AMDGPUBaseInfo.h"
23#include "llvm/ADT/BitVector.h"
24#include "llvm/ADT/SmallSet.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/CodeGen/MachineBasicBlock.h"
27#include "llvm/CodeGen/MachineFrameInfo.h"
28#include "llvm/CodeGen/MachineFunction.h"
29#include "llvm/CodeGen/MachineInstr.h"
30#include "llvm/CodeGen/MachineInstrBuilder.h"
31#include "llvm/CodeGen/MachineOperand.h"
32#include "llvm/CodeGen/MachineRegisterInfo.h"
33#include "llvm/CodeGen/TargetRegisterInfo.h"
34#include "llvm/CodeGen/TargetSubtargetInfo.h"
35#include "llvm/Support/ErrorHandling.h"
36#include <algorithm>
37#include <cassert>
38#include <cstdint>
39#include <cstring>
40#include <iterator>
41#include <utility>
42#include <vector>
43
44using namespace llvm;
45
46#define GET_INSTRINFO_CTOR_DTOR
47#include "R600GenDFAPacketizer.inc"
48
49#define GET_INSTRINFO_CTOR_DTOR
50#define GET_INSTRMAP_INFO
51#define GET_INSTRINFO_NAMED_OPS
52#include "R600GenInstrInfo.inc"
53
54R600InstrInfo::R600InstrInfo(const R600Subtarget &ST)
55 : R600GenInstrInfo(-1, -1), RI(), ST(ST) {}
56
57bool R600InstrInfo::isVector(const MachineInstr &MI) const {
58 return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;
59}
60
61void R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
62 MachineBasicBlock::iterator MI,
63 const DebugLoc &DL, unsigned DestReg,
64 unsigned SrcReg, bool KillSrc) const {
65 unsigned VectorComponents = 0;
66 if ((R600::R600_Reg128RegClass.contains(DestReg) ||
67 R600::R600_Reg128VerticalRegClass.contains(DestReg)) &&
68 (R600::R600_Reg128RegClass.contains(SrcReg) ||
69 R600::R600_Reg128VerticalRegClass.contains(SrcReg))) {
70 VectorComponents = 4;
71 } else if((R600::R600_Reg64RegClass.contains(DestReg) ||
72 R600::R600_Reg64VerticalRegClass.contains(DestReg)) &&
73 (R600::R600_Reg64RegClass.contains(SrcReg) ||
74 R600::R600_Reg64VerticalRegClass.contains(SrcReg))) {
75 VectorComponents = 2;
76 }
77
78 if (VectorComponents > 0) {
79 for (unsigned I = 0; I < VectorComponents; I++) {
80 unsigned SubRegIndex = AMDGPURegisterInfo::getSubRegFromChannel(I);
81 buildDefaultInstruction(MBB, MI, R600::MOV,
82 RI.getSubReg(DestReg, SubRegIndex),
83 RI.getSubReg(SrcReg, SubRegIndex))
84 .addReg(DestReg,
85 RegState::Define | RegState::Implicit);
86 }
87 } else {
88 MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, R600::MOV,
89 DestReg, SrcReg);
90 NewMI->getOperand(getOperandIdx(*NewMI, R600::OpName::src0))
91 .setIsKill(KillSrc);
92 }
93}
94
95/// \returns true if \p MBBI can be moved into a new basic.
96bool R600InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,
97 MachineBasicBlock::iterator MBBI) const {
98 for (MachineInstr::const_mop_iterator I = MBBI->operands_begin(),
99 E = MBBI->operands_end(); I != E; ++I) {
100 if (I->isReg() && !TargetRegisterInfo::isVirtualRegister(I->getReg()) &&
101 I->isUse() && RI.isPhysRegLiveAcrossClauses(I->getReg()))
102 return false;
103 }
104 return true;
105}
106
107bool R600InstrInfo::isMov(unsigned Opcode) const {
108 switch(Opcode) {
109 default:
110 return false;
111 case R600::MOV:
112 case R600::MOV_IMM_F32:
113 case R600::MOV_IMM_I32:
114 return true;
115 }
116}
117
118bool R600InstrInfo::isReductionOp(unsigned Opcode) const {
119 return false;
120}
121
122bool R600InstrInfo::isCubeOp(unsigned Opcode) const {
123 switch(Opcode) {
124 default: return false;
125 case R600::CUBE_r600_pseudo:
126 case R600::CUBE_r600_real:
127 case R600::CUBE_eg_pseudo:
128 case R600::CUBE_eg_real:
129 return true;
130 }
131}
132
133bool R600InstrInfo::isALUInstr(unsigned Opcode) const {
134 unsigned TargetFlags = get(Opcode).TSFlags;
135
136 return (TargetFlags & R600_InstFlag::ALU_INST);
137}
138
139bool R600InstrInfo::hasInstrModifiers(unsigned Opcode) const {
140 unsigned TargetFlags = get(Opcode).TSFlags;
141
142 return ((TargetFlags & R600_InstFlag::OP1) |
143 (TargetFlags & R600_InstFlag::OP2) |
144 (TargetFlags & R600_InstFlag::OP3));
145}
146
147bool R600InstrInfo::isLDSInstr(unsigned Opcode) const {
148 unsigned TargetFlags = get(Opcode).TSFlags;
149
150 return ((TargetFlags & R600_InstFlag::LDS_1A) |
151 (TargetFlags & R600_InstFlag::LDS_1A1D) |
152 (TargetFlags & R600_InstFlag::LDS_1A2D));
153}
154
155bool R600InstrInfo::isLDSRetInstr(unsigned Opcode) const {
156 return isLDSInstr(Opcode) && getOperandIdx(Opcode, R600::OpName::dst) != -1;
157}
158
159bool R600InstrInfo::canBeConsideredALU(const MachineInstr &MI) const {
160 if (isALUInstr(MI.getOpcode()))
161 return true;
162 if (isVector(MI) || isCubeOp(MI.getOpcode()))
163 return true;
164 switch (MI.getOpcode()) {
165 case R600::PRED_X:
166 case R600::INTERP_PAIR_XY:
167 case R600::INTERP_PAIR_ZW:
168 case R600::INTERP_VEC_LOAD:
169 case R600::COPY:
170 case R600::DOT_4:
171 return true;
172 default:
173 return false;
174 }
175}
176
177bool R600InstrInfo::isTransOnly(unsigned Opcode) const {
178 if (ST.hasCaymanISA())
179 return false;
180 return (get(Opcode).getSchedClass() == R600::Sched::TransALU);
181}
182
183bool R600InstrInfo::isTransOnly(const MachineInstr &MI) const {
184 return isTransOnly(MI.getOpcode());
185}
186
187bool R600InstrInfo::isVectorOnly(unsigned Opcode) const {
188 return (get(Opcode).getSchedClass() == R600::Sched::VecALU);
189}
190
191bool R600InstrInfo::isVectorOnly(const MachineInstr &MI) const {
192 return isVectorOnly(MI.getOpcode());
193}
194
195bool R600InstrInfo::isExport(unsigned Opcode) const {
196 return (get(Opcode).TSFlags & R600_InstFlag::IS_EXPORT);
197}
198
199bool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
200 return ST.hasVertexCache() && IS_VTX(get(Opcode))((get(Opcode)).TSFlags & R600_InstFlag::VTX_INST);
201}
202
203bool R600InstrInfo::usesVertexCache(const MachineInstr &MI) const {
204 const MachineFunction *MF = MI.getParent()->getParent();
205 return !AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
206 usesVertexCache(MI.getOpcode());
207}
208
209bool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
210 return (!ST.hasVertexCache() && IS_VTX(get(Opcode))((get(Opcode)).TSFlags & R600_InstFlag::VTX_INST)) || IS_TEX(get(Opcode))((get(Opcode)).TSFlags & R600_InstFlag::TEX_INST);
211}
212
213bool R600InstrInfo::usesTextureCache(const MachineInstr &MI) const {
214 const MachineFunction *MF = MI.getParent()->getParent();
215 return (AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
216 usesVertexCache(MI.getOpcode())) ||
217 usesTextureCache(MI.getOpcode());
218}
219
220bool R600InstrInfo::mustBeLastInClause(unsigned Opcode) const {
221 switch (Opcode) {
222 case R600::KILLGT:
223 case R600::GROUP_BARRIER:
224 return true;
225 default:
226 return false;
227 }
228}
229
230bool R600InstrInfo::usesAddressRegister(MachineInstr &MI) const {
231 return MI.findRegisterUseOperandIdx(R600::AR_X, false, &RI) != -1;
232}
233
234bool R600InstrInfo::definesAddressRegister(MachineInstr &MI) const {
235 return MI.findRegisterDefOperandIdx(R600::AR_X, false, false, &RI) != -1;
236}
237
238bool R600InstrInfo::readsLDSSrcReg(const MachineInstr &MI) const {
239 if (!isALUInstr(MI.getOpcode())) {
240 return false;
241 }
242 for (MachineInstr::const_mop_iterator I = MI.operands_begin(),
243 E = MI.operands_end();
244 I != E; ++I) {
245 if (!I->isReg() || !I->isUse() ||
246 TargetRegisterInfo::isVirtualRegister(I->getReg()))
247 continue;
248
249 if (R600::R600_LDS_SRC_REGRegClass.contains(I->getReg()))
250 return true;
251 }
252 return false;
253}
254
255int R600InstrInfo::getSelIdx(unsigned Opcode, unsigned SrcIdx) const {
256 static const unsigned SrcSelTable[][2] = {
257 {R600::OpName::src0, R600::OpName::src0_sel},
258 {R600::OpName::src1, R600::OpName::src1_sel},
259 {R600::OpName::src2, R600::OpName::src2_sel},
260 {R600::OpName::src0_X, R600::OpName::src0_sel_X},
261 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
262 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
263 {R600::OpName::src0_W, R600::OpName::src0_sel_W},
264 {R600::OpName::src1_X, R600::OpName::src1_sel_X},
265 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
266 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
267 {R600::OpName::src1_W, R600::OpName::src1_sel_W}
268 };
269
270 for (const auto &Row : SrcSelTable) {
271 if (getOperandIdx(Opcode, Row[0]) == (int)SrcIdx) {
272 return getOperandIdx(Opcode, Row[1]);
273 }
274 }
275 return -1;
276}
277
278SmallVector<std::pair<MachineOperand *, int64_t>, 3>
279R600InstrInfo::getSrcs(MachineInstr &MI) const {
280 SmallVector<std::pair<MachineOperand *, int64_t>, 3> Result;
281
282 if (MI.getOpcode() == R600::DOT_4) {
283 static const unsigned OpTable[8][2] = {
284 {R600::OpName::src0_X, R600::OpName::src0_sel_X},
285 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
286 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
287 {R600::OpName::src0_W, R600::OpName::src0_sel_W},
288 {R600::OpName::src1_X, R600::OpName::src1_sel_X},
289 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
290 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
291 {R600::OpName::src1_W, R600::OpName::src1_sel_W},
292 };
293
294 for (unsigned j = 0; j < 8; j++) {
295 MachineOperand &MO =
296 MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][0]));
297 unsigned Reg = MO.getReg();
298 if (Reg == R600::ALU_CONST) {
299 MachineOperand &Sel =
300 MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][1]));
301 Result.push_back(std::make_pair(&MO, Sel.getImm()));
302 continue;
303 }
304
305 }
306 return Result;
307 }
308
309 static const unsigned OpTable[3][2] = {
310 {R600::OpName::src0, R600::OpName::src0_sel},
311 {R600::OpName::src1, R600::OpName::src1_sel},
312 {R600::OpName::src2, R600::OpName::src2_sel},
313 };
314
315 for (unsigned j = 0; j < 3; j++) {
316 int SrcIdx = getOperandIdx(MI.getOpcode(), OpTable[j][0]);
317 if (SrcIdx < 0)
318 break;
319 MachineOperand &MO = MI.getOperand(SrcIdx);
320 unsigned Reg = MO.getReg();
321 if (Reg == R600::ALU_CONST) {
322 MachineOperand &Sel =
323 MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][1]));
324 Result.push_back(std::make_pair(&MO, Sel.getImm()));
325 continue;
326 }
327 if (Reg == R600::ALU_LITERAL_X) {
328 MachineOperand &Operand =
329 MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));
330 if (Operand.isImm()) {
331 Result.push_back(std::make_pair(&MO, Operand.getImm()));
332 continue;
333 }
334 assert(Operand.isGlobal())((Operand.isGlobal()) ? static_cast<void> (0) : __assert_fail
("Operand.isGlobal()", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 334, __PRETTY_FUNCTION__))
;
335 }
336 Result.push_back(std::make_pair(&MO, 0));
337 }
338 return Result;
339}
340
341std::vector<std::pair<int, unsigned>>
342R600InstrInfo::ExtractSrcs(MachineInstr &MI,
343 const DenseMap<unsigned, unsigned> &PV,
344 unsigned &ConstCount) const {
345 ConstCount = 0;
346 const std::pair<int, unsigned> DummyPair(-1, 0);
347 std::vector<std::pair<int, unsigned>> Result;
348 unsigned i = 0;
349 for (const auto &Src : getSrcs(MI)) {
350 ++i;
351 unsigned Reg = Src.first->getReg();
352 int Index = RI.getEncodingValue(Reg) & 0xff;
353 if (Reg == R600::OQAP) {
354 Result.push_back(std::make_pair(Index, 0U));
355 }
356 if (PV.find(Reg) != PV.end()) {
357 // 255 is used to tells its a PS/PV reg
358 Result.push_back(std::make_pair(255, 0U));
359 continue;
360 }
361 if (Index > 127) {
362 ConstCount++;
363 Result.push_back(DummyPair);
364 continue;
365 }
366 unsigned Chan = RI.getHWRegChan(Reg);
367 Result.push_back(std::make_pair(Index, Chan));
368 }
369 for (; i < 3; ++i)
370 Result.push_back(DummyPair);
371 return Result;
372}
373
374static std::vector<std::pair<int, unsigned>>
375Swizzle(std::vector<std::pair<int, unsigned>> Src,
376 R600InstrInfo::BankSwizzle Swz) {
377 if (Src[0] == Src[1])
378 Src[1].first = -1;
379 switch (Swz) {
380 case R600InstrInfo::ALU_VEC_012_SCL_210:
381 break;
382 case R600InstrInfo::ALU_VEC_021_SCL_122:
383 std::swap(Src[1], Src[2]);
384 break;
385 case R600InstrInfo::ALU_VEC_102_SCL_221:
386 std::swap(Src[0], Src[1]);
387 break;
388 case R600InstrInfo::ALU_VEC_120_SCL_212:
389 std::swap(Src[0], Src[1]);
390 std::swap(Src[0], Src[2]);
391 break;
392 case R600InstrInfo::ALU_VEC_201:
393 std::swap(Src[0], Src[2]);
394 std::swap(Src[0], Src[1]);
395 break;
396 case R600InstrInfo::ALU_VEC_210:
397 std::swap(Src[0], Src[2]);
398 break;
399 }
400 return Src;
401}
402
403static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {
404 switch (Swz) {
27
Control jumps to 'case ALU_VEC_012_SCL_210:' at line 405
405 case R600InstrInfo::ALU_VEC_012_SCL_210: {
406 unsigned Cycles[3] = { 2, 1, 0};
407 return Cycles[Op];
28
Undefined or garbage value returned to caller
408 }
409 case R600InstrInfo::ALU_VEC_021_SCL_122: {
410 unsigned Cycles[3] = { 1, 2, 2};
411 return Cycles[Op];
412 }
413 case R600InstrInfo::ALU_VEC_120_SCL_212: {
414 unsigned Cycles[3] = { 2, 1, 2};
415 return Cycles[Op];
416 }
417 case R600InstrInfo::ALU_VEC_102_SCL_221: {
418 unsigned Cycles[3] = { 2, 2, 1};
419 return Cycles[Op];
420 }
421 default:
422 llvm_unreachable("Wrong Swizzle for Trans Slot")::llvm::llvm_unreachable_internal("Wrong Swizzle for Trans Slot"
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 422)
;
423 }
424}
425
426/// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
427/// in the same Instruction Group while meeting read port limitations given a
428/// Swz swizzle sequence.
429unsigned R600InstrInfo::isLegalUpTo(
430 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
431 const std::vector<R600InstrInfo::BankSwizzle> &Swz,
432 const std::vector<std::pair<int, unsigned>> &TransSrcs,
433 R600InstrInfo::BankSwizzle TransSwz) const {
434 int Vector[4][3];
435 memset(Vector, -1, sizeof(Vector));
436 for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
7
Assuming 'i' is >= 'e'
8
Loop condition is false. Execution continues on line 460
437 const std::vector<std::pair<int, unsigned>> &Srcs =
438 Swizzle(IGSrcs[i], Swz[i]);
439 for (unsigned j = 0; j < 3; j++) {
440 const std::pair<int, unsigned> &Src = Srcs[j];
441 if (Src.first < 0 || Src.first == 255)
442 continue;
443 if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))((RI.getEncodingValue(R600::OQAP)) & 0x1ff)) {
444 if (Swz[i] != R600InstrInfo::ALU_VEC_012_SCL_210 &&
445 Swz[i] != R600InstrInfo::ALU_VEC_021_SCL_122) {
446 // The value from output queue A (denoted by register OQAP) can
447 // only be fetched during the first cycle.
448 return false;
449 }
450 // OQAP does not count towards the normal read port restrictions
451 continue;
452 }
453 if (Vector[Src.second][j] < 0)
454 Vector[Src.second][j] = Src.first;
455 if (Vector[Src.second][j] != Src.first)
456 return i;
457 }
458 }
459 // Now check Trans Alu
460 for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
9
Assuming 'i' is < 'e'
10
Loop condition is true. Entering loop body
14
Assuming 'i' is < 'e'
15
Loop condition is true. Entering loop body
19
Assuming 'i' is < 'e'
20
Loop condition is true. Entering loop body
24
Assuming 'i' is < 'e'
25
Loop condition is true. Entering loop body
461 const std::pair<int, unsigned> &Src = TransSrcs[i];
462 unsigned Cycle = getTransSwizzle(TransSwz, i);
26
Calling 'getTransSwizzle'
463 if (Src.first < 0)
11
Assuming the condition is true
12
Taking true branch
16
Assuming the condition is true
17
Taking true branch
21
Assuming the condition is true
22
Taking true branch
464 continue;
13
Execution continues on line 460
18
Execution continues on line 460
23
Execution continues on line 460
465 if (Src.first == 255)
466 continue;
467 if (Vector[Src.second][Cycle] < 0)
468 Vector[Src.second][Cycle] = Src.first;
469 if (Vector[Src.second][Cycle] != Src.first)
470 return IGSrcs.size() - 1;
471 }
472 return IGSrcs.size();
473}
474
475/// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
476/// (in lexicographic term) swizzle sequence assuming that all swizzles after
477/// Idx can be skipped
478static bool
479NextPossibleSolution(
480 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
481 unsigned Idx) {
482 assert(Idx < SwzCandidate.size())((Idx < SwzCandidate.size()) ? static_cast<void> (0)
: __assert_fail ("Idx < SwzCandidate.size()", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 482, __PRETTY_FUNCTION__))
;
483 int ResetIdx = Idx;
484 while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)
485 ResetIdx --;
486 for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
487 SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;
488 }
489 if (ResetIdx == -1)
490 return false;
491 int NextSwizzle = SwzCandidate[ResetIdx] + 1;
492 SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;
493 return true;
494}
495
496/// Enumerate all possible Swizzle sequence to find one that can meet all
497/// read port requirements.
498bool R600InstrInfo::FindSwizzleForVectorSlot(
499 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
500 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
501 const std::vector<std::pair<int, unsigned>> &TransSrcs,
502 R600InstrInfo::BankSwizzle TransSwz) const {
503 unsigned ValidUpTo = 0;
504 do {
505 ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
6
Calling 'R600InstrInfo::isLegalUpTo'
506 if (ValidUpTo == IGSrcs.size())
507 return true;
508 } while (NextPossibleSolution(SwzCandidate, ValidUpTo));
509 return false;
510}
511
512/// Instructions in Trans slot can't read gpr at cycle 0 if they also read
513/// a const, and can't read a gpr at cycle 1 if they read 2 const.
514static bool
515isConstCompatible(R600InstrInfo::BankSwizzle TransSwz,
516 const std::vector<std::pair<int, unsigned>> &TransOps,
517 unsigned ConstCount) {
518 // TransALU can't read 3 constants
519 if (ConstCount > 2)
520 return false;
521 for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
522 const std::pair<int, unsigned> &Src = TransOps[i];
523 unsigned Cycle = getTransSwizzle(TransSwz, i);
524 if (Src.first < 0)
525 continue;
526 if (ConstCount > 0 && Cycle == 0)
527 return false;
528 if (ConstCount > 1 && Cycle == 1)
529 return false;
530 }
531 return true;
532}
533
534bool
535R600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
536 const DenseMap<unsigned, unsigned> &PV,
537 std::vector<BankSwizzle> &ValidSwizzle,
538 bool isLastAluTrans)
539 const {
540 //Todo : support shared src0 - src1 operand
541
542 std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;
543 ValidSwizzle.clear();
544 unsigned ConstCount;
545 BankSwizzle TransBS = ALU_VEC_012_SCL_210;
546 for (unsigned i = 0, e = IG.size(); i < e; ++i) {
1
Assuming 'i' is >= 'e'
2
Loop condition is false. Execution continues on line 553
547 IGSrcs.push_back(ExtractSrcs(*IG[i], PV, ConstCount));
548 unsigned Op = getOperandIdx(IG[i]->getOpcode(),
549 R600::OpName::bank_swizzle);
550 ValidSwizzle.push_back( (R600InstrInfo::BankSwizzle)
551 IG[i]->getOperand(Op).getImm());
552 }
553 std::vector<std::pair<int, unsigned>> TransOps;
554 if (!isLastAluTrans)
3
Assuming 'isLastAluTrans' is 0
4
Taking true branch
555 return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);
5
Calling 'R600InstrInfo::FindSwizzleForVectorSlot'
556
557 TransOps = std::move(IGSrcs.back());
558 IGSrcs.pop_back();
559 ValidSwizzle.pop_back();
560
561 static const R600InstrInfo::BankSwizzle TransSwz[] = {
562 ALU_VEC_012_SCL_210,
563 ALU_VEC_021_SCL_122,
564 ALU_VEC_120_SCL_212,
565 ALU_VEC_102_SCL_221
566 };
567 for (unsigned i = 0; i < 4; i++) {
568 TransBS = TransSwz[i];
569 if (!isConstCompatible(TransBS, TransOps, ConstCount))
570 continue;
571 bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,
572 TransBS);
573 if (Result) {
574 ValidSwizzle.push_back(TransBS);
575 return true;
576 }
577 }
578
579 return false;
580}
581
582bool
583R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
584 const {
585 assert (Consts.size() <= 12 && "Too many operands in instructions group")((Consts.size() <= 12 && "Too many operands in instructions group"
) ? static_cast<void> (0) : __assert_fail ("Consts.size() <= 12 && \"Too many operands in instructions group\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 585, __PRETTY_FUNCTION__))
;
586 unsigned Pair1 = 0, Pair2 = 0;
587 for (unsigned i = 0, n = Consts.size(); i < n; ++i) {
588 unsigned ReadConstHalf = Consts[i] & 2;
589 unsigned ReadConstIndex = Consts[i] & (~3);
590 unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
591 if (!Pair1) {
592 Pair1 = ReadHalfConst;
593 continue;
594 }
595 if (Pair1 == ReadHalfConst)
596 continue;
597 if (!Pair2) {
598 Pair2 = ReadHalfConst;
599 continue;
600 }
601 if (Pair2 != ReadHalfConst)
602 return false;
603 }
604 return true;
605}
606
607bool
608R600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)
609 const {
610 std::vector<unsigned> Consts;
611 SmallSet<int64_t, 4> Literals;
612 for (unsigned i = 0, n = MIs.size(); i < n; i++) {
613 MachineInstr &MI = *MIs[i];
614 if (!isALUInstr(MI.getOpcode()))
615 continue;
616
617 for (const auto &Src : getSrcs(MI)) {
618 if (Src.first->getReg() == R600::ALU_LITERAL_X)
619 Literals.insert(Src.second);
620 if (Literals.size() > 4)
621 return false;
622 if (Src.first->getReg() == R600::ALU_CONST)
623 Consts.push_back(Src.second);
624 if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||
625 R600::R600_KC1RegClass.contains(Src.first->getReg())) {
626 unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
627 unsigned Chan = RI.getHWRegChan(Src.first->getReg());
628 Consts.push_back((Index << 2) | Chan);
629 }
630 }
631 }
632 return fitsConstReadLimitations(Consts);
633}
634
635DFAPacketizer *
636R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo &STI) const {
637 const InstrItineraryData *II = STI.getInstrItineraryData();
638 return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);
639}
640
641static bool
642isPredicateSetter(unsigned Opcode) {
643 switch (Opcode) {
644 case R600::PRED_X:
645 return true;
646 default:
647 return false;
648 }
649}
650
651static MachineInstr *
652findFirstPredicateSetterFrom(MachineBasicBlock &MBB,
653 MachineBasicBlock::iterator I) {
654 while (I != MBB.begin()) {
655 --I;
656 MachineInstr &MI = *I;
657 if (isPredicateSetter(MI.getOpcode()))
658 return &MI;
659 }
660
661 return nullptr;
662}
663
664static
665bool isJump(unsigned Opcode) {
666 return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
667}
668
669static bool isBranch(unsigned Opcode) {
670 return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
671 Opcode == R600::BRANCH_COND_f32;
672}
673
674bool R600InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
675 MachineBasicBlock *&TBB,
676 MachineBasicBlock *&FBB,
677 SmallVectorImpl<MachineOperand> &Cond,
678 bool AllowModify) const {
679 // Most of the following comes from the ARM implementation of AnalyzeBranch
680
681 // If the block has no terminators, it just falls into the block after it.
682 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
683 if (I == MBB.end())
684 return false;
685
686 // R600::BRANCH* instructions are only available after isel and are not
687 // handled
688 if (isBranch(I->getOpcode()))
689 return true;
690 if (!isJump(I->getOpcode())) {
691 return false;
692 }
693
694 // Remove successive JUMP
695 while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {
696 MachineBasicBlock::iterator PriorI = std::prev(I);
697 if (AllowModify)
698 I->removeFromParent();
699 I = PriorI;
700 }
701 MachineInstr &LastInst = *I;
702
703 // If there is only one terminator instruction, process it.
704 unsigned LastOpc = LastInst.getOpcode();
705 if (I == MBB.begin() || !isJump((--I)->getOpcode())) {
706 if (LastOpc == R600::JUMP) {
707 TBB = LastInst.getOperand(0).getMBB();
708 return false;
709 } else if (LastOpc == R600::JUMP_COND) {
710 auto predSet = I;
711 while (!isPredicateSetter(predSet->getOpcode())) {
712 predSet = --I;
713 }
714 TBB = LastInst.getOperand(0).getMBB();
715 Cond.push_back(predSet->getOperand(1));
716 Cond.push_back(predSet->getOperand(2));
717 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
718 return false;
719 }
720 return true; // Can't handle indirect branch.
721 }
722
723 // Get the instruction before it if it is a terminator.
724 MachineInstr &SecondLastInst = *I;
725 unsigned SecondLastOpc = SecondLastInst.getOpcode();
726
727 // If the block ends with a B and a Bcc, handle it.
728 if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
729 auto predSet = --I;
730 while (!isPredicateSetter(predSet->getOpcode())) {
731 predSet = --I;
732 }
733 TBB = SecondLastInst.getOperand(0).getMBB();
734 FBB = LastInst.getOperand(0).getMBB();
735 Cond.push_back(predSet->getOperand(1));
736 Cond.push_back(predSet->getOperand(2));
737 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
738 return false;
739 }
740
741 // Otherwise, can't handle this.
742 return true;
743}
744
745static
746MachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB) {
747 for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
748 It != E; ++It) {
749 if (It->getOpcode() == R600::CF_ALU ||
750 It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
751 return It.getReverse();
752 }
753 return MBB.end();
754}
755
756unsigned R600InstrInfo::insertBranch(MachineBasicBlock &MBB,
757 MachineBasicBlock *TBB,
758 MachineBasicBlock *FBB,
759 ArrayRef<MachineOperand> Cond,
760 const DebugLoc &DL,
761 int *BytesAdded) const {
762 assert(TBB && "insertBranch must not be told to insert a fallthrough")((TBB && "insertBranch must not be told to insert a fallthrough"
) ? static_cast<void> (0) : __assert_fail ("TBB && \"insertBranch must not be told to insert a fallthrough\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 762, __PRETTY_FUNCTION__))
;
763 assert(!BytesAdded && "code size not handled")((!BytesAdded && "code size not handled") ? static_cast
<void> (0) : __assert_fail ("!BytesAdded && \"code size not handled\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 763, __PRETTY_FUNCTION__))
;
764
765 if (!FBB) {
766 if (Cond.empty()) {
767 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);
768 return 1;
769 } else {
770 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
771 assert(PredSet && "No previous predicate !")((PredSet && "No previous predicate !") ? static_cast
<void> (0) : __assert_fail ("PredSet && \"No previous predicate !\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 771, __PRETTY_FUNCTION__))
;
772 addFlag(*PredSet, 0, MO_FLAG_PUSH(1 << 4));
773 PredSet->getOperand(2).setImm(Cond[1].getImm());
774
775 BuildMI(&MBB, DL, get(R600::JUMP_COND))
776 .addMBB(TBB)
777 .addReg(R600::PREDICATE_BIT, RegState::Kill);
778 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
779 if (CfAlu == MBB.end())
780 return 1;
781 assert (CfAlu->getOpcode() == R600::CF_ALU)((CfAlu->getOpcode() == R600::CF_ALU) ? static_cast<void
> (0) : __assert_fail ("CfAlu->getOpcode() == R600::CF_ALU"
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 781, __PRETTY_FUNCTION__))
;
782 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
783 return 1;
784 }
785 } else {
786 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
787 assert(PredSet && "No previous predicate !")((PredSet && "No previous predicate !") ? static_cast
<void> (0) : __assert_fail ("PredSet && \"No previous predicate !\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 787, __PRETTY_FUNCTION__))
;
788 addFlag(*PredSet, 0, MO_FLAG_PUSH(1 << 4));
789 PredSet->getOperand(2).setImm(Cond[1].getImm());
790 BuildMI(&MBB, DL, get(R600::JUMP_COND))
791 .addMBB(TBB)
792 .addReg(R600::PREDICATE_BIT, RegState::Kill);
793 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(FBB);
794 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
795 if (CfAlu == MBB.end())
796 return 2;
797 assert (CfAlu->getOpcode() == R600::CF_ALU)((CfAlu->getOpcode() == R600::CF_ALU) ? static_cast<void
> (0) : __assert_fail ("CfAlu->getOpcode() == R600::CF_ALU"
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 797, __PRETTY_FUNCTION__))
;
798 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
799 return 2;
800 }
801}
802
803unsigned R600InstrInfo::removeBranch(MachineBasicBlock &MBB,
804 int *BytesRemoved) const {
805 assert(!BytesRemoved && "code size not handled")((!BytesRemoved && "code size not handled") ? static_cast
<void> (0) : __assert_fail ("!BytesRemoved && \"code size not handled\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 805, __PRETTY_FUNCTION__))
;
806
807 // Note : we leave PRED* instructions there.
808 // They may be needed when predicating instructions.
809
810 MachineBasicBlock::iterator I = MBB.end();
811
812 if (I == MBB.begin()) {
813 return 0;
814 }
815 --I;
816 switch (I->getOpcode()) {
817 default:
818 return 0;
819 case R600::JUMP_COND: {
820 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
821 clearFlag(*predSet, 0, MO_FLAG_PUSH(1 << 4));
822 I->eraseFromParent();
823 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
824 if (CfAlu == MBB.end())
825 break;
826 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE)((CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE) ? static_cast
<void> (0) : __assert_fail ("CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE"
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 826, __PRETTY_FUNCTION__))
;
827 CfAlu->setDesc(get(R600::CF_ALU));
828 break;
829 }
830 case R600::JUMP:
831 I->eraseFromParent();
832 break;
833 }
834 I = MBB.end();
835
836 if (I == MBB.begin()) {
837 return 1;
838 }
839 --I;
840 switch (I->getOpcode()) {
841 // FIXME: only one case??
842 default:
843 return 1;
844 case R600::JUMP_COND: {
845 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
846 clearFlag(*predSet, 0, MO_FLAG_PUSH(1 << 4));
847 I->eraseFromParent();
848 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
849 if (CfAlu == MBB.end())
850 break;
851 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE)((CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE) ? static_cast
<void> (0) : __assert_fail ("CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE"
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 851, __PRETTY_FUNCTION__))
;
852 CfAlu->setDesc(get(R600::CF_ALU));
853 break;
854 }
855 case R600::JUMP:
856 I->eraseFromParent();
857 break;
858 }
859 return 2;
860}
861
862bool R600InstrInfo::isPredicated(const MachineInstr &MI) const {
863 int idx = MI.findFirstPredOperandIdx();
864 if (idx < 0)
865 return false;
866
867 unsigned Reg = MI.getOperand(idx).getReg();
868 switch (Reg) {
869 default: return false;
870 case R600::PRED_SEL_ONE:
871 case R600::PRED_SEL_ZERO:
872 case R600::PREDICATE_BIT:
873 return true;
874 }
875}
876
877bool R600InstrInfo::isPredicable(const MachineInstr &MI) const {
878 // XXX: KILL* instructions can be predicated, but they must be the last
879 // instruction in a clause, so this means any instructions after them cannot
880 // be predicated. Until we have proper support for instruction clauses in the
881 // backend, we will mark KILL* instructions as unpredicable.
882
883 if (MI.getOpcode() == R600::KILLGT) {
884 return false;
885 } else if (MI.getOpcode() == R600::CF_ALU) {
886 // If the clause start in the middle of MBB then the MBB has more
887 // than a single clause, unable to predicate several clauses.
888 if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))
889 return false;
890 // TODO: We don't support KC merging atm
891 return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
892 } else if (isVector(MI)) {
893 return false;
894 } else {
895 return TargetInstrInfo::isPredicable(MI);
896 }
897}
898
899bool
900R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
901 unsigned NumCycles,
902 unsigned ExtraPredCycles,
903 BranchProbability Probability) const{
904 return true;
905}
906
907bool
908R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
909 unsigned NumTCycles,
910 unsigned ExtraTCycles,
911 MachineBasicBlock &FMBB,
912 unsigned NumFCycles,
913 unsigned ExtraFCycles,
914 BranchProbability Probability) const {
915 return true;
916}
917
918bool
919R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
920 unsigned NumCycles,
921 BranchProbability Probability)
922 const {
923 return true;
924}
925
926bool
927R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
928 MachineBasicBlock &FMBB) const {
929 return false;
930}
931
932bool
933R600InstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
934 MachineOperand &MO = Cond[1];
935 switch (MO.getImm()) {
936 case R600::PRED_SETE_INT:
937 MO.setImm(R600::PRED_SETNE_INT);
938 break;
939 case R600::PRED_SETNE_INT:
940 MO.setImm(R600::PRED_SETE_INT);
941 break;
942 case R600::PRED_SETE:
943 MO.setImm(R600::PRED_SETNE);
944 break;
945 case R600::PRED_SETNE:
946 MO.setImm(R600::PRED_SETE);
947 break;
948 default:
949 return true;
950 }
951
952 MachineOperand &MO2 = Cond[2];
953 switch (MO2.getReg()) {
954 case R600::PRED_SEL_ZERO:
955 MO2.setReg(R600::PRED_SEL_ONE);
956 break;
957 case R600::PRED_SEL_ONE:
958 MO2.setReg(R600::PRED_SEL_ZERO);
959 break;
960 default:
961 return true;
962 }
963 return false;
964}
965
966bool R600InstrInfo::DefinesPredicate(MachineInstr &MI,
967 std::vector<MachineOperand> &Pred) const {
968 return isPredicateSetter(MI.getOpcode());
969}
970
971bool R600InstrInfo::PredicateInstruction(MachineInstr &MI,
972 ArrayRef<MachineOperand> Pred) const {
973 int PIdx = MI.findFirstPredOperandIdx();
974
975 if (MI.getOpcode() == R600::CF_ALU) {
976 MI.getOperand(8).setImm(0);
977 return true;
978 }
979
980 if (MI.getOpcode() == R600::DOT_4) {
981 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))
982 .setReg(Pred[2].getReg());
983 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))
984 .setReg(Pred[2].getReg());
985 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))
986 .setReg(Pred[2].getReg());
987 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))
988 .setReg(Pred[2].getReg());
989 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
990 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
991 return true;
992 }
993
994 if (PIdx != -1) {
995 MachineOperand &PMO = MI.getOperand(PIdx);
996 PMO.setReg(Pred[2].getReg());
997 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
998 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
999 return true;
1000 }
1001
1002 return false;
1003}
1004
1005unsigned int R600InstrInfo::getPredicationCost(const MachineInstr &) const {
1006 return 2;
1007}
1008
1009unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
1010 const MachineInstr &,
1011 unsigned *PredCost) const {
1012 if (PredCost)
1013 *PredCost = 2;
1014 return 2;
1015}
1016
1017unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
1018 unsigned Channel) const {
1019 assert(Channel == 0)((Channel == 0) ? static_cast<void> (0) : __assert_fail
("Channel == 0", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1019, __PRETTY_FUNCTION__))
;
1020 return RegIndex;
1021}
1022
1023bool R600InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
1024 switch (MI.getOpcode()) {
1025 default: {
1026 MachineBasicBlock *MBB = MI.getParent();
1027 int OffsetOpIdx =
1028 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
1029 // addr is a custom operand with multiple MI operands, and only the
1030 // first MI operand is given a name.
1031 int RegOpIdx = OffsetOpIdx + 1;
1032 int ChanOpIdx =
1033 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
1034 if (isRegisterLoad(MI)) {
1035 int DstOpIdx =
1036 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
1037 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1038 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1039 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1040 unsigned OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1041 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1042 buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),
1043 getIndirectAddrRegClass()->getRegister(Address));
1044 } else {
1045 buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
1046 OffsetReg);
1047 }
1048 } else if (isRegisterStore(MI)) {
1049 int ValOpIdx =
1050 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
1051 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1052 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1053 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1054 unsigned OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1055 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1056 buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
1057 MI.getOperand(ValOpIdx).getReg());
1058 } else {
1059 buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
1060 calculateIndirectAddress(RegIndex, Channel),
1061 OffsetReg);
1062 }
1063 } else {
1064 return false;
1065 }
1066
1067 MBB->erase(MI);
1068 return true;
1069 }
1070 case R600::R600_EXTRACT_ELT_V2:
1071 case R600::R600_EXTRACT_ELT_V4:
1072 buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
1073 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1074 MI.getOperand(2).getReg(),
1075 RI.getHWRegChan(MI.getOperand(1).getReg()));
1076 break;
1077 case R600::R600_INSERT_ELT_V2:
1078 case R600::R600_INSERT_ELT_V4:
1079 buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value
1080 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1081 MI.getOperand(3).getReg(), // Offset
1082 RI.getHWRegChan(MI.getOperand(1).getReg())); // Channel
1083 break;
1084 }
1085 MI.eraseFromParent();
1086 return true;
1087}
1088
1089void R600InstrInfo::reserveIndirectRegisters(BitVector &Reserved,
1090 const MachineFunction &MF,
1091 const R600RegisterInfo &TRI) const {
1092 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1093 const R600FrameLowering *TFL = ST.getFrameLowering();
1094
1095 unsigned StackWidth = TFL->getStackWidth(MF);
1096 int End = getIndirectIndexEnd(MF);
1097
1098 if (End == -1)
1099 return;
1100
1101 for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
1102 for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
1103 unsigned Reg = R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
1104 TRI.reserveRegisterTuples(Reserved, Reg);
1105 }
1106 }
1107}
1108
1109const TargetRegisterClass *R600InstrInfo::getIndirectAddrRegClass() const {
1110 return &R600::R600_TReg32_XRegClass;
1111}
1112
1113MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1114 MachineBasicBlock::iterator I,
1115 unsigned ValueReg, unsigned Address,
1116 unsigned OffsetReg) const {
1117 return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);
1118}
1119
1120MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1121 MachineBasicBlock::iterator I,
1122 unsigned ValueReg, unsigned Address,
1123 unsigned OffsetReg,
1124 unsigned AddrChan) const {
1125 unsigned AddrReg;
1126 switch (AddrChan) {
1127 default: llvm_unreachable("Invalid Channel")::llvm::llvm_unreachable_internal("Invalid Channel", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1127)
;
1128 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1129 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1130 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1131 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1132 }
1133 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1134 R600::AR_X, OffsetReg);
1135 setImmOperand(*MOVA, R600::OpName::write, 0);
1136
1137 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
1138 AddrReg, ValueReg)
1139 .addReg(R600::AR_X,
1140 RegState::Implicit | RegState::Kill);
1141 setImmOperand(*Mov, R600::OpName::dst_rel, 1);
1142 return Mov;
1143}
1144
1145MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1146 MachineBasicBlock::iterator I,
1147 unsigned ValueReg, unsigned Address,
1148 unsigned OffsetReg) const {
1149 return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);
1150}
1151
1152MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1153 MachineBasicBlock::iterator I,
1154 unsigned ValueReg, unsigned Address,
1155 unsigned OffsetReg,
1156 unsigned AddrChan) const {
1157 unsigned AddrReg;
1158 switch (AddrChan) {
1159 default: llvm_unreachable("Invalid Channel")::llvm::llvm_unreachable_internal("Invalid Channel", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1159)
;
1160 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1161 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1162 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1163 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1164 }
1165 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1166 R600::AR_X,
1167 OffsetReg);
1168 setImmOperand(*MOVA, R600::OpName::write, 0);
1169 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
1170 ValueReg,
1171 AddrReg)
1172 .addReg(R600::AR_X,
1173 RegState::Implicit | RegState::Kill);
1174 setImmOperand(*Mov, R600::OpName::src0_rel, 1);
1175
1176 return Mov;
1177}
1178
1179int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
1180 const MachineRegisterInfo &MRI = MF.getRegInfo();
1181 const MachineFrameInfo &MFI = MF.getFrameInfo();
1182 int Offset = -1;
1183
1184 if (MFI.getNumObjects() == 0) {
1185 return -1;
1186 }
1187
1188 if (MRI.livein_empty()) {
1189 return 0;
1190 }
1191
1192 const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
1193 for (std::pair<unsigned, unsigned> LI : MRI.liveins()) {
1194 unsigned Reg = LI.first;
1195 if (TargetRegisterInfo::isVirtualRegister(Reg) ||
1196 !IndirectRC->contains(Reg))
1197 continue;
1198
1199 unsigned RegIndex;
1200 unsigned RegEnd;
1201 for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
1202 ++RegIndex) {
1203 if (IndirectRC->getRegister(RegIndex) == Reg)
1204 break;
1205 }
1206 Offset = std::max(Offset, (int)RegIndex);
1207 }
1208
1209 return Offset + 1;
1210}
1211
1212int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
1213 int Offset = 0;
1214 const MachineFrameInfo &MFI = MF.getFrameInfo();
1215
1216 // Variable sized objects are not supported
1217 if (MFI.hasVarSizedObjects()) {
1218 return -1;
1219 }
1220
1221 if (MFI.getNumObjects() == 0) {
1222 return -1;
1223 }
1224
1225 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1226 const R600FrameLowering *TFL = ST.getFrameLowering();
1227
1228 unsigned IgnoredFrameReg;
1229 Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg);
1230
1231 return getIndirectIndexBegin(MF) + Offset;
1232}
1233
1234unsigned R600InstrInfo::getMaxAlusPerClause() const {
1235 return 115;
1236}
1237
1238MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
1239 MachineBasicBlock::iterator I,
1240 unsigned Opcode,
1241 unsigned DstReg,
1242 unsigned Src0Reg,
1243 unsigned Src1Reg) const {
1244 MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
1245 DstReg); // $dst
1246
1247 if (Src1Reg) {
1248 MIB.addImm(0) // $update_exec_mask
1249 .addImm(0); // $update_predicate
1250 }
1251 MIB.addImm(1) // $write
1252 .addImm(0) // $omod
1253 .addImm(0) // $dst_rel
1254 .addImm(0) // $dst_clamp
1255 .addReg(Src0Reg) // $src0
1256 .addImm(0) // $src0_neg
1257 .addImm(0) // $src0_rel
1258 .addImm(0) // $src0_abs
1259 .addImm(-1); // $src0_sel
1260
1261 if (Src1Reg) {
1262 MIB.addReg(Src1Reg) // $src1
1263 .addImm(0) // $src1_neg
1264 .addImm(0) // $src1_rel
1265 .addImm(0) // $src1_abs
1266 .addImm(-1); // $src1_sel
1267 }
1268
1269 //XXX: The r600g finalizer expects this to be 1, once we've moved the
1270 //scheduling to the backend, we can change the default to 0.
1271 MIB.addImm(1) // $last
1272 .addReg(R600::PRED_SEL_OFF) // $pred_sel
1273 .addImm(0) // $literal
1274 .addImm(0); // $bank_swizzle
1275
1276 return MIB;
1277}
1278
1279#define OPERAND_CASE(Label) \
1280 case Label: { \
1281 static const unsigned Ops[] = \
1282 { \
1283 Label##_X, \
1284 Label##_Y, \
1285 Label##_Z, \
1286 Label##_W \
1287 }; \
1288 return Ops[Slot]; \
1289 }
1290
1291static unsigned getSlotedOps(unsigned Op, unsigned Slot) {
1292 switch (Op) {
1293 OPERAND_CASE(R600::OpName::update_exec_mask)
1294 OPERAND_CASE(R600::OpName::update_pred)
1295 OPERAND_CASE(R600::OpName::write)
1296 OPERAND_CASE(R600::OpName::omod)
1297 OPERAND_CASE(R600::OpName::dst_rel)
1298 OPERAND_CASE(R600::OpName::clamp)
1299 OPERAND_CASE(R600::OpName::src0)
1300 OPERAND_CASE(R600::OpName::src0_neg)
1301 OPERAND_CASE(R600::OpName::src0_rel)
1302 OPERAND_CASE(R600::OpName::src0_abs)
1303 OPERAND_CASE(R600::OpName::src0_sel)
1304 OPERAND_CASE(R600::OpName::src1)
1305 OPERAND_CASE(R600::OpName::src1_neg)
1306 OPERAND_CASE(R600::OpName::src1_rel)
1307 OPERAND_CASE(R600::OpName::src1_abs)
1308 OPERAND_CASE(R600::OpName::src1_sel)
1309 OPERAND_CASE(R600::OpName::pred_sel)
1310 default:
1311 llvm_unreachable("Wrong Operand")::llvm::llvm_unreachable_internal("Wrong Operand", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1311)
;
1312 }
1313}
1314
1315#undef OPERAND_CASE
1316
1317MachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(
1318 MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
1319 const {
1320 assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented")((MI->getOpcode() == R600::DOT_4 && "Not Implemented"
) ? static_cast<void> (0) : __assert_fail ("MI->getOpcode() == R600::DOT_4 && \"Not Implemented\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1320, __PRETTY_FUNCTION__))
;
1321 unsigned Opcode;
1322 if (ST.getGeneration() <= AMDGPUSubtarget::R700)
1323 Opcode = R600::DOT4_r600;
1324 else
1325 Opcode = R600::DOT4_eg;
1326 MachineBasicBlock::iterator I = MI;
1327 MachineOperand &Src0 = MI->getOperand(
1328 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));
1329 MachineOperand &Src1 = MI->getOperand(
1330 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));
1331 MachineInstr *MIB = buildDefaultInstruction(
1332 MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
1333 static const unsigned Operands[14] = {
1334 R600::OpName::update_exec_mask,
1335 R600::OpName::update_pred,
1336 R600::OpName::write,
1337 R600::OpName::omod,
1338 R600::OpName::dst_rel,
1339 R600::OpName::clamp,
1340 R600::OpName::src0_neg,
1341 R600::OpName::src0_rel,
1342 R600::OpName::src0_abs,
1343 R600::OpName::src0_sel,
1344 R600::OpName::src1_neg,
1345 R600::OpName::src1_rel,
1346 R600::OpName::src1_abs,
1347 R600::OpName::src1_sel,
1348 };
1349
1350 MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
1351 getSlotedOps(R600::OpName::pred_sel, Slot)));
1352 MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))
1353 .setReg(MO.getReg());
1354
1355 for (unsigned i = 0; i < 14; i++) {
1356 MachineOperand &MO = MI->getOperand(
1357 getOperandIdx(MI->getOpcode(), getSlotedOps(Operands[i], Slot)));
1358 assert (MO.isImm())((MO.isImm()) ? static_cast<void> (0) : __assert_fail (
"MO.isImm()", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1358, __PRETTY_FUNCTION__))
;
1359 setImmOperand(*MIB, Operands[i], MO.getImm());
1360 }
1361 MIB->getOperand(20).setImm(0);
1362 return MIB;
1363}
1364
1365MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
1366 MachineBasicBlock::iterator I,
1367 unsigned DstReg,
1368 uint64_t Imm) const {
1369 MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,
1370 R600::ALU_LITERAL_X);
1371 setImmOperand(*MovImm, R600::OpName::literal, Imm);
1372 return MovImm;
1373}
1374
1375MachineInstr *R600InstrInfo::buildMovInstr(MachineBasicBlock *MBB,
1376 MachineBasicBlock::iterator I,
1377 unsigned DstReg, unsigned SrcReg) const {
1378 return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);
1379}
1380
1381int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
1382 return getOperandIdx(MI.getOpcode(), Op);
1383}
1384
1385int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
1386 return R600::getNamedOperandIdx(Opcode, Op);
1387}
1388
1389void R600InstrInfo::setImmOperand(MachineInstr &MI, unsigned Op,
1390 int64_t Imm) const {
1391 int Idx = getOperandIdx(MI, Op);
1392 assert(Idx != -1 && "Operand not supported for this instruction.")((Idx != -1 && "Operand not supported for this instruction."
) ? static_cast<void> (0) : __assert_fail ("Idx != -1 && \"Operand not supported for this instruction.\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1392, __PRETTY_FUNCTION__))
;
1393 assert(MI.getOperand(Idx).isImm())((MI.getOperand(Idx).isImm()) ? static_cast<void> (0) :
__assert_fail ("MI.getOperand(Idx).isImm()", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1393, __PRETTY_FUNCTION__))
;
1394 MI.getOperand(Idx).setImm(Imm);
1395}
1396
1397//===----------------------------------------------------------------------===//
1398// Instruction flag getters/setters
1399//===----------------------------------------------------------------------===//
1400
1401MachineOperand &R600InstrInfo::getFlagOp(MachineInstr &MI, unsigned SrcIdx,
1402 unsigned Flag) const {
1403 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1404 int FlagIndex = 0;
1405 if (Flag != 0) {
1406 // If we pass something other than the default value of Flag to this
1407 // function, it means we are want to set a flag on an instruction
1408 // that uses native encoding.
1409 assert(HAS_NATIVE_OPERANDS(TargetFlags))((((TargetFlags) & R600_InstFlag::NATIVE_OPERANDS)) ? static_cast
<void> (0) : __assert_fail ("HAS_NATIVE_OPERANDS(TargetFlags)"
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1409, __PRETTY_FUNCTION__))
;
1410 bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
1411 switch (Flag) {
1412 case MO_FLAG_CLAMP(1 << 0):
1413 FlagIndex = getOperandIdx(MI, R600::OpName::clamp);
1414 break;
1415 case MO_FLAG_MASK(1 << 3):
1416 FlagIndex = getOperandIdx(MI, R600::OpName::write);
1417 break;
1418 case MO_FLAG_NOT_LAST(1 << 5):
1419 case MO_FLAG_LAST(1 << 6):
1420 FlagIndex = getOperandIdx(MI, R600::OpName::last);
1421 break;
1422 case MO_FLAG_NEG(1 << 1):
1423 switch (SrcIdx) {
1424 case 0:
1425 FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);
1426 break;
1427 case 1:
1428 FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);
1429 break;
1430 case 2:
1431 FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);
1432 break;
1433 }
1434 break;
1435
1436 case MO_FLAG_ABS(1 << 2):
1437 assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "((!IsOP3 && "Cannot set absolute value modifier for OP3 "
"instructions.") ? static_cast<void> (0) : __assert_fail
("!IsOP3 && \"Cannot set absolute value modifier for OP3 \" \"instructions.\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1438, __PRETTY_FUNCTION__))
1438 "instructions.")((!IsOP3 && "Cannot set absolute value modifier for OP3 "
"instructions.") ? static_cast<void> (0) : __assert_fail
("!IsOP3 && \"Cannot set absolute value modifier for OP3 \" \"instructions.\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1438, __PRETTY_FUNCTION__))
;
1439 (void)IsOP3;
1440 switch (SrcIdx) {
1441 case 0:
1442 FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);
1443 break;
1444 case 1:
1445 FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);
1446 break;
1447 }
1448 break;
1449
1450 default:
1451 FlagIndex = -1;
1452 break;
1453 }
1454 assert(FlagIndex != -1 && "Flag not supported for this instruction")((FlagIndex != -1 && "Flag not supported for this instruction"
) ? static_cast<void> (0) : __assert_fail ("FlagIndex != -1 && \"Flag not supported for this instruction\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1454, __PRETTY_FUNCTION__))
;
1455 } else {
1456 FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags)(((TargetFlags) >> 7) & 0x3);
1457 assert(FlagIndex != 0 &&((FlagIndex != 0 && "Instruction flags not supported for this instruction"
) ? static_cast<void> (0) : __assert_fail ("FlagIndex != 0 && \"Instruction flags not supported for this instruction\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1458, __PRETTY_FUNCTION__))
1458 "Instruction flags not supported for this instruction")((FlagIndex != 0 && "Instruction flags not supported for this instruction"
) ? static_cast<void> (0) : __assert_fail ("FlagIndex != 0 && \"Instruction flags not supported for this instruction\""
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1458, __PRETTY_FUNCTION__))
;
1459 }
1460
1461 MachineOperand &FlagOp = MI.getOperand(FlagIndex);
1462 assert(FlagOp.isImm())((FlagOp.isImm()) ? static_cast<void> (0) : __assert_fail
("FlagOp.isImm()", "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1462, __PRETTY_FUNCTION__))
;
1463 return FlagOp;
1464}
1465
1466void R600InstrInfo::addFlag(MachineInstr &MI, unsigned Operand,
1467 unsigned Flag) const {
1468 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1469 if (Flag == 0) {
1470 return;
1471 }
1472 if (HAS_NATIVE_OPERANDS(TargetFlags)((TargetFlags) & R600_InstFlag::NATIVE_OPERANDS)) {
1473 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1474 if (Flag == MO_FLAG_NOT_LAST(1 << 5)) {
1475 clearFlag(MI, Operand, MO_FLAG_LAST(1 << 6));
1476 } else if (Flag == MO_FLAG_MASK(1 << 3)) {
1477 clearFlag(MI, Operand, Flag);
1478 } else {
1479 FlagOp.setImm(1);
1480 }
1481 } else {
1482 MachineOperand &FlagOp = getFlagOp(MI, Operand);
1483 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS7 * Operand)));
1484 }
1485}
1486
1487void R600InstrInfo::clearFlag(MachineInstr &MI, unsigned Operand,
1488 unsigned Flag) const {
1489 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1490 if (HAS_NATIVE_OPERANDS(TargetFlags)((TargetFlags) & R600_InstFlag::NATIVE_OPERANDS)) {
1491 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1492 FlagOp.setImm(0);
1493 } else {
1494 MachineOperand &FlagOp = getFlagOp(MI);
1495 unsigned InstFlags = FlagOp.getImm();
1496 InstFlags &= ~(Flag << (NUM_MO_FLAGS7 * Operand));
1497 FlagOp.setImm(InstFlags);
1498 }
1499}
1500
1501unsigned R600InstrInfo::getAddressSpaceForPseudoSourceKind(
1502 unsigned Kind) const {
1503 switch (Kind) {
1504 case PseudoSourceValue::Stack:
1505 case PseudoSourceValue::FixedStack:
1506 return AMDGPUAS::PRIVATE_ADDRESS;
1507 case PseudoSourceValue::ConstantPool:
1508 case PseudoSourceValue::GOT:
1509 case PseudoSourceValue::JumpTable:
1510 case PseudoSourceValue::GlobalValueCallEntry:
1511 case PseudoSourceValue::ExternalSymbolCallEntry:
1512 case PseudoSourceValue::TargetCustom:
1513 return AMDGPUAS::CONSTANT_ADDRESS;
1514 }
1515
1516 llvm_unreachable("Invalid pseudo source kind")::llvm::llvm_unreachable_internal("Invalid pseudo source kind"
, "/build/llvm-toolchain-snapshot-9~svn359999/lib/Target/AMDGPU/R600InstrInfo.cpp"
, 1516)
;
1517}