1 /**************************************************************************** 2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * @file JitManager.h 24 * 25 * @brief JitManager contains the LLVM data structures used for JIT generation 26 * 27 * Notes: 28 * 29 ******************************************************************************/ 30 #pragma once 31 32 #include "jit_pch.hpp" 33 #include "common/isa.hpp" 34 35 36 ////////////////////////////////////////////////////////////////////////// 37 /// JitInstructionSet 38 /// @brief Subclass of InstructionSet that allows users to override 39 /// the reporting of support for certain ISA features. This allows capping 40 /// the jitted code to a certain feature level, e.g. jit AVX level code on 41 /// a platform that supports AVX2. 42 ////////////////////////////////////////////////////////////////////////// 43 class JitInstructionSet : public InstructionSet 44 { 45 public: JitInstructionSet(const char * requestedIsa)46 JitInstructionSet(const char* requestedIsa) : isaRequest(requestedIsa) 47 { 48 std::transform(isaRequest.begin(), isaRequest.end(), isaRequest.begin(), ::tolower); 49 50 if(isaRequest == "avx") 51 { 52 bForceAVX = true; 53 bForceAVX2 = false; 54 bForceAVX512 = false; 55 } 56 else if(isaRequest == "avx2") 57 { 58 bForceAVX = false; 59 bForceAVX2 = true; 60 bForceAVX512 = false; 61 } 62 else if(isaRequest == "avx512") 63 { 64 bForceAVX = false; 65 bForceAVX2 = false; 66 bForceAVX512 = true; 67 } 68 }; 69 AVX2(void)70 bool AVX2(void) { return bForceAVX ? 0 : InstructionSet::AVX2(); } AVX512F(void)71 bool AVX512F(void) { return (bForceAVX | bForceAVX2) ? 0 : InstructionSet::AVX512F(); } BMI2(void)72 bool BMI2(void) { return bForceAVX ? 0 : InstructionSet::BMI2(); } 73 74 private: 75 bool bForceAVX = false; 76 bool bForceAVX2 = false; 77 bool bForceAVX512 = false; 78 std::string isaRequest; 79 }; 80 81 82 83 struct JitLLVMContext : llvm::LLVMContext 84 { 85 }; 86 87 88 ////////////////////////////////////////////////////////////////////////// 89 /// JitCache 90 ////////////////////////////////////////////////////////////////////////// 91 struct JitManager; // Forward Decl 92 class JitCache : public llvm::ObjectCache 93 { 94 public: 95 /// constructor 96 JitCache(); ~JitCache()97 virtual ~JitCache() {} 98 Init(JitManager * pJitMgr,const llvm::StringRef & cpu,llvm::CodeGenOpt::Level level)99 void Init( 100 JitManager* pJitMgr, 101 const llvm::StringRef& cpu, 102 llvm::CodeGenOpt::Level level) 103 { 104 mCpu = cpu.str(); 105 mpJitMgr = pJitMgr; 106 mOptLevel = level; 107 } 108 109 /// notifyObjectCompiled - Provides a pointer to compiled code for Module M. 110 virtual void notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj); 111 112 /// Returns a pointer to a newly allocated MemoryBuffer that contains the 113 /// object which corresponds with Module M, or 0 if an object is not 114 /// available. 115 virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M); 116 117 private: 118 std::string mCpu; 119 llvm::SmallString<MAX_PATH> mCacheDir; 120 uint32_t mCurrentModuleCRC = 0; 121 JitManager* mpJitMgr = nullptr; 122 llvm::CodeGenOpt::Level mOptLevel = llvm::CodeGenOpt::None; 123 }; 124 125 ////////////////////////////////////////////////////////////////////////// 126 /// JitManager 127 ////////////////////////////////////////////////////////////////////////// 128 struct JitManager 129 { 130 JitManager(uint32_t w, const char* arch, const char* core); ~JitManagerJitManager131 ~JitManager(){}; 132 133 JitLLVMContext mContext; ///< LLVM compiler 134 llvm::IRBuilder<> mBuilder; ///< LLVM IR Builder 135 llvm::ExecutionEngine* mpExec; 136 JitCache mCache; 137 138 // Need to be rebuilt after a JIT and before building new IR 139 llvm::Module* mpCurrentModule; 140 bool mIsModuleFinalized; 141 uint32_t mJitNumber; 142 143 uint32_t mVWidth; 144 145 146 // Built in types. 147 llvm::Type* mInt8Ty; 148 llvm::Type* mInt32Ty; 149 llvm::Type* mInt64Ty; 150 llvm::Type* mFP32Ty; 151 152 llvm::Type* mSimtFP32Ty; 153 llvm::Type* mSimtInt32Ty; 154 155 llvm::Type* mSimdVectorInt32Ty; 156 llvm::Type* mSimdVectorTy; 157 158 #if USE_SIMD16_SHADERS 159 llvm::Type* mSimd16FP32Ty; 160 llvm::Type* mSimd16Int32Ty; 161 162 llvm::Type* mSimd16VectorFP32Ty; 163 llvm::Type* mSimd16VectorInt32Ty; 164 165 #endif 166 // fetch shader types 167 llvm::FunctionType* mFetchShaderTy; 168 169 JitInstructionSet mArch; 170 std::string mCore; 171 172 // Debugging support 173 std::unordered_map<llvm::StructType*, llvm::DIType*> mDebugStructMap; 174 175 void SetupNewModule(); 176 177 void DumpAsm(llvm::Function* pFunction, const char* fileName); 178 static void DumpToFile(llvm::Function *f, const char *fileName); 179 static void DumpToFile(llvm::Module *M, const char *fileName); 180 static std::string GetOutputDir(); 181 182 // Debugging support methods 183 llvm::DIType* GetDebugType(llvm::Type* pTy); 184 llvm::DIType* GetDebugIntegerType(llvm::Type* pTy); 185 llvm::DIType* GetDebugArrayType(llvm::Type* pTy); 186 llvm::DIType* GetDebugVectorType(llvm::Type* pTy); 187 llvm::DIType* GetDebugFunctionType(llvm::Type* pTy); 188 GetDebugStructTypeJitManager189 llvm::DIType* GetDebugStructType(llvm::Type* pType) 190 { 191 llvm::StructType* pStructTy = llvm::cast<llvm::StructType>(pType); 192 if (mDebugStructMap.find(pStructTy) == mDebugStructMap.end()) 193 { 194 return nullptr; 195 } 196 return mDebugStructMap[pStructTy]; 197 } 198 199 llvm::DIType* CreateDebugStructType(llvm::StructType* pType, const std::string& name, llvm::DIFile* pFile, uint32_t lineNum, 200 const std::vector<std::pair<std::string, uint32_t>>& members); 201 }; 202