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