swr/rast: Implement JIT shader caching to disk
[mesa.git] / src / gallium / drivers / swr / rasterizer / jitter / JitManager.h
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 #if defined(_WIN32)
33 #pragma warning(disable : 4146 4244 4267 4800 4996)
34 #endif
35
36 // llvm 3.7+ reuses "DEBUG" as an enum value
37 #pragma push_macro("DEBUG")
38 #undef DEBUG
39
40 #include "llvm/IR/DataLayout.h"
41 #include "llvm/IR/Instructions.h"
42 #include "llvm/IR/LLVMContext.h"
43 #include "llvm/IR/Module.h"
44 #include "llvm/IR/Type.h"
45 #include "llvm/IR/IRBuilder.h"
46 #include "llvm/IR/IntrinsicInst.h"
47 #include "llvm/ExecutionEngine/ObjectCache.h"
48
49 #include "llvm/Config/llvm-config.h"
50 #ifndef LLVM_VERSION_MAJOR
51 #include "llvm/Config/config.h"
52 #endif
53
54 #ifndef HAVE_LLVM
55 #define HAVE_LLVM ((LLVM_VERSION_MAJOR << 8) | LLVM_VERSION_MINOR)
56 #endif
57
58 #include "llvm/IR/Verifier.h"
59 #include "llvm/ExecutionEngine/MCJIT.h"
60 #include "llvm/Support/FileSystem.h"
61 #define LLVM_F_NONE sys::fs::F_None
62
63 #include "llvm/Analysis/Passes.h"
64
65 #include "llvm/IR/LegacyPassManager.h"
66 using FunctionPassManager = llvm::legacy::FunctionPassManager;
67 using PassManager = llvm::legacy::PassManager;
68
69 #include "llvm/CodeGen/Passes.h"
70 #include "llvm/ExecutionEngine/ExecutionEngine.h"
71 #include "llvm/Support/raw_ostream.h"
72 #include "llvm/Support/TargetSelect.h"
73 #include "llvm/Transforms/IPO.h"
74 #include "llvm/Transforms/Scalar.h"
75 #include "llvm/Support/Host.h"
76 #include "llvm/Support/DynamicLibrary.h"
77
78
79 #include "common/os.h"
80 #include "common/isa.hpp"
81
82 #include <mutex>
83
84 #pragma pop_macro("DEBUG")
85
86 //////////////////////////////////////////////////////////////////////////
87 /// JitInstructionSet
88 /// @brief Subclass of InstructionSet that allows users to override
89 /// the reporting of support for certain ISA features. This allows capping
90 /// the jitted code to a certain feature level, e.g. jit AVX level code on
91 /// a platform that supports AVX2.
92 //////////////////////////////////////////////////////////////////////////
93 class JitInstructionSet : public InstructionSet
94 {
95 public:
96 JitInstructionSet(const char* requestedIsa) : isaRequest(requestedIsa)
97 {
98 std::transform(isaRequest.begin(), isaRequest.end(), isaRequest.begin(), ::tolower);
99
100 if(isaRequest == "avx")
101 {
102 bForceAVX = true;
103 bForceAVX2 = false;
104 bForceAVX512 = false;
105 }
106 else if(isaRequest == "avx2")
107 {
108 bForceAVX = false;
109 bForceAVX2 = true;
110 bForceAVX512 = false;
111 }
112 #if 0
113 else if(isaRequest == "avx512")
114 {
115 bForceAVX = false;
116 bForceAVX2 = false;
117 bForceAVX512 = true;
118 }
119 #endif
120 };
121
122 bool AVX2(void) { return bForceAVX ? 0 : InstructionSet::AVX2(); }
123 bool AVX512F(void) { return (bForceAVX | bForceAVX2) ? 0 : InstructionSet::AVX512F(); }
124 bool BMI2(void) { return bForceAVX ? 0 : InstructionSet::BMI2(); }
125
126 private:
127 bool bForceAVX = false;
128 bool bForceAVX2 = false;
129 bool bForceAVX512 = false;
130 std::string isaRequest;
131 };
132
133
134
135 struct JitLLVMContext : llvm::LLVMContext
136 {
137 };
138
139 //////////////////////////////////////////////////////////////////////////
140 /// JitCache
141 //////////////////////////////////////////////////////////////////////////
142 class JitCache : public llvm::ObjectCache
143 {
144 public:
145 /// constructor
146 JitCache();
147 virtual ~JitCache() {}
148
149 void SetCpu(const llvm::StringRef& cpu) { mCpu = cpu.str(); }
150
151 /// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
152 virtual void notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj);
153
154 /// Returns a pointer to a newly allocated MemoryBuffer that contains the
155 /// object which corresponds with Module M, or 0 if an object is not
156 /// available.
157 virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M);
158
159 private:
160 std::string mCpu;
161 llvm::SmallString<MAX_PATH> mCacheDir;
162 uint32_t mCurrentModuleCRC;
163 };
164
165 //////////////////////////////////////////////////////////////////////////
166 /// JitManager
167 //////////////////////////////////////////////////////////////////////////
168 struct JitManager
169 {
170 JitManager(uint32_t w, const char* arch, const char* core);
171 ~JitManager(){};
172
173 JitLLVMContext mContext; ///< LLVM compiler
174 llvm::IRBuilder<> mBuilder; ///< LLVM IR Builder
175 llvm::ExecutionEngine* mpExec;
176 JitCache mCache;
177
178 // Need to be rebuilt after a JIT and before building new IR
179 llvm::Module* mpCurrentModule;
180 bool mIsModuleFinalized;
181 uint32_t mJitNumber;
182
183 uint32_t mVWidth;
184
185 // Built in types.
186 llvm::Type* mInt8Ty;
187 llvm::Type* mInt32Ty;
188 llvm::Type* mInt64Ty;
189 llvm::Type* mFP32Ty;
190
191 llvm::Type* mSimtFP32Ty;
192 llvm::Type* mSimtInt32Ty;
193
194 llvm::Type* mSimdVectorInt32Ty;
195 llvm::Type* mSimdVectorTy;
196
197 // fetch shader types
198 llvm::FunctionType* mFetchShaderTy;
199
200 JitInstructionSet mArch;
201 std::string mCore;
202
203 void SetupNewModule();
204
205 void DumpAsm(llvm::Function* pFunction, const char* fileName);
206 static void DumpToFile(llvm::Function *f, const char *fileName);
207 };