1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2018-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #include "llvmWrapper/IR/DerivedTypes.h"
10 
11 #include "PacketBuilder.h"
12 #include "Probe/Assertion.h"
13 
14 using namespace llvm;
15 
16 namespace pktz
17 {
18     //////////////////////////////////////////////////////////////////////////
19     /// @brief Contructor for Builder.
20     /// @param pJitMgr - JitManager which contains modules, function passes, etc.
PacketBuilder(Module * pModule,uint32_t width)21     PacketBuilder::PacketBuilder(Module *pModule, uint32_t width)
22     {
23         mVWidth16 = 16;
24         mpModule = static_cast<IGCLLVM::Module*>(pModule);
25 
26         // Built in types: scalar
27         LLVMContext& Ctx = getContext();
28         mpIRBuilder = new IGCLLVM::IRBuilder<>(Ctx);
29         mVoidTy     = Type::getVoidTy(Ctx);
30         mFP16Ty     = Type::getHalfTy(Ctx);
31         mFP32Ty     = Type::getFloatTy(Ctx);
32         mFP32PtrTy  = PointerType::get(mFP32Ty, 0);
33         mDoubleTy   = Type::getDoubleTy(Ctx);
34         mInt1Ty     = Type::getInt1Ty(Ctx);
35         mInt8Ty     = Type::getInt8Ty(Ctx);
36         mInt16Ty    = Type::getInt16Ty(Ctx);
37         mInt32Ty    = Type::getInt32Ty(Ctx);
38         mInt8PtrTy  = PointerType::get(mInt8Ty, 0);
39         mInt16PtrTy = PointerType::get(mInt16Ty, 0);
40         mInt32PtrTy = PointerType::get(mInt32Ty, 0);
41         mInt64Ty    = Type::getInt64Ty(Ctx);
42 
43         mSimd4FP64Ty = IGCLLVM::FixedVectorType::get(mDoubleTy, 4);
44 
45         // Built in types: simd16
46         mSimd16Int1Ty = IGCLLVM::FixedVectorType::get(mInt1Ty, mVWidth16);
47         mSimd16Int16Ty = IGCLLVM::FixedVectorType::get(mInt16Ty, mVWidth16);
48         mSimd16Int32Ty = IGCLLVM::FixedVectorType::get(mInt32Ty, mVWidth16);
49         mSimd16Int64Ty = IGCLLVM::FixedVectorType::get(mInt64Ty, mVWidth16);
50         mSimd16FP16Ty = IGCLLVM::FixedVectorType::get(mFP16Ty, mVWidth16);
51         mSimd16FP32Ty = IGCLLVM::FixedVectorType::get(mFP32Ty, mVWidth16);
52 
53         mSimd32Int8Ty = IGCLLVM::FixedVectorType::get(mInt8Ty, 32);
54 
55         if (sizeof(uint32_t*) == 4)
56         {
57             mIntPtrTy       = mInt32Ty;
58             mSimd16IntPtrTy = mSimd16Int32Ty;
59         }
60         else
61         {
62             IGC_ASSERT(sizeof(uint32_t*) == 8);
63             mIntPtrTy       = mInt64Ty;
64             mSimd16IntPtrTy = mSimd16Int64Ty;
65         }
66         // Built in types: target simd
67         SetTargetWidth(width);
68 
69     }
70 
SetTargetWidth(uint32_t width)71     void PacketBuilder::SetTargetWidth(uint32_t width)
72     {
73         mVWidth = width;
74 
75         mSimdInt1Ty = IGCLLVM::FixedVectorType::get(mInt1Ty, mVWidth);
76         mSimdInt16Ty = IGCLLVM::FixedVectorType::get(mInt16Ty, mVWidth);
77         mSimdInt32Ty = IGCLLVM::FixedVectorType::get(mInt32Ty, mVWidth);
78         mSimdInt64Ty = IGCLLVM::FixedVectorType::get(mInt64Ty, mVWidth);
79         mSimdFP16Ty = IGCLLVM::FixedVectorType::get(mFP16Ty, mVWidth);
80         mSimdFP32Ty = IGCLLVM::FixedVectorType::get(mFP32Ty, mVWidth);
81         if (sizeof(uint32_t*) == 4)
82         {
83           mSimdIntPtrTy = mSimdInt32Ty;
84         }
85         else
86         {
87           IGC_ASSERT(sizeof(uint32_t*) == 8);
88           mSimdIntPtrTy = mSimdInt64Ty;
89         }
90     }
91 
92     /// @brief Mark this alloca as temporary to avoid hoisting later on
SetTempAlloca(Value * inst)93     void PacketBuilder::SetTempAlloca(Value* inst)
94     {
95         AllocaInst* pAlloca = dyn_cast<AllocaInst>(inst);
96         IGC_ASSERT_MESSAGE(pAlloca, "Unexpected non-alloca instruction");
97         MDNode* N = MDNode::get(getContext(), MDString::get(getContext(), "is_temp_alloca"));
98         pAlloca->setMetadata("is_temp_alloca", N);
99     }
100 
IsTempAlloca(Value * inst)101     bool PacketBuilder::IsTempAlloca(Value* inst)
102     {
103         AllocaInst* pAlloca = dyn_cast<AllocaInst>(inst);
104         IGC_ASSERT_MESSAGE(pAlloca, "Unexpected non-alloca instruction");
105 
106         return (pAlloca->getMetadata("is_temp_alloca") != nullptr);
107     }
108 
109     // Returns true if able to find a call instruction to mark
SetNamedMetaDataOnCallInstr(Instruction * inst,StringRef mdName)110     bool PacketBuilder::SetNamedMetaDataOnCallInstr(Instruction* inst, StringRef mdName)
111     {
112         CallInst* pCallInstr = dyn_cast<CallInst>(inst);
113         if (pCallInstr)
114         {
115             MDNode* N = MDNode::get(getContext(), MDString::get(getContext(), mdName));
116             pCallInstr->setMetadata(mdName, N);
117             return true;
118         }
119         else
120         {
121             // Follow use def chain back up
122             for (Use& u : inst->operands())
123             {
124                 Instruction* srcInst = dyn_cast<Instruction>(u.get());
125                 if (srcInst)
126                 {
127                     if (SetNamedMetaDataOnCallInstr(srcInst, mdName))
128                     {
129                         return true;
130                     }
131                 }
132             }
133         }
134 
135         return false;
136     }
137 
HasNamedMetaDataOnCallInstr(Instruction * inst,StringRef mdName)138     bool PacketBuilder::HasNamedMetaDataOnCallInstr(Instruction* inst, StringRef mdName)
139     {
140         CallInst* pCallInstr = dyn_cast<CallInst>(inst);
141 
142         if (!pCallInstr)
143         {
144             return false;
145         }
146 
147         return (pCallInstr->getMetadata(mdName) != nullptr);
148     }
149 
150     //////////////////////////////////////////////////////////////////////////
151     /// @brief Packetizes the type. Assumes SOA conversion.
GetVectorType(Type * pType)152     Type* PacketBuilder::GetVectorType(Type* pType)
153     {
154         if (pType->isVoidTy())
155             return pType;
156 
157         if (auto VecpType = dyn_cast<IGCLLVM::FixedVectorType>(pType)) {
158           uint32_t vectorSize = VecpType->getNumElements();
159           Type *pElemType = VecpType->getElementType();
160           Type *pVecType =
161               IGCLLVM::FixedVectorType::get(pElemType, vectorSize * mVWidth);
162           return pVecType;
163         }
164 
165         // [N x float] should packetize to [N x <8 x float>]
166         if (pType->isArrayTy())
167         {
168             uint32_t arraySize     = pType->getArrayNumElements();
169             Type*    pArrayType    = pType->getArrayElementType();
170             Type*    pVecArrayType = GetVectorType(pArrayType);
171             Type*    pVecType      = ArrayType::get(pVecArrayType, arraySize);
172             return pVecType;
173         }
174 
175         // {float,int} should packetize to {<8 x float>, <8 x int>}
176         if (pType->isAggregateType())
177         {
178             uint32_t              numElems = pType->getStructNumElements();
179             SmallVector<Type*, 8> vecTypes;
180             for (uint32_t i = 0; i < numElems; ++i)
181             {
182                 Type* pElemType    = pType->getStructElementType(i);
183                 Type* pVecElemType = GetVectorType(pElemType);
184                 vecTypes.push_back(pVecElemType);
185             }
186             Type* pVecType = StructType::get(getContext(), vecTypes);
187             return pVecType;
188         }
189 
190         // <ty> should packetize to <8 x <ty>>
191         Type *vecType = IGCLLVM::FixedVectorType::get(pType, mVWidth);
192         return vecType;
193     }
194 } // end of namespace pktz
195