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;
50 void BuilderGfxMem::NotifyPrivateContextSet()
54 void BuilderGfxMem::AssertGFXMemoryParams(Value
* ptr
, MEM_CLIENT usage
)
56 SWR_ASSERT(!(ptr
->getType() == mInt64Ty
&& usage
== MEM_CLIENT::MEM_CLIENT_INTERNAL
),
57 "Internal memory should not be gfxptr_t.");
60 //////////////////////////////////////////////////////////////////////////
61 /// @brief Generate a masked gather operation in LLVM IR. If not
62 /// supported on the underlying platform, emulate it with loads
63 /// @param vSrc - SIMD wide value that will be loaded if mask is invalid
64 /// @param pBase - Int8* base VB address pointer value
65 /// @param vIndices - SIMD wide value of VB byte offsets
66 /// @param vMask - SIMD wide mask that controls whether to access memory or the src values
67 /// @param scale - value to scale indices by
68 Value
* BuilderGfxMem::GATHERPS(Value
* vSrc
,
75 // address may be coming in as 64bit int now so get the pointer
76 if (pBase
->getType() == mInt64Ty
)
78 pBase
= INT_TO_PTR(pBase
, PointerType::get(mInt8Ty
, 0));
81 Value
* vGather
= Builder::GATHERPS(vSrc
, pBase
, vIndices
, vMask
, scale
);
85 //////////////////////////////////////////////////////////////////////////
86 /// @brief Generate a masked gather operation in LLVM IR. If not
87 /// supported on the underlying platform, emulate it with loads
88 /// @param vSrc - SIMD wide value that will be loaded if mask is invalid
89 /// @param pBase - Int8* base VB address pointer value
90 /// @param vIndices - SIMD wide value of VB byte offsets
91 /// @param vMask - SIMD wide mask that controls whether to access memory or the src values
92 /// @param scale - value to scale indices by
93 Value
* BuilderGfxMem::GATHERDD(Value
* vSrc
,
101 // address may be coming in as 64bit int now so get the pointer
102 if (pBase
->getType() == mInt64Ty
)
104 pBase
= INT_TO_PTR(pBase
, PointerType::get(mInt8Ty
, 0));
107 Value
* vGather
= Builder::GATHERDD(vSrc
, pBase
, vIndices
, vMask
, scale
);
111 void BuilderGfxMem::SCATTERPS(
112 Value
* pDst
, Value
* vSrc
, Value
* vOffsets
, Value
* vMask
, MEM_CLIENT usage
)
115 // address may be coming in as 64bit int now so get the pointer
116 if (pDst
->getType() == mInt64Ty
)
118 pDst
= INT_TO_PTR(pDst
, PointerType::get(mInt8Ty
, 0));
121 Builder::SCATTERPS(pDst
, BITCAST(vSrc
, mSimdFP32Ty
), vOffsets
, vMask
, usage
);
124 Value
* BuilderGfxMem::OFFSET_TO_NEXT_COMPONENT(Value
* base
, Constant
* offset
)
126 return ADD(base
, offset
);
129 Value
* BuilderGfxMem::GEP(Value
* Ptr
, Value
* Idx
, Type
* Ty
, bool isReadOnly
, const Twine
& Name
)
131 bool xlate
= (Ptr
->getType() == mInt64Ty
);
134 Ptr
= INT_TO_PTR(Ptr
, Ty
);
135 Ptr
= Builder::GEP(Ptr
, Idx
, nullptr, isReadOnly
, Name
);
136 Ptr
= PTR_TO_INT(Ptr
, mInt64Ty
);
139 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
143 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForWrite
);
148 Ptr
= Builder::GEP(Ptr
, Idx
, nullptr, isReadOnly
, Name
);
153 Value
* BuilderGfxMem::GEP(Type
* Ty
, Value
* Ptr
, Value
* Idx
, const Twine
& Name
)
155 bool xlate
= (Ptr
->getType() == mInt64Ty
);
158 Ptr
= INT_TO_PTR(Ptr
, Ty
);
159 Ptr
= Builder::GEP(Ty
, Ptr
, Idx
, Name
);
160 Ptr
= PTR_TO_INT(Ptr
, mInt64Ty
);
161 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
165 Ptr
= Builder::GEP(Ty
, Ptr
, Idx
, Name
);
170 Value
* BuilderGfxMem::GEP(Value
* Ptr
, const std::initializer_list
<Value
*>& indexList
, Type
* Ty
)
172 bool xlate
= (Ptr
->getType() == mInt64Ty
);
175 Ptr
= INT_TO_PTR(Ptr
, Ty
);
176 Ptr
= Builder::GEP(Ptr
, indexList
);
177 Ptr
= PTR_TO_INT(Ptr
, mInt64Ty
);
178 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
182 Ptr
= Builder::GEP(Ptr
, indexList
);
188 BuilderGfxMem::GEP(Value
* Ptr
, const std::initializer_list
<uint32_t>& indexList
, Type
* Ty
)
190 bool xlate
= (Ptr
->getType() == mInt64Ty
);
193 Ptr
= INT_TO_PTR(Ptr
, Ty
);
194 Ptr
= Builder::GEP(Ptr
, indexList
);
195 Ptr
= PTR_TO_INT(Ptr
, mInt64Ty
);
196 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
200 Ptr
= Builder::GEP(Ptr
, indexList
);
205 Value
* BuilderGfxMem::TranslationHelper(Value
* Ptr
, Type
* Ty
, Value
* pfnTranslateGfxAddress
)
207 SWR_ASSERT(!(Ptr
->getType() == mInt64Ty
&& Ty
== nullptr),
208 "Access of GFX pointers must have non-null type specified.");
210 // address may be coming in as 64bit int now so get the pointer
211 if (Ptr
->getType() == mInt64Ty
)
213 Ptr
= INT_TO_PTR(Ptr
, Ty
);
219 void BuilderGfxMem::TrackerHelper(Value
* Ptr
, Type
* Ty
, MEM_CLIENT usage
, bool isRead
)
221 #if defined(KNOB_ENABLE_AR)
222 if (!KNOB_AR_ENABLE_MEMORY_EVENTS
)
228 // convert actual pointers to int64.
231 if (Ptr
->getType() == mInt64Ty
)
233 DataLayout
dataLayout(JM()->mpCurrentModule
);
234 size
= (uint32_t)dataLayout
.getTypeAllocSize(Ty
);
240 DataLayout
dataLayout(JM()->mpCurrentModule
);
241 size
= (uint32_t)dataLayout
.getTypeAllocSize(Ptr
->getType());
243 tmpPtr
= PTR_TO_INT(Ptr
, mInt64Ty
);
246 // There are some shader compile setups where there's no translation functions set up.
247 // This would be a situation where the accesses are to internal rasterizer memory and won't
249 // TODO: we may wish to revisit this for URB reads/writes, though.
250 if (mpfnTrackMemAccess
)
252 SWR_ASSERT(mpWorkerData
!= nullptr);
253 CALL(mpfnTrackMemAccess
,
259 C((uint32_t)usage
)});
266 LoadInst
* BuilderGfxMem::LOAD(Value
* Ptr
, const char* Name
, Type
* Ty
, MEM_CLIENT usage
)
268 AssertGFXMemoryParams(Ptr
, usage
);
269 TrackerHelper(Ptr
, Ty
, usage
, true);
271 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
272 return Builder::LOAD(Ptr
, Name
);
275 LoadInst
* BuilderGfxMem::LOAD(Value
* Ptr
, const Twine
& Name
, Type
* Ty
, MEM_CLIENT usage
)
277 AssertGFXMemoryParams(Ptr
, usage
);
278 TrackerHelper(Ptr
, Ty
, usage
, true);
280 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
281 return Builder::LOAD(Ptr
, Name
);
284 LoadInst
* BuilderGfxMem::LOAD(
285 Value
* Ptr
, bool isVolatile
, const Twine
& Name
, Type
* Ty
, MEM_CLIENT usage
)
287 AssertGFXMemoryParams(Ptr
, usage
);
288 TrackerHelper(Ptr
, Ty
, usage
, true);
290 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
291 return Builder::LOAD(Ptr
, isVolatile
, Name
);
294 LoadInst
* BuilderGfxMem::LOAD(Value
* BasePtr
,
295 const std::initializer_list
<uint32_t>& offset
,
296 const llvm::Twine
& name
,
300 AssertGFXMemoryParams(BasePtr
, usage
);
302 bool bNeedTranslation
= false;
303 if (BasePtr
->getType() == mInt64Ty
)
306 BasePtr
= INT_TO_PTR(BasePtr
, Ty
, name
);
307 bNeedTranslation
= true;
309 std::vector
<Value
*> valIndices
;
310 for (auto i
: offset
)
312 valIndices
.push_back(C(i
));
314 BasePtr
= Builder::GEPA(BasePtr
, valIndices
, name
);
315 if (bNeedTranslation
)
317 BasePtr
= PTR_TO_INT(BasePtr
, mInt64Ty
, name
);
320 return LOAD(BasePtr
, name
, Ty
, usage
);
323 CallInst
* BuilderGfxMem::MASKED_LOAD(Value
* Ptr
,
331 AssertGFXMemoryParams(Ptr
, usage
);
332 TrackerHelper(Ptr
, Ty
, usage
, true);
334 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
335 return Builder::MASKED_LOAD(Ptr
, Align
, Mask
, PassThru
, Name
, Ty
, usage
);
339 BuilderGfxMem::STORE(Value
* Val
, Value
* Ptr
, bool isVolatile
, Type
* Ty
, MEM_CLIENT usage
)
341 AssertGFXMemoryParams(Ptr
, usage
);
342 TrackerHelper(Ptr
, Ty
, usage
, false);
344 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
345 return Builder::STORE(Val
, Ptr
, isVolatile
, Ty
, usage
);
348 StoreInst
* BuilderGfxMem::STORE(Value
* Val
,
350 const std::initializer_list
<uint32_t>& offset
,
354 AssertGFXMemoryParams(BasePtr
, usage
);
355 TrackerHelper(BasePtr
, Ty
, usage
, false);
357 BasePtr
= TranslationHelper(BasePtr
, Ty
, mpfnTranslateGfxAddressForRead
);
358 return Builder::STORE(Val
, BasePtr
, offset
, Ty
, usage
);
361 CallInst
* BuilderGfxMem::MASKED_STORE(
362 Value
* Val
, Value
* Ptr
, unsigned Align
, Value
* Mask
, Type
* Ty
, MEM_CLIENT usage
)
364 AssertGFXMemoryParams(Ptr
, usage
);
366 TrackerHelper(Ptr
, Ty
, usage
, false);
368 Ptr
= TranslationHelper(Ptr
, Ty
, mpfnTranslateGfxAddressForRead
);
369 return Builder::MASKED_STORE(Val
, Ptr
, Align
, Mask
, Ty
, usage
);
372 Value
* BuilderGfxMem::TranslateGfxAddressForRead(Value
* xpGfxAddress
,
375 MEM_CLIENT
/* usage */)
377 if (PtrTy
== nullptr)
381 return INT_TO_PTR(xpGfxAddress
, PtrTy
, Name
);
384 Value
* BuilderGfxMem::TranslateGfxAddressForWrite(Value
* xpGfxAddress
,
387 MEM_CLIENT
/* usage */)
389 if (PtrTy
== nullptr)
393 return INT_TO_PTR(xpGfxAddress
, PtrTy
, Name
);
396 } // namespace SwrJit