1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
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:
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
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
25 * @brief JitManager contains the LLVM data structures used for JIT generation
29 ******************************************************************************/
32 #include "jit_pch.hpp"
33 #include "common/isa.hpp"
34 #include <llvm/IR/AssemblyAnnotationWriter.h>
37 //////////////////////////////////////////////////////////////////////////
39 /// @brief Subclass of InstructionSet that allows users to override
40 /// the reporting of support for certain ISA features. This allows capping
41 /// the jitted code to a certain feature level, e.g. jit AVX level code on
42 /// a platform that supports AVX2.
43 //////////////////////////////////////////////////////////////////////////
44 class JitInstructionSet
: public InstructionSet
47 JitInstructionSet(const char* requestedIsa
) : isaRequest(requestedIsa
)
49 std::transform(isaRequest
.begin(), isaRequest
.end(), isaRequest
.begin(), ::tolower
);
51 if (isaRequest
== "avx")
57 else if (isaRequest
== "avx2")
63 else if (isaRequest
== "avx512")
71 bool AVX2(void) { return bForceAVX
? 0 : InstructionSet::AVX2(); }
72 bool AVX512F(void) { return (bForceAVX
| bForceAVX2
) ? 0 : InstructionSet::AVX512F(); }
73 bool AVX512ER(void) { return (bForceAVX
| bForceAVX2
) ? 0 : InstructionSet::AVX512ER(); }
74 bool BMI2(void) { return bForceAVX
? 0 : InstructionSet::BMI2(); }
77 bool bForceAVX
= false;
78 bool bForceAVX2
= false;
79 bool bForceAVX512
= false;
80 std::string isaRequest
;
83 struct JitLLVMContext
: llvm::LLVMContext
87 //////////////////////////////////////////////////////////////////////////
89 //////////////////////////////////////////////////////////////////////////
90 struct JitManager
; // Forward Decl
91 class JitCache
: public llvm::ObjectCache
96 virtual ~JitCache() {}
98 void Init(JitManager
* pJitMgr
, const llvm::StringRef
& cpu
, llvm::CodeGenOpt::Level level
)
105 /// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
106 void notifyObjectCompiled(const llvm::Module
* M
, llvm::MemoryBufferRef Obj
) override
;
108 /// Returns a pointer to a newly allocated MemoryBuffer that contains the
109 /// object which corresponds with Module M, or 0 if an object is not
111 std::unique_ptr
<llvm::MemoryBuffer
> getObject(const llvm::Module
* M
) override
;
115 llvm::SmallString
<MAX_PATH
> mCacheDir
;
116 llvm::SmallString
<MAX_PATH
> mModuleCacheDir
;
117 uint32_t mCurrentModuleCRC
= 0;
118 JitManager
* mpJitMgr
= nullptr;
119 llvm::CodeGenOpt::Level mOptLevel
= llvm::CodeGenOpt::None
;
121 /// Calculate actual directory where module will be cached.
122 /// This is always a subdirectory of mCacheDir. Full absolute
123 /// path name will be stored in mCurrentModuleCacheDir
124 void CalcModuleCacheDir();
127 //////////////////////////////////////////////////////////////////////////
129 //////////////////////////////////////////////////////////////////////////
132 JitManager(uint32_t w
, const char* arch
, const char* core
);
135 for (auto* pExec
: mvExecEngines
)
141 JitLLVMContext mContext
; ///< LLVM compiler
142 llvm::IRBuilder
<> mBuilder
; ///< LLVM IR Builder
143 llvm::ExecutionEngine
* mpExec
;
144 std::vector
<llvm::ExecutionEngine
*> mvExecEngines
;
146 llvm::StringRef mHostCpuName
;
147 llvm::CodeGenOpt::Level mOptLevel
;
149 // Need to be rebuilt after a JIT and before building new IR
150 llvm::Module
* mpCurrentModule
;
151 bool mIsModuleFinalized
;
156 bool mUsingAVX512
= false;
158 // fetch shader types
159 llvm::FunctionType
* mFetchShaderTy
;
161 JitInstructionSet mArch
;
164 std::unordered_map
<llvm::StructType
*, llvm::DIType
*> mDebugStructMap
;
166 void CreateExecEngine(std::unique_ptr
<llvm::Module
> M
);
167 void SetupNewModule();
169 void DumpAsm(llvm::Function
* pFunction
, const char* fileName
);
170 static void DumpToFile(llvm::Function
* f
, const char* fileName
);
171 static void DumpToFile(llvm::Module
* M
,
172 const char* fileName
,
173 llvm::AssemblyAnnotationWriter
* annotater
= nullptr);
174 static std::string
GetOutputDir();
176 // Debugging support methods
177 llvm::DIType
* GetDebugType(llvm::Type
* pTy
);
178 llvm::DIType
* GetDebugIntegerType(llvm::Type
* pTy
);
179 llvm::DIType
* GetDebugArrayType(llvm::Type
* pTy
);
180 llvm::DIType
* GetDebugVectorType(llvm::Type
* pTy
);
181 llvm::DIType
* GetDebugFunctionType(llvm::Type
* pTy
);
183 llvm::DIType
* GetDebugStructType(llvm::Type
* pType
)
185 llvm::StructType
* pStructTy
= llvm::cast
<llvm::StructType
>(pType
);
186 if (mDebugStructMap
.find(pStructTy
) == mDebugStructMap
.end())
190 return mDebugStructMap
[pStructTy
];
194 CreateDebugStructType(llvm::StructType
* pType
,
195 const std::string
& name
,
198 const std::vector
<std::pair
<std::string
, uint32_t>>& members
);
201 class InterleaveAssemblyAnnotater
: public llvm::AssemblyAnnotationWriter
204 void emitInstructionAnnot(const llvm::Instruction
* pInst
,
205 llvm::formatted_raw_ostream
& OS
) override
;
206 std::vector
<std::string
> mAssembly
;
209 uint32_t mCurrentLineNo
= 0;