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