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 builder.h 24 * 25 * @brief Includes all the builder related functionality 26 * 27 * Notes: 28 * 29 ******************************************************************************/ 30 31 #include "jit_pch.hpp" 32 #include "builder.h" 33 34 namespace SwrJit 35 { 36 using namespace llvm; 37 38 ////////////////////////////////////////////////////////////////////////// 39 /// @brief Contructor for Builder. 40 /// @param pJitMgr - JitManager which contains modules, function passes, etc. Builder(JitManager * pJitMgr)41 Builder::Builder(JitManager* pJitMgr) : mpJitMgr(pJitMgr), mpPrivateContext(nullptr) 42 { 43 mVWidth = pJitMgr->mVWidth; 44 mVWidth16 = 16; 45 46 mpIRBuilder = &pJitMgr->mBuilder; 47 48 // Built in types: scalar 49 50 mVoidTy = Type::getVoidTy(pJitMgr->mContext); 51 mFP16Ty = Type::getHalfTy(pJitMgr->mContext); 52 mFP32Ty = Type::getFloatTy(pJitMgr->mContext); 53 mFP32PtrTy = PointerType::get(mFP32Ty, 0); 54 mDoubleTy = Type::getDoubleTy(pJitMgr->mContext); 55 mInt1Ty = Type::getInt1Ty(pJitMgr->mContext); 56 mInt8Ty = Type::getInt8Ty(pJitMgr->mContext); 57 mInt16Ty = Type::getInt16Ty(pJitMgr->mContext); 58 mInt32Ty = Type::getInt32Ty(pJitMgr->mContext); 59 mInt64Ty = Type::getInt64Ty(pJitMgr->mContext); 60 mInt8PtrTy = PointerType::get(mInt8Ty, 0); 61 mInt16PtrTy = PointerType::get(mInt16Ty, 0); 62 mInt32PtrTy = PointerType::get(mInt32Ty, 0); 63 mInt64PtrTy = PointerType::get(mInt64Ty, 0); 64 mHandleTy = mInt8PtrTy; 65 66 mSimd4FP64Ty = getVectorType(mDoubleTy, 4); 67 68 // Built in types: target simd 69 SetTargetWidth(pJitMgr->mVWidth); 70 71 // Built in types: simd16 72 73 mSimd16Int1Ty = getVectorType(mInt1Ty, mVWidth16); 74 mSimd16Int16Ty = getVectorType(mInt16Ty, mVWidth16); 75 mSimd16Int32Ty = getVectorType(mInt32Ty, mVWidth16); 76 mSimd16Int64Ty = getVectorType(mInt64Ty, mVWidth16); 77 mSimd16FP16Ty = getVectorType(mFP16Ty, mVWidth16); 78 mSimd16FP32Ty = getVectorType(mFP32Ty, mVWidth16); 79 mSimd16VectorTy = ArrayType::get(mSimd16FP32Ty, 4); 80 mSimd16VectorTRTy = ArrayType::get(mSimd16FP32Ty, 5); 81 82 mSimd32Int8Ty = getVectorType(mInt8Ty, 32); 83 84 if (sizeof(uint32_t*) == 4) 85 { 86 mIntPtrTy = mInt32Ty; 87 mSimdIntPtrTy = mSimdInt32Ty; 88 mSimd16IntPtrTy = mSimd16Int32Ty; 89 } 90 else 91 { 92 SWR_ASSERT(sizeof(uint32_t*) == 8); 93 94 mIntPtrTy = mInt64Ty; 95 mSimdIntPtrTy = mSimdInt64Ty; 96 mSimd16IntPtrTy = mSimd16Int64Ty; 97 } 98 } 99 SetTargetWidth(uint32_t width)100 void Builder::SetTargetWidth(uint32_t width) 101 { 102 mVWidth = width; 103 104 mSimdInt1Ty = getVectorType(mInt1Ty, mVWidth); 105 mSimdInt16Ty = getVectorType(mInt16Ty, mVWidth); 106 mSimdInt32Ty = getVectorType(mInt32Ty, mVWidth); 107 mSimdInt64Ty = getVectorType(mInt64Ty, mVWidth); 108 mSimdFP16Ty = getVectorType(mFP16Ty, mVWidth); 109 mSimdFP32Ty = getVectorType(mFP32Ty, mVWidth); 110 mSimdVectorTy = ArrayType::get(mSimdFP32Ty, 4); 111 mSimdVectorIntTy = ArrayType::get(mSimdInt32Ty, 4); 112 mSimdVectorTRTy = ArrayType::get(mSimdFP32Ty, 5); 113 mSimdVectorTRIntTy = ArrayType::get(mSimdInt32Ty, 5); 114 } 115 116 /// @brief Mark this alloca as temporary to avoid hoisting later on SetTempAlloca(Value * inst)117 void Builder::SetTempAlloca(Value* inst) 118 { 119 AllocaInst* pAlloca = dyn_cast<AllocaInst>(inst); 120 SWR_ASSERT(pAlloca, "Unexpected non-alloca instruction"); 121 MDNode* N = MDNode::get(JM()->mContext, MDString::get(JM()->mContext, "is_temp_alloca")); 122 pAlloca->setMetadata("is_temp_alloca", N); 123 } 124 IsTempAlloca(Value * inst)125 bool Builder::IsTempAlloca(Value* inst) 126 { 127 AllocaInst* pAlloca = dyn_cast<AllocaInst>(inst); 128 SWR_ASSERT(pAlloca, "Unexpected non-alloca instruction"); 129 130 return (pAlloca->getMetadata("is_temp_alloca") != nullptr); 131 } 132 133 // Returns true if able to find a call instruction to mark SetNamedMetaDataOnCallInstr(Instruction * inst,StringRef mdName)134 bool Builder::SetNamedMetaDataOnCallInstr(Instruction* inst, StringRef mdName) 135 { 136 CallInst* pCallInstr = dyn_cast<CallInst>(inst); 137 if (pCallInstr) 138 { 139 MDNode* N = MDNode::get(JM()->mContext, MDString::get(JM()->mContext, mdName)); 140 pCallInstr->setMetadata(mdName, N); 141 return true; 142 } 143 else 144 { 145 // Follow use def chain back up 146 for (Use& u : inst->operands()) 147 { 148 Instruction* srcInst = dyn_cast<Instruction>(u.get()); 149 if (srcInst) 150 { 151 if (SetNamedMetaDataOnCallInstr(srcInst, mdName)) 152 { 153 return true; 154 } 155 } 156 } 157 } 158 159 return false; 160 } 161 HasNamedMetaDataOnCallInstr(Instruction * inst,StringRef mdName)162 bool Builder::HasNamedMetaDataOnCallInstr(Instruction* inst, StringRef mdName) 163 { 164 CallInst* pCallInstr = dyn_cast<CallInst>(inst); 165 166 if (!pCallInstr) 167 { 168 return false; 169 } 170 171 return (pCallInstr->getMetadata(mdName) != nullptr); 172 } 173 174 ////////////////////////////////////////////////////////////////////////// 175 /// @brief Packetizes the type. Assumes SOA conversion. GetVectorType(Type * pType)176 Type* Builder::GetVectorType(Type* pType) 177 { 178 if (pType->isVectorTy()) 179 { 180 return pType; 181 } 182 183 // [N x float] should packetize to [N x <8 x float>] 184 if (pType->isArrayTy()) 185 { 186 uint32_t arraySize = pType->getArrayNumElements(); 187 Type* pArrayType = pType->getArrayElementType(); 188 Type* pVecArrayType = GetVectorType(pArrayType); 189 Type* pVecType = ArrayType::get(pVecArrayType, arraySize); 190 return pVecType; 191 } 192 193 // {float,int} should packetize to {<8 x float>, <8 x int>} 194 if (pType->isAggregateType()) 195 { 196 uint32_t numElems = pType->getStructNumElements(); 197 SmallVector<Type*, 8> vecTypes; 198 for (uint32_t i = 0; i < numElems; ++i) 199 { 200 Type* pElemType = pType->getStructElementType(i); 201 Type* pVecElemType = GetVectorType(pElemType); 202 vecTypes.push_back(pVecElemType); 203 } 204 Type* pVecType = StructType::get(JM()->mContext, vecTypes); 205 return pVecType; 206 } 207 208 // [N x float]* should packetize to [N x <8 x float>]* 209 if (pType->isPointerTy() && pType->getPointerElementType()->isArrayTy()) 210 { 211 return PointerType::get(GetVectorType(pType->getPointerElementType()), 212 pType->getPointerAddressSpace()); 213 } 214 215 // <ty> should packetize to <8 x <ty>> 216 Type* vecType = getVectorType(pType, JM()->mVWidth); 217 return vecType; 218 } 219 } // namespace SwrJit 220