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