swr/rast: silence write of cfg graph
[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 #pragma push_macro("DEBUG")
35 #undef DEBUG
36
37 #if defined(_WIN32)
38 #include "llvm/ADT/Triple.h"
39 #endif
40 #include "llvm/IR/Function.h"
41
42 #include "llvm/Support/MemoryBuffer.h"
43 #include "llvm/Support/SourceMgr.h"
44
45 #include "llvm/Analysis/CFGPrinter.h"
46 #include "llvm/IRReader/IRReader.h"
47 #include "llvm/Target/TargetMachine.h"
48 #include "llvm/Support/FormattedStream.h"
49
50 #if LLVM_USE_INTEL_JITEVENTS
51 #include "llvm/ExecutionEngine/JITEventListener.h"
52 #endif
53
54 #pragma pop_macro("DEBUG")
55
56 #include "JitManager.h"
57 #include "jit_api.h"
58 #include "fetch_jit.h"
59
60 #include "core/state.h"
61
62 #include "gen_state_llvm.h"
63
64 #include <sstream>
65 #if defined(_WIN32)
66 #include <psapi.h>
67 #include <cstring>
68
69 #define INTEL_OUTPUT_DIR "c:\\Intel"
70 #define SWR_OUTPUT_DIR INTEL_OUTPUT_DIR "\\SWR"
71 #define JITTER_OUTPUT_DIR SWR_OUTPUT_DIR "\\Jitter"
72 #endif // _WIN32
73
74
75 using namespace llvm;
76 using namespace SwrJit;
77
78 //////////////////////////////////////////////////////////////////////////
79 /// @brief Contructor for JitManager.
80 /// @param simdWidth - SIMD width to be used in generated program.
81 JitManager::JitManager(uint32_t simdWidth, const char *arch, const char* core)
82 : mContext(), mBuilder(mContext), mIsModuleFinalized(true), mJitNumber(0), mVWidth(simdWidth), mArch(arch)
83 {
84 InitializeNativeTarget();
85 InitializeNativeTargetAsmPrinter();
86 InitializeNativeTargetDisassembler();
87
88 TargetOptions tOpts;
89 tOpts.AllowFPOpFusion = FPOpFusion::Fast;
90 tOpts.NoInfsFPMath = false;
91 tOpts.NoNaNsFPMath = false;
92 tOpts.UnsafeFPMath = false;
93 #if defined(_DEBUG)
94 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7
95 tOpts.NoFramePointerElim = true;
96 #endif
97 #endif
98
99 //tOpts.PrintMachineCode = true;
100
101 mCore = std::string(core);
102 std::transform(mCore.begin(), mCore.end(), mCore.begin(), ::tolower);
103
104 std::stringstream fnName("JitModule", std::ios_base::in | std::ios_base::out | std::ios_base::ate);
105 fnName << mJitNumber++;
106 std::unique_ptr<Module> newModule(new Module(fnName.str(), mContext));
107 mpCurrentModule = newModule.get();
108
109 StringRef hostCPUName;
110
111 hostCPUName = sys::getHostCPUName();
112
113 #if defined(_WIN32)
114 // Needed for MCJIT on windows
115 Triple hostTriple(sys::getProcessTriple());
116 hostTriple.setObjectFormat(Triple::ELF);
117 mpCurrentModule->setTargetTriple(hostTriple.getTriple());
118 #endif // _WIN32
119
120 mpExec = EngineBuilder(std::move(newModule))
121 .setTargetOptions(tOpts)
122 .setOptLevel(CodeGenOpt::Aggressive)
123 .setMCPU(hostCPUName)
124 .create();
125
126 #if LLVM_USE_INTEL_JITEVENTS
127 JITEventListener *vTune = JITEventListener::createIntelJITEventListener();
128 mpExec->RegisterJITEventListener(vTune);
129 #endif
130
131 mFP32Ty = Type::getFloatTy(mContext); // float type
132 mInt8Ty = Type::getInt8Ty(mContext);
133 mInt32Ty = Type::getInt32Ty(mContext); // int type
134 mInt64Ty = Type::getInt64Ty(mContext); // int type
135
136 // fetch function signature
137 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simdvertex& out);
138 std::vector<Type*> fsArgs;
139 fsArgs.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
140 fsArgs.push_back(PointerType::get(Gen_simdvertex(this), 0));
141
142 mFetchShaderTy = FunctionType::get(Type::getVoidTy(mContext), fsArgs, false);
143
144 mSimtFP32Ty = VectorType::get(mFP32Ty, mVWidth);
145 mSimtInt32Ty = VectorType::get(mInt32Ty, mVWidth);
146
147 mSimdVectorTy = ArrayType::get(mSimtFP32Ty, 4);
148 mSimdVectorInt32Ty = ArrayType::get(mSimtInt32Ty, 4);
149
150 #if defined(_WIN32)
151 // explicitly instantiate used symbols from potentially staticly linked libs
152 sys::DynamicLibrary::AddSymbol("exp2f", &exp2f);
153 sys::DynamicLibrary::AddSymbol("log2f", &log2f);
154 sys::DynamicLibrary::AddSymbol("sinf", &sinf);
155 sys::DynamicLibrary::AddSymbol("cosf", &cosf);
156 sys::DynamicLibrary::AddSymbol("powf", &powf);
157 #endif
158
159 #if defined(_WIN32)
160 if (KNOB_DUMP_SHADER_IR)
161 {
162 CreateDirectoryPath(INTEL_OUTPUT_DIR);
163 CreateDirectoryPath(SWR_OUTPUT_DIR);
164 CreateDirectoryPath(JITTER_OUTPUT_DIR);
165 }
166 #endif
167 }
168
169 //////////////////////////////////////////////////////////////////////////
170 /// @brief Create new LLVM module.
171 void JitManager::SetupNewModule()
172 {
173 SWR_ASSERT(mIsModuleFinalized == true && "Current module is not finalized!");
174
175 std::stringstream fnName("JitModule", std::ios_base::in | std::ios_base::out | std::ios_base::ate);
176 fnName << mJitNumber++;
177 std::unique_ptr<Module> newModule(new Module(fnName.str(), mContext));
178 mpCurrentModule = newModule.get();
179 #if defined(_WIN32)
180 // Needed for MCJIT on windows
181 Triple hostTriple(sys::getProcessTriple());
182 hostTriple.setObjectFormat(Triple::ELF);
183 newModule->setTargetTriple(hostTriple.getTriple());
184 #endif // _WIN32
185
186 mpExec->addModule(std::move(newModule));
187 mIsModuleFinalized = false;
188 }
189
190
191 //////////////////////////////////////////////////////////////////////////
192 /// @brief Dump function x86 assembly to file.
193 /// @note This should only be called after the module has been jitted to x86 and the
194 /// module will not be further accessed.
195 void JitManager::DumpAsm(Function* pFunction, const char* fileName)
196 {
197 if (KNOB_DUMP_SHADER_IR)
198 {
199
200 #if defined(_WIN32)
201 DWORD pid = GetCurrentProcessId();
202 TCHAR procname[MAX_PATH];
203 GetModuleFileName(NULL, procname, MAX_PATH);
204 const char* pBaseName = strrchr(procname, '\\');
205 std::stringstream outDir;
206 outDir << JITTER_OUTPUT_DIR << pBaseName << "_" << pid << std::ends;
207 CreateDirectoryPath(outDir.str().c_str());
208 #endif
209
210 std::error_code EC;
211 Module* pModule = pFunction->getParent();
212 const char *funcName = pFunction->getName().data();
213 char fName[256];
214 #if defined(_WIN32)
215 sprintf(fName, "%s\\%s.%s.asm", outDir.str().c_str(), funcName, fileName);
216 #else
217 sprintf(fName, "%s.%s.asm", funcName, fileName);
218 #endif
219
220 raw_fd_ostream filestream(fName, EC, llvm::sys::fs::F_None);
221
222 legacy::PassManager* pMPasses = new legacy::PassManager();
223 auto* pTarget = mpExec->getTargetMachine();
224 pTarget->Options.MCOptions.AsmVerbose = true;
225 pTarget->addPassesToEmitFile(*pMPasses, filestream, TargetMachine::CGFT_AssemblyFile);
226 pMPasses->run(*pModule);
227 delete pMPasses;
228 pTarget->Options.MCOptions.AsmVerbose = false;
229 }
230 }
231
232 //////////////////////////////////////////////////////////////////////////
233 /// @brief Dump function to file.
234 void JitManager::DumpToFile(Function *f, const char *fileName)
235 {
236 if (KNOB_DUMP_SHADER_IR)
237 {
238 #if defined(_WIN32)
239 DWORD pid = GetCurrentProcessId();
240 TCHAR procname[MAX_PATH];
241 GetModuleFileName(NULL, procname, MAX_PATH);
242 const char* pBaseName = strrchr(procname, '\\');
243 std::stringstream outDir;
244 outDir << JITTER_OUTPUT_DIR << pBaseName << "_" << pid << std::ends;
245 CreateDirectoryPath(outDir.str().c_str());
246 #endif
247
248 std::error_code EC;
249 const char *funcName = f->getName().data();
250 char fName[256];
251 #if defined(_WIN32)
252 sprintf(fName, "%s\\%s.%s.ll", outDir.str().c_str(), funcName, fileName);
253 #else
254 sprintf(fName, "%s.%s.ll", funcName, fileName);
255 #endif
256 raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);
257 Module* pModule = f->getParent();
258 pModule->print(fd, nullptr);
259
260 #if defined(_WIN32)
261 sprintf(fName, "%s\\cfg.%s.%s.dot", outDir.str().c_str(), funcName, fileName);
262 #else
263 sprintf(fName, "cfg.%s.%s.dot", funcName, fileName);
264 #endif
265 fd.flush();
266
267 //raw_fd_ostream fd_cfg(fName, EC, llvm::sys::fs::F_Text);
268 //WriteGraph(fd_cfg, (const Function*)f);
269
270 //fd_cfg.flush();
271 }
272 }
273
274 extern "C"
275 {
276 bool g_DllActive = true;
277
278 //////////////////////////////////////////////////////////////////////////
279 /// @brief Create JIT context.
280 /// @param simdWidth - SIMD width to be used in generated program.
281 HANDLE JITCALL JitCreateContext(uint32_t targetSimdWidth, const char* arch, const char* core)
282 {
283 return new JitManager(targetSimdWidth, arch, core);
284 }
285
286 //////////////////////////////////////////////////////////////////////////
287 /// @brief Destroy JIT context.
288 void JITCALL JitDestroyContext(HANDLE hJitContext)
289 {
290 if (g_DllActive)
291 {
292 delete reinterpret_cast<JitManager*>(hJitContext);
293 }
294 }
295 }