Home | History | Annotate | Download | only in jitter
      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 "jit_pch.hpp"
     33 #include "common/isa.hpp"
     34 
     35 
     36 //////////////////////////////////////////////////////////////////////////
     37 /// JitInstructionSet
     38 /// @brief Subclass of InstructionSet that allows users to override
     39 /// the reporting of support for certain ISA features.  This allows capping
     40 /// the jitted code to a certain feature level, e.g. jit AVX level code on
     41 /// a platform that supports AVX2.
     42 //////////////////////////////////////////////////////////////////////////
     43 class JitInstructionSet : public InstructionSet
     44 {
     45 public:
     46     JitInstructionSet(const char* requestedIsa) : isaRequest(requestedIsa)
     47     {
     48         std::transform(isaRequest.begin(), isaRequest.end(), isaRequest.begin(), ::tolower);
     49 
     50         if(isaRequest == "avx")
     51         {
     52             bForceAVX = true;
     53             bForceAVX2 = false;
     54             bForceAVX512 = false;
     55         }
     56         else if(isaRequest == "avx2")
     57         {
     58             bForceAVX = false;
     59             bForceAVX2 = true;
     60             bForceAVX512 = false;
     61         }
     62         else if(isaRequest == "avx512")
     63         {
     64             bForceAVX = false;
     65             bForceAVX2 = false;
     66             bForceAVX512 = true;
     67         }
     68     };
     69 
     70     bool AVX2(void) { return bForceAVX ? 0 : InstructionSet::AVX2(); }
     71     bool AVX512F(void) { return (bForceAVX | bForceAVX2) ? 0 : InstructionSet::AVX512F(); }
     72     bool BMI2(void) { return bForceAVX ? 0 : InstructionSet::BMI2(); }
     73 
     74 private:
     75     bool bForceAVX = false;
     76     bool bForceAVX2 = false;
     77     bool bForceAVX512 = false;
     78     std::string isaRequest;
     79 };
     80 
     81 
     82 
     83 struct JitLLVMContext : llvm::LLVMContext
     84 {
     85 };
     86 
     87 
     88 //////////////////////////////////////////////////////////////////////////
     89 /// JitCache
     90 //////////////////////////////////////////////////////////////////////////
     91 struct JitManager; // Forward Decl
     92 class JitCache : public llvm::ObjectCache
     93 {
     94 public:
     95     /// constructor
     96     JitCache();
     97     virtual ~JitCache() {}
     98 
     99     void Init(
    100         JitManager* pJitMgr,
    101         const llvm::StringRef& cpu,
    102         llvm::CodeGenOpt::Level level)
    103     {
    104         mCpu = cpu.str();
    105         mpJitMgr = pJitMgr;
    106         mOptLevel = level;
    107     }
    108 
    109     /// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
    110     virtual void notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj);
    111 
    112     /// Returns a pointer to a newly allocated MemoryBuffer that contains the
    113     /// object which corresponds with Module M, or 0 if an object is not
    114     /// available.
    115     virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M);
    116 
    117 private:
    118     std::string mCpu;
    119     llvm::SmallString<MAX_PATH> mCacheDir;
    120     uint32_t mCurrentModuleCRC = 0;
    121     JitManager* mpJitMgr = nullptr;
    122     llvm::CodeGenOpt::Level mOptLevel = llvm::CodeGenOpt::None;
    123 };
    124 
    125 //////////////////////////////////////////////////////////////////////////
    126 /// JitManager
    127 //////////////////////////////////////////////////////////////////////////
    128 struct JitManager
    129 {
    130     JitManager(uint32_t w, const char* arch, const char* core);
    131     ~JitManager(){};
    132 
    133     JitLLVMContext          mContext;   ///< LLVM compiler
    134     llvm::IRBuilder<>       mBuilder;   ///< LLVM IR Builder
    135     llvm::ExecutionEngine*  mpExec;
    136     JitCache                mCache;
    137 
    138     // Need to be rebuilt after a JIT and before building new IR
    139     llvm::Module* mpCurrentModule;
    140     bool mIsModuleFinalized;
    141     uint32_t mJitNumber;
    142 
    143     uint32_t                 mVWidth;
    144 
    145 
    146     // Built in types.
    147     llvm::Type*                mInt8Ty;
    148     llvm::Type*                mInt32Ty;
    149     llvm::Type*                mInt64Ty;
    150     llvm::Type*                mFP32Ty;
    151 
    152     llvm::Type* mSimtFP32Ty;
    153     llvm::Type* mSimtInt32Ty;
    154 
    155     llvm::Type* mSimdVectorInt32Ty;
    156     llvm::Type* mSimdVectorTy;
    157 
    158 #if USE_SIMD16_SHADERS
    159     llvm::Type* mSimd16FP32Ty;
    160     llvm::Type* mSimd16Int32Ty;
    161 
    162     llvm::Type* mSimd16VectorFP32Ty;
    163     llvm::Type* mSimd16VectorInt32Ty;
    164 
    165 #endif
    166     // fetch shader types
    167     llvm::FunctionType*        mFetchShaderTy;
    168 
    169     JitInstructionSet mArch;
    170     std::string mCore;
    171 
    172     // Debugging support
    173     std::unordered_map<llvm::StructType*, llvm::DIType*> mDebugStructMap;
    174 
    175     void SetupNewModule();
    176 
    177     void DumpAsm(llvm::Function* pFunction, const char* fileName);
    178     static void DumpToFile(llvm::Function *f, const char *fileName);
    179     static void DumpToFile(llvm::Module *M, const char *fileName);
    180     static std::string GetOutputDir();
    181 
    182     // Debugging support methods
    183     llvm::DIType* GetDebugType(llvm::Type* pTy);
    184     llvm::DIType* GetDebugIntegerType(llvm::Type* pTy);
    185     llvm::DIType* GetDebugArrayType(llvm::Type* pTy);
    186     llvm::DIType* GetDebugVectorType(llvm::Type* pTy);
    187     llvm::DIType* GetDebugFunctionType(llvm::Type* pTy);
    188 
    189     llvm::DIType* GetDebugStructType(llvm::Type* pType)
    190     {
    191         llvm::StructType* pStructTy = llvm::cast<llvm::StructType>(pType);
    192         if (mDebugStructMap.find(pStructTy) == mDebugStructMap.end())
    193         {
    194             return nullptr;
    195         }
    196         return mDebugStructMap[pStructTy];
    197     }
    198 
    199     llvm::DIType* CreateDebugStructType(llvm::StructType* pType, const std::string& name, llvm::DIFile* pFile, uint32_t lineNum,
    200         const std::vector<std::pair<std::string, uint32_t>>& members);
    201 };
    202