swr: [rasterizer jitter] Fix MASKLOADD AVX prototype (float -> i32)
[mesa.git] / src / gallium / drivers / swr / rasterizer / jitter / JitManager.cpp
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.cpp
24 *
25 * @brief Implementation if the Jit Manager.
26 *
27 * Notes:
28 *
29 ******************************************************************************/
30 #if defined(_WIN32)
31 #pragma warning(disable: 4800 4146 4244 4267 4355 4996)
32 #endif
33
34 #include "jit_api.h"
35 #include "JitManager.h"
36 #include "fetch_jit.h"
37
38 #if defined(_WIN32)
39 #include "llvm/ADT/Triple.h"
40 #endif
41 #include "llvm/IR/Function.h"
42 #include "llvm/Support/DynamicLibrary.h"
43
44 #include "llvm/Support/MemoryBuffer.h"
45 #include "llvm/Support/SourceMgr.h"
46
47 #include "llvm/Analysis/CFGPrinter.h"
48 #include "llvm/IRReader/IRReader.h"
49
50 #if LLVM_USE_INTEL_JITEVENTS
51 #include "llvm/ExecutionEngine/JITEventListener.h"
52 #endif
53
54 #include "core/state.h"
55 #include "common/containers.hpp"
56
57 #include "state_llvm.h"
58
59 #include <sstream>
60 #if defined(_WIN32)
61 #include <psapi.h>
62 #include <cstring>
63
64 #define INTEL_OUTPUT_DIR "c:\\Intel"
65 #define SWR_OUTPUT_DIR INTEL_OUTPUT_DIR "\\SWR"
66 #define JITTER_OUTPUT_DIR SWR_OUTPUT_DIR "\\Jitter"
67 #endif
68
69 using namespace llvm;
70
71 //////////////////////////////////////////////////////////////////////////
72 /// @brief Contructor for JitManager.
73 /// @param simdWidth - SIMD width to be used in generated program.
74 JitManager::JitManager(uint32_t simdWidth, const char *arch)
75 : mContext(), mBuilder(mContext), mIsModuleFinalized(true), mJitNumber(0), mVWidth(simdWidth), mArch(arch)
76 {
77 InitializeNativeTarget();
78 InitializeNativeTargetAsmPrinter();
79 InitializeNativeTargetDisassembler();
80
81 TargetOptions tOpts;
82 tOpts.AllowFPOpFusion = FPOpFusion::Fast;
83 tOpts.NoInfsFPMath = false;
84 tOpts.NoNaNsFPMath = false;
85 tOpts.UnsafeFPMath = true;
86 #if defined(_DEBUG)
87 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7
88 tOpts.NoFramePointerElim = true;
89 #endif
90 #endif
91
92 //tOpts.PrintMachineCode = true;
93
94 std::stringstream fnName("JitModule", std::ios_base::in | std::ios_base::out | std::ios_base::ate);
95 fnName << mJitNumber++;
96 std::unique_ptr<Module> newModule(new Module(fnName.str(), mContext));
97 mpCurrentModule = newModule.get();
98
99 auto &&EB = EngineBuilder(std::move(newModule));
100 EB.setTargetOptions(tOpts);
101 EB.setOptLevel(CodeGenOpt::Aggressive);
102
103 StringRef hostCPUName;
104
105 // force JIT to use the same CPU arch as the rest of swr
106 if(mArch.AVX512F())
107 {
108 assert(0 && "Implement AVX512 jitter");
109 hostCPUName = sys::getHostCPUName();
110 if (mVWidth == 0)
111 {
112 mVWidth = 16;
113 }
114 }
115 else if(mArch.AVX2())
116 {
117 hostCPUName = StringRef("core-avx2");
118 if (mVWidth == 0)
119 {
120 mVWidth = 8;
121 }
122 }
123 else if(mArch.AVX())
124 {
125 if (mArch.F16C())
126 {
127 hostCPUName = StringRef("core-avx-i");
128 }
129 else
130 {
131 hostCPUName = StringRef("corei7-avx");
132 }
133 if (mVWidth == 0)
134 {
135 mVWidth = 8;
136 }
137 }
138 else
139 {
140 hostCPUName = sys::getHostCPUName();
141 if (mVWidth == 0)
142 {
143 mVWidth = 8; // 4?
144 }
145 }
146
147 EB.setMCPU(hostCPUName);
148
149 #if defined(_WIN32)
150 // Needed for MCJIT on windows
151 Triple hostTriple(sys::getProcessTriple());
152 hostTriple.setObjectFormat(Triple::ELF);
153 mpCurrentModule->setTargetTriple(hostTriple.getTriple());
154 #endif // _WIN32
155
156 mpExec = EB.create();
157
158 #if LLVM_USE_INTEL_JITEVENTS
159 JITEventListener *vTune = JITEventListener::createIntelJITEventListener();
160 mpExec->RegisterJITEventListener(vTune);
161 #endif
162
163 mFP32Ty = Type::getFloatTy(mContext); // float type
164 mInt8Ty = Type::getInt8Ty(mContext);
165 mInt32Ty = Type::getInt32Ty(mContext); // int type
166 mInt64Ty = Type::getInt64Ty(mContext); // int type
167 mV4FP32Ty = StructType::get(mContext, std::vector<Type*>(4, mFP32Ty), false); // vector4 float type (represented as structure)
168 mV4Int32Ty = StructType::get(mContext, std::vector<Type*>(4, mInt32Ty), false); // vector4 int type
169
170 // fetch function signature
171 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simdvertex& out);
172 std::vector<Type*> fsArgs;
173 fsArgs.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
174 fsArgs.push_back(PointerType::get(Gen_simdvertex(this), 0));
175
176 mFetchShaderTy = FunctionType::get(Type::getVoidTy(mContext), fsArgs, false);
177
178 mSimtFP32Ty = VectorType::get(mFP32Ty, mVWidth);
179 mSimtInt32Ty = VectorType::get(mInt32Ty, mVWidth);
180
181 mSimdVectorTy = StructType::get(mContext, std::vector<Type*>(4, mSimtFP32Ty), false);
182 mSimdVectorInt32Ty = StructType::get(mContext, std::vector<Type*>(4, mSimtInt32Ty), false);
183
184 #if defined(_WIN32)
185 // explicitly instantiate used symbols from potentially staticly linked libs
186 sys::DynamicLibrary::AddSymbol("exp2f", &exp2f);
187 sys::DynamicLibrary::AddSymbol("log2f", &log2f);
188 sys::DynamicLibrary::AddSymbol("sinf", &sinf);
189 sys::DynamicLibrary::AddSymbol("cosf", &cosf);
190 sys::DynamicLibrary::AddSymbol("powf", &powf);
191 #endif
192
193 #if defined(_WIN32)
194 if (KNOB_DUMP_SHADER_IR)
195 {
196 CreateDirectory(INTEL_OUTPUT_DIR, NULL);
197 CreateDirectory(SWR_OUTPUT_DIR, NULL);
198 CreateDirectory(JITTER_OUTPUT_DIR, NULL);
199 }
200
201 ///@todo Figure out a better solution for this.
202 // Redirect stdin, stdout, and stderr to attached console.
203 freopen("CONIN$", "r", stdin);
204 freopen("CONOUT$", "w", stdout);
205 freopen("CONOUT$", "w", stderr);
206 #endif
207 }
208
209 //////////////////////////////////////////////////////////////////////////
210 /// @brief Create new LLVM module.
211 void JitManager::SetupNewModule()
212 {
213 SWR_ASSERT(mIsModuleFinalized == true && "Current module is not finalized!");
214
215 std::stringstream fnName("JitModule", std::ios_base::in | std::ios_base::out | std::ios_base::ate);
216 fnName << mJitNumber++;
217 std::unique_ptr<Module> newModule(new Module(fnName.str(), mContext));
218 mpCurrentModule = newModule.get();
219 #if defined(_WIN32)
220 // Needed for MCJIT on windows
221 Triple hostTriple(sys::getProcessTriple());
222 hostTriple.setObjectFormat(Triple::ELF);
223 newModule->setTargetTriple(hostTriple.getTriple());
224 #endif // _WIN32
225
226 mpExec->addModule(std::move(newModule));
227 mIsModuleFinalized = false;
228 }
229
230 //////////////////////////////////////////////////////////////////////////
231 /// @brief Create new LLVM module from IR.
232 bool JitManager::SetupModuleFromIR(const uint8_t *pIR)
233 {
234 std::unique_ptr<MemoryBuffer> pMem = MemoryBuffer::getMemBuffer(StringRef((const char*)pIR), "");
235
236 SMDiagnostic Err;
237 std::unique_ptr<Module> newModule = parseIR(pMem.get()->getMemBufferRef(), Err, mContext);
238
239 if (newModule == nullptr)
240 {
241 SWR_ASSERT(0, "Parse failed! Check Err for details.");
242 return false;
243 }
244
245 mpCurrentModule = newModule.get();
246 #if defined(_WIN32)
247 // Needed for MCJIT on windows
248 Triple hostTriple(sys::getProcessTriple());
249 hostTriple.setObjectFormat(Triple::ELF);
250 newModule->setTargetTriple(hostTriple.getTriple());
251 #endif // _WIN32
252
253 mpExec->addModule(std::move(newModule));
254 mIsModuleFinalized = false;
255
256 return true;
257 }
258
259 //////////////////////////////////////////////////////////////////////////
260 /// @brief Dump function to file.
261 void JitManager::DumpToFile(Function *f, const char *fileName)
262 {
263 if (KNOB_DUMP_SHADER_IR)
264 {
265 #if defined(_WIN32)
266 DWORD pid = GetCurrentProcessId();
267 TCHAR procname[MAX_PATH];
268 GetModuleFileName(NULL, procname, MAX_PATH);
269 const char* pBaseName = strrchr(procname, '\\');
270 std::stringstream outDir;
271 outDir << JITTER_OUTPUT_DIR << pBaseName << "_" << pid << std::ends;
272 CreateDirectory(outDir.str().c_str(), NULL);
273 #endif
274
275 std::error_code EC;
276 const char *funcName = f->getName().data();
277 char fName[256];
278 #if defined(_WIN32)
279 sprintf(fName, "%s\\%s.%s.ll", outDir.str().c_str(), funcName, fileName);
280 #else
281 sprintf(fName, "%s.%s.ll", funcName, fileName);
282 #endif
283 raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);
284 Module* pModule = f->getParent();
285 pModule->print(fd, nullptr);
286
287 #if defined(_WIN32)
288 sprintf(fName, "%s\\cfg.%s.%s.dot", outDir.str().c_str(), funcName, fileName);
289 #else
290 sprintf(fName, "cfg.%s.%s.dot", funcName, fileName);
291 #endif
292 fd.flush();
293
294 raw_fd_ostream fd_cfg(fName, EC, llvm::sys::fs::F_Text);
295 WriteGraph(fd_cfg, (const Function*)f);
296
297 fd_cfg.flush();
298 }
299 }
300
301 extern "C"
302 {
303 //////////////////////////////////////////////////////////////////////////
304 /// @brief Create JIT context.
305 /// @param simdWidth - SIMD width to be used in generated program.
306 HANDLE JITCALL JitCreateContext(uint32_t targetSimdWidth, const char* arch)
307 {
308 return new JitManager(targetSimdWidth, arch);
309 }
310
311 //////////////////////////////////////////////////////////////////////////
312 /// @brief Destroy JIT context.
313 void JITCALL JitDestroyContext(HANDLE hJitContext)
314 {
315 delete reinterpret_cast<JitManager*>(hJitContext);
316 }
317 }