• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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