radeonsi: initial WIP SI code
[mesa.git] / src / gallium / drivers / radeon / AMDILMachineFunctionInfo.cpp
1 //===-- AMDILMachineFunctionInfo.cpp - TODO: Add brief description -------===//
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 #include "AMDILMachineFunctionInfo.h"
10 #include "AMDILCompilerErrors.h"
11 #include "AMDILModuleInfo.h"
12 #include "AMDILSubtarget.h"
13 #include "AMDILTargetMachine.h"
14 #include "AMDILUtilityFunctions.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/CodeGen/MachineFrameInfo.h"
17 #include "llvm/CodeGen/MachineModuleInfo.h"
18 #include "llvm/Constants.h"
19 #include "llvm/DerivedTypes.h"
20 #include "llvm/Function.h"
21 #include "llvm/Instructions.h"
22 #include "llvm/Support/FormattedStream.h"
23
24 using namespace llvm;
25
26 static const AMDILConstPtr *getConstPtr(const AMDILKernel *krnl, const std::string &arg) {
27 llvm::SmallVector<AMDILConstPtr, DEFAULT_VEC_SLOTS>::const_iterator begin, end;
28 for (begin = krnl->constPtr.begin(), end = krnl->constPtr.end();
29 begin != end; ++begin) {
30 if (!strcmp(begin->name.data(),arg.c_str())) {
31 return &(*begin);
32 }
33 }
34 return NULL;
35 }
36
37 void PrintfInfo::addOperand(size_t idx, uint32_t size) {
38 mOperands.resize((unsigned)(idx + 1));
39 mOperands[(unsigned)idx] = size;
40 }
41
42 uint32_t PrintfInfo::getPrintfID() {
43 return mPrintfID;
44 }
45
46 void PrintfInfo::setPrintfID(uint32_t id) {
47 mPrintfID = id;
48 }
49
50 size_t PrintfInfo::getNumOperands() {
51 return mOperands.size();
52 }
53
54 uint32_t PrintfInfo::getOperandID(uint32_t idx) {
55 return mOperands[idx];
56 }
57
58 AMDILMachineFunctionInfo::AMDILMachineFunctionInfo()
59 : CalleeSavedFrameSize(0), BytesToPopOnReturn(0),
60 DecorationStyle(None), ReturnAddrIndex(0),
61 TailCallReturnAddrDelta(0),
62 SRetReturnReg(0), UsesLDS(false), LDSArg(false),
63 UsesGDS(false), GDSArg(false),
64 mReservedLits(9)
65 {
66 for (uint32_t x = 0; x < AMDILDevice::MAX_IDS; ++x) {
67 mUsedMem[x] = false;
68 }
69 mMF = NULL;
70 mKernel = NULL;
71 mScratchSize = -1;
72 mArgSize = -1;
73 mStackSize = -1;
74 }
75
76 AMDILMachineFunctionInfo::AMDILMachineFunctionInfo(MachineFunction& MF)
77 : CalleeSavedFrameSize(0), BytesToPopOnReturn(0),
78 DecorationStyle(None), ReturnAddrIndex(0),
79 TailCallReturnAddrDelta(0),
80 SRetReturnReg(0), UsesLDS(false), LDSArg(false),
81 UsesGDS(false), GDSArg(false),
82 mReservedLits(9)
83 {
84 for (uint32_t x = 0; x < AMDILDevice::MAX_IDS; ++x) {
85 mUsedMem[x] = false;
86 }
87 const Function *F = MF.getFunction();
88 mMF = &MF;
89 MachineModuleInfo &mmi = MF.getMMI();
90 const AMDILTargetMachine *TM =
91 reinterpret_cast<const AMDILTargetMachine*>(&MF.getTarget());
92 AMDILModuleInfo *AMI = &(mmi.getObjFileInfo<AMDILModuleInfo>());
93 AMI->processModule(mmi.getModule(), TM);
94 mSTM = TM->getSubtargetImpl();
95 mKernel = AMI->getKernel(F->getName());
96
97 mScratchSize = -1;
98 mArgSize = -1;
99 mStackSize = -1;
100 }
101
102 AMDILMachineFunctionInfo::~AMDILMachineFunctionInfo()
103 {
104 for (std::map<std::string, PrintfInfo*>::iterator pfb = printf_begin(),
105 pfe = printf_end(); pfb != pfe; ++pfb) {
106 delete pfb->second;
107 }
108 }
109 unsigned int
110 AMDILMachineFunctionInfo::getCalleeSavedFrameSize() const
111 {
112 return CalleeSavedFrameSize;
113 }
114 void
115 AMDILMachineFunctionInfo::setCalleeSavedFrameSize(unsigned int bytes)
116 {
117 CalleeSavedFrameSize = bytes;
118 }
119 unsigned int
120 AMDILMachineFunctionInfo::getBytesToPopOnReturn() const
121 {
122 return BytesToPopOnReturn;
123 }
124 void
125 AMDILMachineFunctionInfo::setBytesToPopOnReturn(unsigned int bytes)
126 {
127 BytesToPopOnReturn = bytes;
128 }
129 NameDecorationStyle
130 AMDILMachineFunctionInfo::getDecorationStyle() const
131 {
132 return DecorationStyle;
133 }
134 void
135 AMDILMachineFunctionInfo::setDecorationStyle(NameDecorationStyle style)
136 {
137 DecorationStyle = style;
138 }
139 int
140 AMDILMachineFunctionInfo::getRAIndex() const
141 {
142 return ReturnAddrIndex;
143 }
144 void
145 AMDILMachineFunctionInfo::setRAIndex(int index)
146 {
147 ReturnAddrIndex = index;
148 }
149 int
150 AMDILMachineFunctionInfo::getTCReturnAddrDelta() const
151 {
152 return TailCallReturnAddrDelta;
153 }
154 void
155 AMDILMachineFunctionInfo::setTCReturnAddrDelta(int delta)
156 {
157 TailCallReturnAddrDelta = delta;
158 }
159 unsigned int
160 AMDILMachineFunctionInfo::getSRetReturnReg() const
161 {
162 return SRetReturnReg;
163 }
164 void
165 AMDILMachineFunctionInfo::setSRetReturnReg(unsigned int reg)
166 {
167 SRetReturnReg = reg;
168 }
169
170 void
171 AMDILMachineFunctionInfo::setUsesLocal()
172 {
173 UsesLDS = true;
174 }
175
176 bool
177 AMDILMachineFunctionInfo::usesLocal() const
178 {
179 return UsesLDS;
180 }
181
182 void
183 AMDILMachineFunctionInfo::setHasLocalArg()
184 {
185 LDSArg = true;
186 }
187
188 bool
189 AMDILMachineFunctionInfo::hasLocalArg() const
190 {
191 return LDSArg;
192 }
193
194
195
196 void
197 AMDILMachineFunctionInfo::setUsesRegion()
198 {
199 UsesGDS = true;
200 }
201
202 bool
203 AMDILMachineFunctionInfo::usesRegion() const
204 {
205 return UsesGDS;
206 }
207
208 void
209 AMDILMachineFunctionInfo::setHasRegionArg()
210 {
211 GDSArg = true;
212 }
213
214 bool
215 AMDILMachineFunctionInfo::hasRegionArg() const
216 {
217 return GDSArg;
218 }
219
220
221 bool
222 AMDILMachineFunctionInfo::usesHWConstant(std::string name) const
223 {
224 const AMDILConstPtr *curConst = getConstPtr(mKernel, name);
225 if (curConst) {
226 return curConst->usesHardware;
227 } else {
228 return false;
229 }
230 }
231
232 uint32_t
233 AMDILMachineFunctionInfo::getLocal(uint32_t dim)
234 {
235 if (mKernel && mKernel->sgv) {
236 AMDILKernelAttr *sgv = mKernel->sgv;
237 switch (dim) {
238 default: break;
239 case 0:
240 case 1:
241 case 2:
242 return sgv->reqGroupSize[dim];
243 break;
244 case 3:
245 return sgv->reqGroupSize[0] * sgv->reqGroupSize[1] * sgv->reqGroupSize[2];
246 };
247 }
248 switch (dim) {
249 default:
250 return 1;
251 case 3:
252 return mSTM->getDefaultSize(0) *
253 mSTM->getDefaultSize(1) *
254 mSTM->getDefaultSize(2);
255 case 2:
256 case 1:
257 case 0:
258 return mSTM->getDefaultSize(dim);
259 break;
260 };
261 return 1;
262 }
263 bool
264 AMDILMachineFunctionInfo::isKernel() const
265 {
266 return mKernel != NULL && mKernel->mKernel;
267 }
268
269 AMDILKernel*
270 AMDILMachineFunctionInfo::getKernel()
271 {
272 return mKernel;
273 }
274
275 std::string
276 AMDILMachineFunctionInfo::getName()
277 {
278 if (mMF) {
279 return mMF->getFunction()->getName();
280 } else {
281 return "";
282 }
283 }
284
285 uint32_t
286 AMDILMachineFunctionInfo::getArgSize()
287 {
288 if (mArgSize == -1) {
289 Function::const_arg_iterator I = mMF->getFunction()->arg_begin();
290 Function::const_arg_iterator Ie = mMF->getFunction()->arg_end();
291 uint32_t Counter = 0;
292 while (I != Ie) {
293 Type* curType = I->getType();
294 if (curType->isIntegerTy() || curType->isFloatingPointTy()) {
295 ++Counter;
296 } else if (const VectorType *VT = dyn_cast<VectorType>(curType)) {
297 Type *ET = VT->getElementType();
298 int numEle = VT->getNumElements();
299 switch (ET->getPrimitiveSizeInBits()) {
300 default:
301 if (numEle == 3) {
302 Counter++;
303 } else {
304 Counter += ((numEle + 2) >> 2);
305 }
306 break;
307 case 64:
308 if (numEle == 3) {
309 Counter += 2;
310 } else {
311 Counter += (numEle >> 1);
312 }
313 break;
314 case 16:
315 case 8:
316 switch (numEle) {
317 default:
318 Counter += ((numEle + 2) >> 2);
319 case 2:
320 Counter++;
321 break;
322 }
323 break;
324 }
325 } else if (const PointerType *PT = dyn_cast<PointerType>(curType)) {
326 Type *CT = PT->getElementType();
327 const StructType *ST = dyn_cast<StructType>(CT);
328 if (ST && ST->isOpaque()) {
329 bool i1d = ST->getName() == "struct._image1d_t";
330 bool i1da = ST->getName() == "struct._image1d_array_t";
331 bool i1db = ST->getName() == "struct._image1d_buffer_t";
332 bool i2d = ST->getName() == "struct._image2d_t";
333 bool i2da = ST->getName() == "struct._image2d_array_t";
334 bool i3d = ST->getName() == "struct._image3d_t";
335 bool is_image = i1d || i1da || i1db || i2d || i2da || i3d;
336 if (is_image) {
337 if (mSTM->device()->isSupported(AMDILDeviceInfo::Images)) {
338 Counter += 2;
339 } else {
340 addErrorMsg(amd::CompilerErrorMessage[NO_IMAGE_SUPPORT]);
341 }
342 } else {
343 Counter++;
344 }
345 } else if (CT->isStructTy()
346 && PT->getAddressSpace() == AMDILAS::PRIVATE_ADDRESS) {
347 StructType *ST = dyn_cast<StructType>(CT);
348 Counter += ((getTypeSize(ST) + 15) & ~15) >> 4;
349 } else if (CT->isIntOrIntVectorTy()
350 || CT->isFPOrFPVectorTy()
351 || CT->isArrayTy()
352 || CT->isPointerTy()
353 || PT->getAddressSpace() != AMDILAS::PRIVATE_ADDRESS) {
354 ++Counter;
355 } else {
356 assert(0 && "Current type is not supported!");
357 addErrorMsg(amd::CompilerErrorMessage[INTERNAL_ERROR]);
358 }
359 } else {
360 assert(0 && "Current type is not supported!");
361 addErrorMsg(amd::CompilerErrorMessage[INTERNAL_ERROR]);
362 }
363 ++I;
364 }
365 // Convert from slots to bytes by multiplying by 16(shift by 4).
366 mArgSize = Counter << 4;
367 }
368 return (uint32_t)mArgSize;
369 }
370 uint32_t
371 AMDILMachineFunctionInfo::getScratchSize()
372 {
373 if (mScratchSize == -1) {
374 mScratchSize = 0;
375 Function::const_arg_iterator I = mMF->getFunction()->arg_begin();
376 Function::const_arg_iterator Ie = mMF->getFunction()->arg_end();
377 while (I != Ie) {
378 Type *curType = I->getType();
379 mScratchSize += ((getTypeSize(curType) + 15) & ~15);
380 ++I;
381 }
382 mScratchSize += ((mScratchSize + 15) & ~15);
383 }
384 return (uint32_t)mScratchSize;
385 }
386
387 uint32_t
388 AMDILMachineFunctionInfo::getStackSize()
389 {
390 if (mStackSize == -1) {
391 uint32_t privSize = 0;
392 const MachineFrameInfo *MFI = mMF->getFrameInfo();
393 privSize = MFI->getOffsetAdjustment() + MFI->getStackSize();
394 const AMDILTargetMachine *TM =
395 reinterpret_cast<const AMDILTargetMachine*>(&mMF->getTarget());
396 bool addStackSize = TM->getOptLevel() == CodeGenOpt::None;
397 Function::const_arg_iterator I = mMF->getFunction()->arg_begin();
398 Function::const_arg_iterator Ie = mMF->getFunction()->arg_end();
399 while (I != Ie) {
400 Type *curType = I->getType();
401 ++I;
402 if (dyn_cast<PointerType>(curType)) {
403 Type *CT = dyn_cast<PointerType>(curType)->getElementType();
404 if (CT->isStructTy()
405 && dyn_cast<PointerType>(curType)->getAddressSpace()
406 == AMDILAS::PRIVATE_ADDRESS) {
407 addStackSize = true;
408 }
409 }
410 }
411 if (addStackSize) {
412 privSize += getScratchSize();
413 }
414 mStackSize = privSize;
415 }
416 return (uint32_t)mStackSize;
417
418 }
419
420 uint32_t
421 AMDILMachineFunctionInfo::addi32Literal(uint32_t val, int Opcode) {
422 // Since we have emulated 16/8/1 bit register types with a 32bit real
423 // register, we need to sign extend the constants to 32bits in order for
424 // comparisons against the constants to work correctly, this fixes some issues
425 // we had in conformance failing for saturation.
426 if (Opcode == AMDIL::LOADCONST_i16) {
427 val = (((int32_t)val << 16) >> 16);
428 } else if (Opcode == AMDIL::LOADCONST_i8) {
429 val = (((int32_t)val << 24) >> 24);
430 }
431 if (mIntLits.find(val) == mIntLits.end()) {
432 mIntLits[val] = getNumLiterals();
433 }
434 return mIntLits[val];
435 }
436
437 uint32_t
438 AMDILMachineFunctionInfo::addi64Literal(uint64_t val) {
439 if (mLongLits.find(val) == mLongLits.end()) {
440 mLongLits[val] = getNumLiterals();
441 }
442 return mLongLits[val];
443 }
444
445 uint32_t
446 AMDILMachineFunctionInfo::addi128Literal(uint64_t val_lo, uint64_t val_hi) {
447 std::pair<uint64_t, uint64_t> a;
448 a.first = val_lo;
449 a.second = val_hi;
450 if (mVecLits.find(a) == mVecLits.end()) {
451 mVecLits[a] = getNumLiterals();
452 }
453 return mVecLits[a];
454 }
455
456 uint32_t
457 AMDILMachineFunctionInfo::addf32Literal(const ConstantFP *CFP) {
458 uint32_t val = (uint32_t)CFP->getValueAPF().bitcastToAPInt().getZExtValue();
459 if (mIntLits.find(val) == mIntLits.end()) {
460 mIntLits[val] = getNumLiterals();
461 }
462 return mIntLits[val];
463 }
464
465 uint32_t
466 AMDILMachineFunctionInfo::addf64Literal(const ConstantFP *CFP) {
467 union dtol_union {
468 double d;
469 uint64_t ul;
470 } dval;
471 const APFloat &APF = CFP->getValueAPF();
472 if (&APF.getSemantics() == (const llvm::fltSemantics *)&APFloat::IEEEsingle) {
473 float fval = APF.convertToFloat();
474 dval.d = (double)fval;
475 } else {
476 dval.d = APF.convertToDouble();
477 }
478 if (mLongLits.find(dval.ul) == mLongLits.end()) {
479 mLongLits[dval.ul] = getNumLiterals();
480 }
481 return mLongLits[dval.ul];
482 }
483
484 uint32_t
485 AMDILMachineFunctionInfo::getIntLits(uint32_t offset)
486 {
487 return mIntLits[offset];
488 }
489
490 uint32_t
491 AMDILMachineFunctionInfo::getLongLits(uint64_t offset)
492 {
493 return mLongLits[offset];
494 }
495
496 uint32_t
497 AMDILMachineFunctionInfo::getVecLits(uint64_t low64, uint64_t high64)
498 {
499 return mVecLits[std::pair<uint64_t, uint64_t>(low64, high64)];
500 }
501
502 size_t
503 AMDILMachineFunctionInfo::getNumLiterals() const {
504 return mLongLits.size() + mIntLits.size() + mVecLits.size() + mReservedLits;
505 }
506
507 void
508 AMDILMachineFunctionInfo::addReservedLiterals(uint32_t size)
509 {
510 mReservedLits += size;
511 }
512
513 uint32_t
514 AMDILMachineFunctionInfo::addSampler(std::string name, uint32_t val)
515 {
516 if (mSamplerMap.find(name) != mSamplerMap.end()) {
517 SamplerInfo newVal = mSamplerMap[name];
518 assert(newVal.val == val
519 && "Found a sampler with same name but different values!");
520 return mSamplerMap[name].idx;
521 } else {
522 SamplerInfo curVal;
523 curVal.name = name;
524 curVal.val = val;
525 curVal.idx = mSamplerMap.size();
526 mSamplerMap[name] = curVal;
527 return curVal.idx;
528 }
529 }
530
531 void
532 AMDILMachineFunctionInfo::setUsesMem(unsigned id) {
533 assert(id < AMDILDevice::MAX_IDS &&
534 "Must set the ID to be less than MAX_IDS!");
535 mUsedMem[id] = true;
536 }
537
538 bool
539 AMDILMachineFunctionInfo::usesMem(unsigned id) {
540 assert(id < AMDILDevice::MAX_IDS &&
541 "Must set the ID to be less than MAX_IDS!");
542 return mUsedMem[id];
543 }
544
545 void
546 AMDILMachineFunctionInfo::addErrorMsg(const char *msg, ErrorMsgEnum val)
547 {
548 if (val == DEBUG_ONLY) {
549 #if defined(DEBUG) || defined(_DEBUG)
550 mErrors.insert(msg);
551 #endif
552 } else if (val == RELEASE_ONLY) {
553 #if !defined(DEBUG) && !defined(_DEBUG)
554 mErrors.insert(msg);
555 #endif
556 } else if (val == ALWAYS) {
557 mErrors.insert(msg);
558 }
559 }
560
561 uint32_t
562 AMDILMachineFunctionInfo::addPrintfString(std::string &name, unsigned offset)
563 {
564 if (mPrintfMap.find(name) != mPrintfMap.end()) {
565 return mPrintfMap[name]->getPrintfID();
566 } else {
567 PrintfInfo *info = new PrintfInfo;
568 info->setPrintfID(mPrintfMap.size() + offset);
569 mPrintfMap[name] = info;
570 return info->getPrintfID();
571 }
572 }
573
574 void
575 AMDILMachineFunctionInfo::addPrintfOperand(std::string &name,
576 size_t idx,
577 uint32_t size)
578 {
579 mPrintfMap[name]->addOperand(idx, size);
580 }
581
582 void
583 AMDILMachineFunctionInfo::addMetadata(const char *md, bool kernelOnly)
584 {
585 addMetadata(std::string(md), kernelOnly);
586 }
587
588 void
589 AMDILMachineFunctionInfo::addMetadata(std::string md, bool kernelOnly)
590 {
591 if (kernelOnly) {
592 mMetadataKernel.push_back(md);
593 } else {
594 mMetadataFunc.insert(md);
595 }
596 }
597