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
23 * @file JitManager.cpp
25 * @brief Implementation if the Jit Manager.
29 ******************************************************************************/
31 #pragma warning(disable: 4800 4146 4244 4267 4355 4996)
34 #pragma push_macro("DEBUG")
38 #include "llvm/ADT/Triple.h"
40 #include "llvm/IR/Function.h"
42 #include "llvm/Support/MemoryBuffer.h"
43 #include "llvm/Support/SourceMgr.h"
45 #include "llvm/Analysis/CFGPrinter.h"
46 #include "llvm/IRReader/IRReader.h"
47 #include "llvm/Target/TargetMachine.h"
48 #include "llvm/Support/FormattedStream.h"
50 #if LLVM_USE_INTEL_JITEVENTS
51 #include "llvm/ExecutionEngine/JITEventListener.h"
54 #pragma pop_macro("DEBUG")
56 #include "JitManager.h"
58 #include "fetch_jit.h"
60 #include "core/state.h"
62 #include "gen_state_llvm.h"
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"
76 using namespace SwrJit
;
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
)
84 InitializeNativeTarget();
85 InitializeNativeTargetAsmPrinter();
86 InitializeNativeTargetDisassembler();
89 tOpts
.AllowFPOpFusion
= FPOpFusion::Fast
;
90 tOpts
.NoInfsFPMath
= false;
91 tOpts
.NoNaNsFPMath
= false;
92 tOpts
.UnsafeFPMath
= false;
94 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7
95 tOpts
.NoFramePointerElim
= true;
99 //tOpts.PrintMachineCode = true;
101 mCore
= std::string(core
);
102 std::transform(mCore
.begin(), mCore
.end(), mCore
.begin(), ::tolower
);
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();
109 StringRef hostCPUName
;
111 hostCPUName
= sys::getHostCPUName();
114 // Needed for MCJIT on windows
115 Triple
hostTriple(sys::getProcessTriple());
116 hostTriple
.setObjectFormat(Triple::ELF
);
117 mpCurrentModule
->setTargetTriple(hostTriple
.getTriple());
120 mpExec
= EngineBuilder(std::move(newModule
))
121 .setTargetOptions(tOpts
)
122 .setOptLevel(CodeGenOpt::Aggressive
)
123 .setMCPU(hostCPUName
)
126 #if LLVM_USE_INTEL_JITEVENTS
127 JITEventListener
*vTune
= JITEventListener::createIntelJITEventListener();
128 mpExec
->RegisterJITEventListener(vTune
);
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
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));
142 mFetchShaderTy
= FunctionType::get(Type::getVoidTy(mContext
), fsArgs
, false);
144 mSimtFP32Ty
= VectorType::get(mFP32Ty
, mVWidth
);
145 mSimtInt32Ty
= VectorType::get(mInt32Ty
, mVWidth
);
147 mSimdVectorTy
= ArrayType::get(mSimtFP32Ty
, 4);
148 mSimdVectorInt32Ty
= ArrayType::get(mSimtInt32Ty
, 4);
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
);
160 if (KNOB_DUMP_SHADER_IR
)
162 CreateDirectoryPath(INTEL_OUTPUT_DIR
);
163 CreateDirectoryPath(SWR_OUTPUT_DIR
);
164 CreateDirectoryPath(JITTER_OUTPUT_DIR
);
169 //////////////////////////////////////////////////////////////////////////
170 /// @brief Create new LLVM module.
171 void JitManager::SetupNewModule()
173 SWR_ASSERT(mIsModuleFinalized
== true && "Current module is not finalized!");
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();
180 // Needed for MCJIT on windows
181 Triple
hostTriple(sys::getProcessTriple());
182 hostTriple
.setObjectFormat(Triple::ELF
);
183 newModule
->setTargetTriple(hostTriple
.getTriple());
186 mpExec
->addModule(std::move(newModule
));
187 mIsModuleFinalized
= false;
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
)
197 if (KNOB_DUMP_SHADER_IR
)
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());
211 Module
* pModule
= pFunction
->getParent();
212 const char *funcName
= pFunction
->getName().data();
215 sprintf(fName
, "%s\\%s.%s.asm", outDir
.str().c_str(), funcName
, fileName
);
217 sprintf(fName
, "%s.%s.asm", funcName
, fileName
);
220 raw_fd_ostream
filestream(fName
, EC
, llvm::sys::fs::F_None
);
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
);
228 pTarget
->Options
.MCOptions
.AsmVerbose
= false;
232 //////////////////////////////////////////////////////////////////////////
233 /// @brief Dump function to file.
234 void JitManager::DumpToFile(Function
*f
, const char *fileName
)
236 if (KNOB_DUMP_SHADER_IR
)
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());
249 const char *funcName
= f
->getName().data();
252 sprintf(fName
, "%s\\%s.%s.ll", outDir
.str().c_str(), funcName
, fileName
);
254 sprintf(fName
, "%s.%s.ll", funcName
, fileName
);
256 raw_fd_ostream
fd(fName
, EC
, llvm::sys::fs::F_None
);
257 Module
* pModule
= f
->getParent();
258 pModule
->print(fd
, nullptr);
261 sprintf(fName
, "%s\\cfg.%s.%s.dot", outDir
.str().c_str(), funcName
, fileName
);
263 sprintf(fName
, "cfg.%s.%s.dot", funcName
, fileName
);
267 //raw_fd_ostream fd_cfg(fName, EC, llvm::sys::fs::F_Text);
268 //WriteGraph(fd_cfg, (const Function*)f);
276 bool g_DllActive
= true;
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
)
283 return new JitManager(targetSimdWidth
, arch
, core
);
286 //////////////////////////////////////////////////////////////////////////
287 /// @brief Destroy JIT context.
288 void JITCALL
JitDestroyContext(HANDLE hJitContext
)
292 delete reinterpret_cast<JitManager
*>(hJitContext
);