e7ba0040d9da11bfd1fc4c584f5f95cfeefd34d0
[mesa.git] / src / gallium / drivers / swr / rasterizer / jitter / builder.cpp
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.
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 = VectorType::get(mDoubleTy, 4);
67
68 // Built in types: target simd
69 SetTargetWidth(pJitMgr->mVWidth);
70
71 // Built in types: simd16
72
73 mSimd16Int1Ty = VectorType::get(mInt1Ty, mVWidth16);
74 mSimd16Int16Ty = VectorType::get(mInt16Ty, mVWidth16);
75 mSimd16Int32Ty = VectorType::get(mInt32Ty, mVWidth16);
76 mSimd16Int64Ty = VectorType::get(mInt64Ty, mVWidth16);
77 mSimd16FP16Ty = VectorType::get(mFP16Ty, mVWidth16);
78 mSimd16FP32Ty = VectorType::get(mFP32Ty, mVWidth16);
79 mSimd16VectorTy = ArrayType::get(mSimd16FP32Ty, 4);
80 mSimd16VectorTRTy = ArrayType::get(mSimd16FP32Ty, 5);
81
82 mSimd32Int8Ty = VectorType::get(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
100 void Builder::SetTargetWidth(uint32_t width)
101 {
102 mVWidth = width;
103
104 mSimdInt1Ty = VectorType::get(mInt1Ty, mVWidth);
105 mSimdInt16Ty = VectorType::get(mInt16Ty, mVWidth);
106 mSimdInt32Ty = VectorType::get(mInt32Ty, mVWidth);
107 mSimdInt64Ty = VectorType::get(mInt64Ty, mVWidth);
108 mSimdFP16Ty = VectorType::get(mFP16Ty, mVWidth);
109 mSimdFP32Ty = VectorType::get(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
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
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
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
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.
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 = VectorType::get(pType, JM()->mVWidth);
217 return vecType;
218 }
219 } // namespace SwrJit