1 /****************************************************************************
2 * Copyright (C) 2014-2018 Intel Corporation. All Rights Reserved.
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:
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
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
23 * @file builder_gfx_mem.cpp
25 * @brief Definition of the gfx mem builder
29 ******************************************************************************/
30 #include "jit_pch.hpp"
32 #include "common/rdtsc_buckets.h"
33 #include "builder_gfx_mem.h"
39 BuilderGfxMem::BuilderGfxMem(JitManager
* pJitMgr
) : Builder(pJitMgr
)
41 mpTranslationFuncTy
= nullptr;
42 mpfnTranslateGfxAddressForRead
= nullptr;
43 mpfnTranslateGfxAddressForWrite
= nullptr;
44 mpfnTrackMemAccess
= nullptr;
45 mpParamSimDC
= nullptr;
46 mpWorkerData
= nullptr;
49 void BuilderGfxMem::NotifyPrivateContextSet()
53 void BuilderGfxMem::AssertGFXMemoryParams(Value
* ptr
, MEM_CLIENT usage
)
55 SWR_ASSERT(!(ptr
->getType() == mInt64Ty
&& usage
== MEM_CLIENT::MEM_CLIENT_INTERNAL
),
56 "Internal memory should not be gfxptr_t.");
59 //////////////////////////////////////////////////////////////////////////
60 /// @brief Generate a masked gather operation in LLVM IR. If not
61 /// supported on the underlying platform, emulate it with loads
62 /// @param vSrc - SIMD wide value that will be loaded if mask is invalid
63 /// @param pBase - Int8* base VB address pointer value
64 /// @param vIndices - SIMD wide value of VB byte offsets
65 /// @param vMask - SIMD wide mask that controls whether to access memory or the src values
66 /// @param scale - value to scale indices by
67 Value
* BuilderGfxMem::GATHERPS(Value
* vSrc
,
74 // address may be coming in as 64bit int now so get the pointer
75 if (pBase
->getType() == mInt64Ty
)
77 pBase
= INT_TO_PTR(pBase
, PointerType::get(mInt8Ty
, 0));
80 Value
* vGather
= Builder::GATHERPS(vSrc
, pBase
, vIndices
, vMask
, scale
);
84 //////////////////////////////////////////////////////////////////////////
85 /// @brief Generate a masked gather operation in LLVM IR. If not
86 /// supported on the underlying platform, emulate it with loads
87 /// @param vSrc - SIMD wide value that will be loaded if mask is invalid
88 /// @param pBase - Int8* base VB address pointer value
89 /// @param vIndices - SIMD wide value of VB byte offsets
90 /// @param vMask - SIMD wide mask that controls whether to access memory or the src values
91 /// @param scale - value to scale indices by
92 Value
* BuilderGfxMem::GATHERDD(Value
* vSrc
,
99 // address may be coming in as 64bit int now so get the pointer
100 if (pBase
->getType() == mInt64Ty
)
102 pBase
= INT_TO_PTR(pBase
, PointerType::get(mInt8Ty
, 0));
105 Value
* vGather
= Builder::GATHERDD(vSrc
, pBase
, vIndices
, vMask
, scale
);
109 void BuilderGfxMem::SCATTERPS(
110 Value
* pDst
, Value
* vSrc
, Value
* vOffsets
, Value
* vMask
, MEM_CLIENT usage
)
112 // address may be coming in as 64bit int now so get the pointer
113 if (pDst
->getType() == mInt64Ty
)
115 pDst
= INT_TO_PTR(pDst
, PointerType::get(mInt8Ty
, 0));
118 Builder::SCATTERPS(pDst
, BITCAST(vSrc
, mSimdFP32Ty
), vOffsets
, vMask
, usage
);
121 Value
* BuilderGfxMem::OFFSET_TO_NEXT_COMPONENT(Value
* base
, Constant
* offset
)
123 return ADD(base
, offset
);
126 Value
* BuilderGfxMem::GEP(Value
* Ptr
, Value
* Idx
, Type
* Ty
, const Twine
& Name
)
128 Ptr
= TranslationHelper(Ptr
, Ty
);
129 return Builder::GEP(Ptr
, Idx
, nullptr, Name
);
132 Value
* BuilderGfxMem::GEP(Type
* Ty
, Value
* Ptr
, Value
* Idx
, const Twine
& Name
)
134 Ptr
= TranslationHelper(Ptr
, Ty
);
135 return Builder::GEP(Ty
, Ptr
, Idx
, Name
);
138 Value
* BuilderGfxMem::GEP(Value
* Ptr
, const std::initializer_list
<Value
*>& indexList
, Type
* Ty
)
140 Ptr
= TranslationHelper(Ptr
, Ty
);
141 return Builder::GEP(Ptr
, indexList
);
145 BuilderGfxMem::GEP(Value
* Ptr
, const std::initializer_list
<uint32_t>& indexList
, Type
* Ty
)
147 Ptr
= TranslationHelper(Ptr
, Ty
);
148 return Builder::GEP(Ptr
, indexList
);
151 Value
* BuilderGfxMem::TranslationHelper(Value
* Ptr
, Type
* Ty
)
153 SWR_ASSERT(!(Ptr
->getType() == mInt64Ty
&& Ty
== nullptr),
154 "Access of GFX pointers must have non-null type specified.");
156 // address may be coming in as 64bit int now so get the pointer
157 if (Ptr
->getType() == mInt64Ty
)
159 Ptr
= INT_TO_PTR(Ptr
, Ty
);
165 void BuilderGfxMem::TrackerHelper(Value
* Ptr
, Type
* Ty
, MEM_CLIENT usage
, bool isRead
)
167 #if defined(KNOB_ENABLE_AR)
168 if (!KNOB_TRACK_MEMORY_WORKING_SET
)
174 // convert actual pointers to int64.
177 if (Ptr
->getType() == mInt64Ty
)
179 DataLayout
dataLayout(JM()->mpCurrentModule
);
180 size
= (uint32_t)dataLayout
.getTypeAllocSize(Ty
);
186 DataLayout
dataLayout(JM()->mpCurrentModule
);
187 size
= (uint32_t)dataLayout
.getTypeAllocSize(Ptr
->getType());
189 tmpPtr
= PTR_TO_INT(Ptr
, mInt64Ty
);
192 // There are some shader compile setups where there's no translation functions set up.
193 // This would be a situation where the accesses are to internal rasterizer memory and won't
195 // TODO: we may wish to revisit this for URB reads/writes, though.
196 if (mpfnTrackMemAccess
)
198 SWR_ASSERT(mpWorkerData
!= nullptr);
199 CALL(mpfnTrackMemAccess
,
205 C((uint32_t)usage
)});
212 LoadInst
* BuilderGfxMem::LOAD(Value
* Ptr
, const char* Name
, Type
* Ty
, MEM_CLIENT usage
)
214 AssertGFXMemoryParams(Ptr
, usage
);
215 TrackerHelper(Ptr
, Ty
, usage
, true);
217 Ptr
= TranslationHelper(Ptr
, Ty
);
218 return Builder::LOAD(Ptr
, Name
);
221 LoadInst
* BuilderGfxMem::LOAD(Value
* Ptr
, const Twine
& Name
, Type
* Ty
, MEM_CLIENT usage
)
223 AssertGFXMemoryParams(Ptr
, usage
);
224 TrackerHelper(Ptr
, Ty
, usage
, true);
226 Ptr
= TranslationHelper(Ptr
, Ty
);
227 return Builder::LOAD(Ptr
, Name
);
230 LoadInst
* BuilderGfxMem::LOAD(
231 Value
* Ptr
, bool isVolatile
, const Twine
& Name
, Type
* Ty
, MEM_CLIENT usage
)
233 AssertGFXMemoryParams(Ptr
, usage
);
234 TrackerHelper(Ptr
, Ty
, usage
, true);
236 Ptr
= TranslationHelper(Ptr
, Ty
);
237 return Builder::LOAD(Ptr
, isVolatile
, Name
);
240 LoadInst
* BuilderGfxMem::LOAD(Value
* BasePtr
,
241 const std::initializer_list
<uint32_t>& offset
,
242 const llvm::Twine
& name
,
246 AssertGFXMemoryParams(BasePtr
, usage
);
248 bool bNeedTranslation
= false;
249 if (BasePtr
->getType() == mInt64Ty
)
252 BasePtr
= INT_TO_PTR(BasePtr
, Ty
, name
);
253 bNeedTranslation
= true;
255 std::vector
<Value
*> valIndices
;
256 for (auto i
: offset
)
258 valIndices
.push_back(C(i
));
260 BasePtr
= Builder::GEPA(BasePtr
, valIndices
, name
);
261 if (bNeedTranslation
)
263 BasePtr
= PTR_TO_INT(BasePtr
, mInt64Ty
, name
);
266 return LOAD(BasePtr
, name
, Ty
, usage
);
269 CallInst
* BuilderGfxMem::MASKED_LOAD(Value
* Ptr
,
277 AssertGFXMemoryParams(Ptr
, usage
);
278 TrackerHelper(Ptr
, Ty
, usage
, true);
280 Ptr
= TranslationHelper(Ptr
, Ty
);
281 return Builder::MASKED_LOAD(Ptr
, Align
, Mask
, PassThru
, Name
, Ty
, usage
);
285 BuilderGfxMem::STORE(Value
* Val
, Value
* Ptr
, bool isVolatile
, Type
* Ty
, MEM_CLIENT usage
)
287 AssertGFXMemoryParams(Ptr
, usage
);
288 TrackerHelper(Ptr
, Ty
, usage
, false);
290 Ptr
= TranslationHelper(Ptr
, Ty
);
291 return Builder::STORE(Val
, Ptr
, isVolatile
, Ty
, usage
);
294 StoreInst
* BuilderGfxMem::STORE(Value
* Val
,
296 const std::initializer_list
<uint32_t>& offset
,
300 AssertGFXMemoryParams(BasePtr
, usage
);
301 TrackerHelper(BasePtr
, Ty
, usage
, false);
303 BasePtr
= TranslationHelper(BasePtr
, Ty
);
304 return Builder::STORE(Val
, BasePtr
, offset
, Ty
, usage
);
307 CallInst
* BuilderGfxMem::MASKED_STORE(
308 Value
* Val
, Value
* Ptr
, unsigned Align
, Value
* Mask
, Type
* Ty
, MEM_CLIENT usage
)
310 AssertGFXMemoryParams(Ptr
, usage
);
312 TrackerHelper(Ptr
, Ty
, usage
, false);
314 Ptr
= TranslationHelper(Ptr
, Ty
);
315 return Builder::MASKED_STORE(Val
, Ptr
, Align
, Mask
, Ty
, usage
);
318 Value
* BuilderGfxMem::TranslateGfxAddressForRead(Value
* xpGfxAddress
,
321 MEM_CLIENT
/* usage */)
323 if (PtrTy
== nullptr)
327 return INT_TO_PTR(xpGfxAddress
, PtrTy
, Name
);
330 Value
* BuilderGfxMem::TranslateGfxAddressForWrite(Value
* xpGfxAddress
,
333 MEM_CLIENT
/* usage */)
335 if (PtrTy
== nullptr)
339 return INT_TO_PTR(xpGfxAddress
, PtrTy
, Name
);
342 } // namespace SwrJit