1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #pragma once
10 
11 #include "llvm/Config/llvm-config.h"
12 #include "common/LLVMWarningsPush.hpp"
13 #include "llvm/Support/DataTypes.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/ADT/APInt.h"
16 #include "llvm/Support/Debug.h"
17 #include "common/LLVMWarningsPop.hpp"
18 
19 #include "VISAIDebugEmitter.hpp"
20 #include "LexicalScopes.hpp"
21 
22 #include <vector>
23 #include <map>
24 #include <string>
25 
26 #include "Probe/Assertion.h"
27 
28 namespace llvm
29 {
30     class Module;
31     class Function;
32     class Instruction;
33     class LLVMContext;
34     class DISubprogram;
35 
36     class Value;
37     class Argument;
38     class Constant;
39     class MDNode;
40 }
41 
42 namespace IGC
43 {
44     class VISAModule;
45     class DwarfDebug;
46 
47     /// @brief VISAVariableLocation holds information on the source variable
48     ///        location with respect to the VISA virtual machine.
49     ///        Also holds attribute to state whether the variable was
50     ///        vectorized or is uniform.
51     struct VISAVariableLocation
52     {
53     public:
54         /// @brief Default Constructor. Creates empty location.
VISAVariableLocationIGC::VISAVariableLocation55         VISAVariableLocation(const VISAModule* m)
56         {
57             m_pVISAModule = m;
58         }
59 
60         /// @brief Constructor. Creates constant value location.
61         /// @param pConstVal constant value.
62         /// @param m points to VISAModule corresponding to this location
VISAVariableLocationIGC::VISAVariableLocation63         VISAVariableLocation(const llvm::Constant* pConstVal, const VISAModule* m)
64         {
65             m_isImmediate = true;
66             m_pConstVal = pConstVal;
67             m_pVISAModule = m;
68         }
69 
70         /// @brief Constructor. Creates surface entry location.
71         /// @param surfaceReg register number that indicates the surface entry.
72         /// @param m points to VISAModule corresponding to this location
VISAVariableLocationIGC::VISAVariableLocation73         VISAVariableLocation(unsigned int surfaceReg, const VISAModule* m)
74         {
75             m_hasSurface = true;
76             m_surfaceReg = surfaceReg;
77             m_pVISAModule = m;
78         }
79 
80         /// @brief Constructor. Creates surface entry + offset location.
81         /// @param surfaceReg register number that indicates the surface entry.
82         /// @param locationValue value indicates the offset of the location.
83         /// @param isRegister true if offset value is a register, false if it is immediate.
84         /// @param isInMemory true if location is stored in memory, false otherwise.
85         /// @param isVectorized true if the underlying virtual variable has been vectorized during codegen.
86         /// @param m points to VISAModule corresponding to this location
VISAVariableLocationIGC::VISAVariableLocation87         VISAVariableLocation(unsigned int surfaceReg, unsigned int locationValue, bool isRegister,
88             bool isInMemory, unsigned int vectorNumElements, bool isVectorized, const VISAModule* m)
89         {
90             m_hasSurface = true;
91             m_surfaceReg = surfaceReg;
92             m_hasLocation = true;
93             m_isInMemory = isInMemory;
94             m_isRegister = isRegister;
95             m_locationReg = isRegister ? locationValue : 0;
96             m_locationOffset = isRegister ? 0 : locationValue;
97             m_isVectorized = isVectorized;
98             m_vectorNumElements = isVectorized ? vectorNumElements : 0;
99             m_pVISAModule = m;
100         }
101 
102         /// @brief Constructor. Creates address/register location.
103         /// @param locationValue value indicates the address/register of the location.
104         /// @param isRegister true if offset value is a register, false if it is immediate.
105         /// @param isInMemory true if location is stored in memory, false otherwise.
106         /// @param isVectorized true if the underlying virtual variable has been vectorized during codegen.
107         /// @param isGlobalAddrSpace true if variable represents a src var belonging to global address space.
108         /// @param m points to VISAModule corresponding to this location
VISAVariableLocationIGC::VISAVariableLocation109         VISAVariableLocation(unsigned int locationValue, bool isRegister, bool isInMemory,
110              unsigned int vectorNumElements, bool isVectorized, bool isGlobalAddrSpace, const VISAModule* m)
111         {
112             m_hasLocation = true;
113             m_isInMemory = isInMemory;
114             m_isRegister = isRegister;
115             m_locationReg = isRegister ? locationValue : 0;
116             m_locationOffset = isRegister ? 0 : locationValue;
117             m_isVectorized = isVectorized;
118             m_vectorNumElements = isVectorized ? vectorNumElements : 0;
119             m_isGlobalAddrSpace = isGlobalAddrSpace;
120             m_pVISAModule = m;
121         }
122 
123         // Getter methods
IsImmediateIGC::VISAVariableLocation124         bool IsImmediate() const { return m_isImmediate; }
HasSurfaceIGC::VISAVariableLocation125         bool HasSurface() const { return m_hasSurface; }
HasLocationIGC::VISAVariableLocation126         bool HasLocation() const { return m_hasLocation; }
IsInMemoryIGC::VISAVariableLocation127         bool IsInMemory() const { return m_isInMemory; }
IsRegisterIGC::VISAVariableLocation128         bool IsRegister() const { return m_isRegister; }
IsVectorizedIGC::VISAVariableLocation129         bool IsVectorized() const { return m_isVectorized; }
IsInGlobalAddrSpaceIGC::VISAVariableLocation130         bool IsInGlobalAddrSpace() const { return m_isGlobalAddrSpace; }
131 
GetImmediateIGC::VISAVariableLocation132         const llvm::Constant* GetImmediate() { return m_pConstVal; }
GetSurfaceIGC::VISAVariableLocation133         unsigned int GetSurface() const { return m_surfaceReg; }
GetRegisterIGC::VISAVariableLocation134         unsigned int GetRegister() const { return m_locationReg; }
GetOffsetIGC::VISAVariableLocation135         unsigned int GetOffset() const { return m_locationOffset; }
GetVectorNumElementsIGC::VISAVariableLocation136         unsigned int GetVectorNumElements() const { return m_vectorNumElements; }
GetVISAModuleIGC::VISAVariableLocation137         const VISAModule* GetVISAModule() const { return m_pVISAModule; }
138 
139         bool IsSampler() const;
140         bool IsTexture() const;
141         bool IsSLM() const;
142 
143         void dump() const;
144         void print (llvm::raw_ostream &OS) const;
145 
146         static void print(llvm::raw_ostream &OS,
147                           const std::vector<VISAVariableLocation> &Locs);
148     private:
149 
150         bool m_isImmediate = false;
151         bool m_hasSurface = false;
152         bool m_hasLocation = false;
153         bool m_isInMemory = false;
154         bool m_isRegister = false;
155         bool m_isVectorized = false;
156         bool m_isGlobalAddrSpace = false;
157 
158         const llvm::Constant* m_pConstVal = nullptr;
159         unsigned int m_surfaceReg = ~0;
160         unsigned int m_locationReg = ~0;
161         unsigned int m_locationOffset = ~0;
162         unsigned int m_vectorNumElements = ~0;
163         const VISAModule* m_pVISAModule = nullptr;
164     };
165 
166     typedef uint64_t GfxAddress;
167 
168     /*
169     * Encoder/decoder for manipulating 64-bit GFX addresses.
170     *
171     *  63            56 55                   48  47            0
172     *  ---------------------------------------------------------
173     * | Address Space  |   Index (BTI/Sampler)  |    Offset     |
174     *  ---------------------------------------------------------
175     *
176     *  Upper      8 bits represent the address space (flat, sampler, surface, etc).
177     *  Following  8 bits represent the index (valid only for surfaces/sampler), and
178     *  Following 48 bits respesent the offset within a memory region.
179     *
180     */
181     class Address
182     {
183     public:
184         enum class Space : GfxAddress
185         {
186             eContextFlat = 0,
187             eContextFlat2 = 255,
188             eSampler = 1,
189             eSurface = 2,
190             eGRF = 3,
191             eSurfaceRelocated = 4,
192             eMMIO = 5,
193             ePhysical = 6,
194             eVirtual = 7,
195             ePCI = 8,
196             eScratch = 9,
197             eLocal = 10
198         };
199 
200     private:
201         static const uint32_t c_space_shift = 56;
202 
203         static const uint32_t c_index_shift = 48;
204         static const uint32_t c_offset_shift = 0;
205 
206         static const uint32_t c_space_size = 8;
207         static const uint32_t c_index_size = 8;
208         static const uint32_t c_offset_size = 64 - c_index_size - c_space_size;
209 
210         static const GfxAddress c_offset_mask = ((1ull << c_offset_size) - 1);
211         static const GfxAddress c_space_mask = ((1ull << c_space_size) - 1);
212         static const GfxAddress c_index_mask = ((1ull << c_index_size) - 1);
213 
214     public:
Address(GfxAddress addr=0)215         Address(GfxAddress addr = 0)
216             : m_addr(addr)
217         {
218         }
219 
220         Space
GetSpace() const221             GetSpace() const
222         {
223             return (Space)((m_addr >> c_space_shift) & c_space_mask);
224         }
225 
226         uint32_t
GetIndex() const227             GetIndex() const
228         {
229             return (uint32_t)((m_addr >> c_index_shift) & c_index_mask);
230         }
231 
232         uint64_t
GetOffset() const233             GetOffset() const
234         {
235             return ((m_addr >> c_offset_shift) & c_offset_mask);
236         }
237 
238         uint64_t
GetAddress() const239             GetAddress() const
240         {
241             return m_addr;
242         }
243 
244         uint64_t
GetCanonicalizedAddress() const245             GetCanonicalizedAddress() const
246         {
247             bool isSignBitSet = ((1ull << 47) & m_addr) != 0;
248 
249             return isSignBitSet ? (~c_offset_mask) | m_addr : c_offset_mask & m_addr;
250         }
251 
252         void
SetSpace(Space space)253             SetSpace(Space space)
254         {
255             GfxAddress s = static_cast<GfxAddress>(space);
256             IGC_ASSERT(s == (s & c_space_mask));
257             m_addr = (m_addr & ~(c_space_mask << c_space_shift)) | ((s & c_space_mask) << c_space_shift);
258         }
259 
260         void
SetIndex(uint32_t index)261             SetIndex(uint32_t index)
262         {
263             IGC_ASSERT(index == (index & c_index_mask));
264             m_addr = (m_addr & ~(c_index_mask << c_index_shift)) | ((index & c_index_mask) << c_index_shift);
265         }
266 
267         void
SetOffset(uint64_t offset)268             SetOffset(uint64_t offset)
269         {
270             IGC_ASSERT(offset == (offset & c_offset_mask));
271             m_addr = (m_addr & ~(c_offset_mask << c_offset_shift)) | ((offset & c_offset_mask) << c_offset_shift);
272         }
273 
274         void
Set(Space space,uint32_t index,uint64_t offset)275             Set(Space space, uint32_t index, uint64_t offset)
276         {
277             SetSpace(space);
278             SetIndex(index);
279             SetOffset(offset);
280         }
281 
282         void
Set(GfxAddress address)283             Set(GfxAddress address)
284         {
285             m_addr = address;
286         }
287 
288     private:
289         uint64_t m_addr;
290     };
291 
292     const unsigned int INVALID_SIZE = (~0);
293 
294     class InstructionInfo
295     {
296     public:
InstructionInfo()297         InstructionInfo() : m_size(INVALID_SIZE), m_offset(0) {}
InstructionInfo(unsigned int size,unsigned int offset)298         InstructionInfo(unsigned int size, unsigned int offset) : m_size(size), m_offset(offset) {}
299         unsigned int m_size;
300         unsigned int m_offset;
301     };
302     typedef std::map<const llvm::Instruction*, InstructionInfo> InstInfoMap;
303 
304     /// @brief VISAModule holds information on LLVM function from which
305     ///     visa function was constructed.
306     /// TODO: rename this class to something like VISAFunction/VISAObject
307     class VISAModule
308     {
309     public:
310         enum class ObjectType
311         {
312             UNKNOWN = 0,
313             KERNEL = 1,
314             STACKCALL_FUNC = 2,
315             SUBROUTINE = 3
316         };
317 
318         using InstList = std::vector<const llvm::Instruction*>;
319         using iterator = InstList::iterator;
320         using const_iterator = InstList::const_iterator;
321 
322         /// Constants represents VISA register encoding in DWARF
323         static constexpr unsigned int LOCAL_SURFACE_BTI = (254);
324         static constexpr unsigned int GENERAL_REGISTER_BEGIN = (0);
325         static constexpr unsigned int GENERAL_REGISTER_NUM = (65536);
326         static constexpr unsigned int SAMPLER_REGISTER_BEGIN = (73728);
327         static constexpr unsigned int SAMPLER_REGISTER_NUM = (16);
328         static constexpr unsigned int TEXTURE_REGISTER_BEGIN = (74744);
329         static constexpr unsigned int TEXTURE_REGISTER_NUM = (255);
330 
331         // Store VISA index->[header VISA index, #VISA instructions] corresponding
332         // to same llvm::Instruction. If llvm inst A generates VISA 3,4,5 then
333         // this structure will have 3 entries:
334         // 3 -> [3,3]
335         // 4 -> [3,3]
336         // 5 -> [3,3]
337         struct VisaInterval {
338             unsigned VisaOffset;
339             unsigned VisaInstrNum;
340         };
341         struct IDX_Gen2Visa {
342             unsigned GenOffset;
343             unsigned VisaOffset;
344         };
345         // Store first VISA index->llvm::Instruction mapping
346         llvm::DenseMap<unsigned, const llvm::Instruction*> VISAIndexToInst;
347         llvm::DenseMap<unsigned, VisaInterval> VISAIndexToSize;
348         llvm::DenseMap<unsigned, unsigned> GenISAInstSizeBytes;
349         llvm::DenseMap<unsigned, std::vector<unsigned>> VISAIndexToAllGenISAOff;
350         std::vector<IDX_Gen2Visa> GenISAToVISAIndex;
351 
352     private:
353         using VarInfoCache =
354             std::unordered_map<unsigned, const DbgDecoder::VarInfo*>;
355 
356         std::string m_triple = "vISA_64";
357         bool IsPrimaryFunc = false;
358         // m_Func points to llvm::Function that resulted in this VISAModule instance.
359         // There is a 1:1 mapping between the two.
360         // Its value is setup in DebugInfo pass, prior to it this is undefined.
361         llvm::Function* m_Func = nullptr;
362         InstList m_instList;
363 
364         unsigned int m_currentVisaId = 0;
365         unsigned int m_catchAllVisaId = 0;
366 
367         InstInfoMap m_instInfoMap;
368 
369         ObjectType m_objectType = ObjectType::UNKNOWN;
370 
371         std::unique_ptr<VarInfoCache> VICache = std::make_unique<VarInfoCache>();
372 
373     public:
374         /// @brief Constructor.
375         /// @param AssociatedFunc holds llvm IR function associated with
376         /// this vISA object
377         /// @param IsPrimary indicates if the associated IR function can be
378         /// classified as a "primary entry point"
379         /// "Primary entry point" is a function that spawns a separate
380         /// gen object (compiled gen isa code). Currently, such functions
381         /// correspond to kernel functions or indirectly called functions.
VISAModule(llvm::Function * AssociatedFunc,bool IsPrimary)382         VISAModule(llvm::Function* AssociatedFunc, bool IsPrimary)
383             : m_Func(AssociatedFunc), IsPrimaryFunc(IsPrimary) {}
384 
~VISAModule()385         virtual ~VISAModule() {}
386 
387         /// @brief true if the underlying function correspond to the
388         /// "primary entry point".
isPrimaryFunc() const389         bool isPrimaryFunc() const { return IsPrimaryFunc; }
390 
391         /// @brief Return first instruction to process.
392         /// @return iterator to first instruction in the entry point function.
begin() const393         const_iterator begin() const { return m_instList.begin(); }
394 
395         /// @brief Return after last instruction to process.
396         /// @return iterator to after last instruction in the entry point function.
end() const397         const_iterator end() const { return m_instList.end(); }
398 
399         /// @brief Process instruction before emitting its VISA code.
400         /// @param Instruction to process.
401         void BeginInstruction(llvm::Instruction*);
402 
403         /// @brief Process instruction after emitting its VISA code.
404         /// @param Instruction to process.
405         void EndInstruction(llvm::Instruction*);
406 
407         /// @brief Mark begin of VISA code emitting section.
408         void BeginEncodingMark();
409 
410         /// @brief Mark end of VISA code emitting section.
411         void EndEncodingMark();
412 
413         /// @brief Return VISA offset (in instructions) mapped to given instruction.
414         /// @param Instruction to query.
415         /// @return VISA offset (in instructions)
416         unsigned int GetVisaOffset(const llvm::Instruction*) const;
417 
418         /// @brief Return VISA code size (in instructions) generated by given instruction.
419         /// @param Instruction to query.
420         /// @return VISA code size (in instructions)
421         unsigned int GetVisaSize(const llvm::Instruction*) const;
422 
423         /// @brief Return LLVM module.
424         /// @return LLVM module.
425         const llvm::Module* GetModule() const;
426 
427         /// @brief Return entry point LLVM function.
428         /// @return LLVM function.
429         const llvm::Function* GetEntryFunction() const;
430 
431         /// @brief Return LLVM context.
432         /// @return LLVM context.
433         const llvm::LLVMContext& GetContext() const;
434 
435         /// @brief Return data layout string.
436         /// @return data layout string.
437         const std::string GetDataLayout() const;
438 
439         /// @brief Return target triple string.
440         /// @return target triple string.
441         const std::string& GetTargetTriple() const;
442 
443         /// @brief Return variable location in VISA for from given debug info instruction.
444         /// Return type is a vector since for SIMD32 a single src variable may map to 2
445         /// VISA variables. In case of SIMD32, each entry is treated to be one half of SIMD16.
446         /// @param Instruction to query.
447         /// @return variable location in VISA.
448         virtual std::vector<VISAVariableLocation>
449             GetVariableLocation(const llvm::Instruction* pInst) const = 0;
450 
451         /// @brief Updates VISA instruction id to current instruction number.
452         virtual void UpdateVisaId() = 0;
453 
454         /// @brief Validate that VISA instruction id is updated to current instruction number.
455         virtual void ValidateVisaId() = 0;
456 
457         /// @brief Return SIMD size of kernel
458         virtual uint16_t GetSIMDSize() const = 0;
459 
460         /// @brief Return whether llvm instruction is the catch all intrinsic
IsCatchAllIntrinsic(const llvm::Instruction * pInst) const461         virtual bool IsCatchAllIntrinsic(const llvm::Instruction* pInst) const
462         {
463             return false;
464         }
465 
466         ///  @brief return false if inst is a placeholder instruction
467         bool IsExecutableInst(const llvm::Instruction& inst);
468         const DbgDecoder::VarInfo* getVarInfo(const IGC::DbgDecoder& VD, unsigned int vreg) const;
469 
470         bool hasOrIsStackCall(const IGC::DbgDecoder& VD) const;
471         const std::vector<DbgDecoder::SubroutineInfo>* getSubroutines(const IGC::DbgDecoder& VD) const;
472 
473         void buildDirectElfMaps(const IGC::DbgDecoder& VD);
474 
475         std::vector<std::pair<unsigned int, unsigned int>> getGenISARange(const InsnRange& Range);
476 
477         // Given %ip range and variable location, returns vector of locations where variable is
478         // available in memory due to caller save sequence.
479         // Return format is:
480         // <start %ip of caller save, end %ip of caller save, stack slot offset for caller save>
481         std::vector<std::tuple<uint64_t, uint64_t, unsigned int>> getAllCallerSave(
482             const IGC::DbgDecoder& VD, uint64_t startRange, uint64_t endRange,
483             DbgDecoder::LiveIntervalsVISA& Locs);
484 
485         virtual const DbgDecoder::DbgInfoFormat*
486             getCompileUnit(const IGC::DbgDecoder& VD) const;
487 
488         virtual unsigned getUnpaddedProgramSize() const = 0;
489         virtual bool isLineTableOnly() const = 0;
490         virtual unsigned getPrivateBaseReg() const = 0;
getGRFSizeInBits() const491         unsigned getGRFSizeInBits() const { return getGRFSizeInBytes() * 8; }
492         virtual unsigned getGRFSizeInBytes() const = 0;
493         virtual unsigned getNumGRFs() const = 0;
494         // TODO: deprecate usage of this method, since it does not respect ASI
495         virtual unsigned getPointerSize() const = 0;
496         virtual uint64_t getTypeSizeInBits(llvm::Type*) const = 0;
497 
498         virtual void* getPrivateBase() const = 0;
499         virtual void setPrivateBase(void*) = 0;
500         virtual bool hasPTO() const = 0;
501         virtual int getPTOReg() const = 0;
502         virtual int getFPReg() const = 0;
503         virtual uint64_t getFPOffset() const = 0;
504 
505         virtual llvm::ArrayRef<char> getGenDebug() const = 0;
506         virtual llvm::ArrayRef<char> getGenBinary() const = 0;
507 
IsIntelSymbolTableVoidProgram() const508         virtual bool IsIntelSymbolTableVoidProgram() const { return false; }
509 
GetVISAFuncName(llvm::StringRef OldName) const510         virtual llvm::StringRef GetVISAFuncName(llvm::StringRef OldName) const { return OldName; }
511 
GetInstInfoMap()512         const InstInfoMap* GetInstInfoMap() { return &m_instInfoMap; }
513 
514         VISAModule& operator=(VISAModule& other) = delete;
515 
GetCurrentVISAId()516         unsigned int GetCurrentVISAId() { return m_currentVisaId; }
SetVISAId(unsigned ID)517         void SetVISAId(unsigned ID) { m_currentVisaId = ID; }
518 
GetType() const519         ObjectType GetType() const { return m_objectType; }
SetType(ObjectType t)520         void SetType(ObjectType t) { m_objectType = t; }
521 
522         // This function coalesces GenISARange which is a vector of <start ip, end ip>
523         static void coalesceRanges(std::vector<std::pair<unsigned int, unsigned int>>& GenISARange);
524 
getFunction() const525         llvm::Function* getFunction() const  { return m_Func; }
GetFuncId() const526         uint64_t GetFuncId() const { return (uint64_t)m_Func; }
527 
dump() const528         void dump() const { print(llvm::dbgs()); }
529         void print (llvm::raw_ostream &OS) const;
530     };
531 } // namespace IGC
532