Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/jitter/builder_gfx_mem.cpp
4574 views
/****************************************************************************1* Copyright (C) 2014-2018 Intel Corporation. All Rights Reserved.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22* @file builder_gfx_mem.cpp23*24* @brief Definition of the gfx mem builder25*26* Notes:27*28******************************************************************************/29#include "jit_pch.hpp"30#include "builder.h"31#include "common/rdtsc_buckets.h"32#include "builder_gfx_mem.h"3334namespace SwrJit35{36using namespace llvm;3738BuilderGfxMem::BuilderGfxMem(JitManager* pJitMgr) : Builder(pJitMgr)39{40mpTranslationFuncTy = nullptr;41mpfnTranslateGfxAddressForRead = nullptr;42mpfnTranslateGfxAddressForWrite = nullptr;43mpfnTrackMemAccess = nullptr;44mpParamSimDC = nullptr;45mpWorkerData = nullptr;4647}4849void BuilderGfxMem::NotifyPrivateContextSet()50{51}5253void BuilderGfxMem::AssertGFXMemoryParams(Value* ptr, MEM_CLIENT usage)54{55SWR_ASSERT(!(ptr->getType() == mInt64Ty && usage == MEM_CLIENT::MEM_CLIENT_INTERNAL),56"Internal memory should not be gfxptr_t.");57}5859//////////////////////////////////////////////////////////////////////////60/// @brief Generate a masked gather operation in LLVM IR. If not61/// supported on the underlying platform, emulate it with loads62/// @param vSrc - SIMD wide value that will be loaded if mask is invalid63/// @param pBase - Int8* base VB address pointer value64/// @param vIndices - SIMD wide value of VB byte offsets65/// @param vMask - SIMD wide mask that controls whether to access memory or the src values66/// @param scale - value to scale indices by67Value* BuilderGfxMem::GATHERPS(Value* vSrc,68Value* pBase,69Value* vIndices,70Value* vMask,71uint8_t scale,72MEM_CLIENT usage)73{74// address may be coming in as 64bit int now so get the pointer75if (pBase->getType() == mInt64Ty)76{77pBase = INT_TO_PTR(pBase, PointerType::get(mInt8Ty, 0));78}7980Value* vGather = Builder::GATHERPS(vSrc, pBase, vIndices, vMask, scale);81return vGather;82}8384//////////////////////////////////////////////////////////////////////////85/// @brief Generate a masked gather operation in LLVM IR. If not86/// supported on the underlying platform, emulate it with loads87/// @param vSrc - SIMD wide value that will be loaded if mask is invalid88/// @param pBase - Int8* base VB address pointer value89/// @param vIndices - SIMD wide value of VB byte offsets90/// @param vMask - SIMD wide mask that controls whether to access memory or the src values91/// @param scale - value to scale indices by92Value* BuilderGfxMem::GATHERDD(Value* vSrc,93Value* pBase,94Value* vIndices,95Value* vMask,96uint8_t scale,97MEM_CLIENT usage)98{99100// address may be coming in as 64bit int now so get the pointer101if (pBase->getType() == mInt64Ty)102{103pBase = INT_TO_PTR(pBase, PointerType::get(mInt8Ty, 0));104}105106Value* vGather = Builder::GATHERDD(vSrc, pBase, vIndices, vMask, scale);107return vGather;108}109110void BuilderGfxMem::SCATTERPS(111Value* pDst, Value* vSrc, Value* vOffsets, Value* vMask, MEM_CLIENT usage)112{113114// address may be coming in as 64bit int now so get the pointer115if (pDst->getType() == mInt64Ty)116{117pDst = INT_TO_PTR(pDst, PointerType::get(mInt8Ty, 0));118}119120Builder::SCATTERPS(pDst, BITCAST(vSrc, mSimdFP32Ty), vOffsets, vMask, usage);121}122123Value* BuilderGfxMem::OFFSET_TO_NEXT_COMPONENT(Value* base, Constant* offset)124{125return ADD(base, offset);126}127128Value* BuilderGfxMem::GEP(Value* Ptr, Value* Idx, Type* Ty, bool isReadOnly, const Twine& Name)129{130bool xlate = (Ptr->getType() == mInt64Ty);131if (xlate)132{133Ptr = INT_TO_PTR(Ptr, Ty);134Ptr = Builder::GEP(Ptr, Idx, nullptr, isReadOnly, Name);135Ptr = PTR_TO_INT(Ptr, mInt64Ty);136if (isReadOnly)137{138Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);139}140else141{142Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForWrite);143}144}145else146{147Ptr = Builder::GEP(Ptr, Idx, nullptr, isReadOnly, Name);148}149return Ptr;150}151152Value* BuilderGfxMem::GEP(Type* Ty, Value* Ptr, Value* Idx, const Twine& Name)153{154bool xlate = (Ptr->getType() == mInt64Ty);155if (xlate)156{157Ptr = INT_TO_PTR(Ptr, Ty);158Ptr = Builder::GEP(Ty, Ptr, Idx, Name);159Ptr = PTR_TO_INT(Ptr, mInt64Ty);160Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);161}162else163{164Ptr = Builder::GEP(Ty, Ptr, Idx, Name);165}166return Ptr;167}168169Value* BuilderGfxMem::GEP(Value* Ptr, const std::initializer_list<Value*>& indexList, Type* Ty)170{171bool xlate = (Ptr->getType() == mInt64Ty);172if (xlate)173{174Ptr = INT_TO_PTR(Ptr, Ty);175Ptr = Builder::GEP(Ptr, indexList);176Ptr = PTR_TO_INT(Ptr, mInt64Ty);177Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);178}179else180{181Ptr = Builder::GEP(Ptr, indexList);182}183return Ptr;184}185186Value*187BuilderGfxMem::GEP(Value* Ptr, const std::initializer_list<uint32_t>& indexList, Type* Ty)188{189bool xlate = (Ptr->getType() == mInt64Ty);190if (xlate)191{192Ptr = INT_TO_PTR(Ptr, Ty);193Ptr = Builder::GEP(Ptr, indexList);194Ptr = PTR_TO_INT(Ptr, mInt64Ty);195Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);196}197else198{199Ptr = Builder::GEP(Ptr, indexList);200}201return Ptr;202}203204Value* BuilderGfxMem::TranslationHelper(Value* Ptr, Type* Ty, Value* pfnTranslateGfxAddress)205{206SWR_ASSERT(!(Ptr->getType() == mInt64Ty && Ty == nullptr),207"Access of GFX pointers must have non-null type specified.");208209// address may be coming in as 64bit int now so get the pointer210if (Ptr->getType() == mInt64Ty)211{212Ptr = INT_TO_PTR(Ptr, Ty);213}214215return Ptr;216}217218void BuilderGfxMem::TrackerHelper(Value* Ptr, Type* Ty, MEM_CLIENT usage, bool isRead)219{220#if defined(KNOB_ENABLE_AR)221if (!KNOB_AR_ENABLE_MEMORY_EVENTS)222{223return;224}225226Value* tmpPtr;227// convert actual pointers to int64.228uint32_t size = 0;229230if (Ptr->getType() == mInt64Ty)231{232DataLayout dataLayout(JM()->mpCurrentModule);233size = (uint32_t)dataLayout.getTypeAllocSize(Ty);234235tmpPtr = Ptr;236}237else238{239DataLayout dataLayout(JM()->mpCurrentModule);240size = (uint32_t)dataLayout.getTypeAllocSize(Ptr->getType());241242tmpPtr = PTR_TO_INT(Ptr, mInt64Ty);243}244245// There are some shader compile setups where there's no translation functions set up.246// This would be a situation where the accesses are to internal rasterizer memory and won't247// be logged.248// TODO: we may wish to revisit this for URB reads/writes, though.249if (mpfnTrackMemAccess)250{251SWR_ASSERT(mpWorkerData != nullptr);252CALL(mpfnTrackMemAccess,253{mpParamSimDC,254mpWorkerData,255tmpPtr,256C((uint32_t)size),257C((uint8_t)isRead),258C((uint32_t)usage)});259}260#endif261262return;263}264265LoadInst* BuilderGfxMem::LOAD(Value* Ptr, const char* Name, Type* Ty, MEM_CLIENT usage)266{267AssertGFXMemoryParams(Ptr, usage);268TrackerHelper(Ptr, Ty, usage, true);269270Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);271return Builder::LOAD(Ptr, Name);272}273274LoadInst* BuilderGfxMem::LOAD(Value* Ptr, const Twine& Name, Type* Ty, MEM_CLIENT usage)275{276AssertGFXMemoryParams(Ptr, usage);277TrackerHelper(Ptr, Ty, usage, true);278279Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);280return Builder::LOAD(Ptr, Name);281}282283LoadInst* BuilderGfxMem::LOAD(284Value* Ptr, bool isVolatile, const Twine& Name, Type* Ty, MEM_CLIENT usage)285{286AssertGFXMemoryParams(Ptr, usage);287TrackerHelper(Ptr, Ty, usage, true);288289Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);290return Builder::LOAD(Ptr, isVolatile, Name);291}292293LoadInst* BuilderGfxMem::LOAD(Value* BasePtr,294const std::initializer_list<uint32_t>& offset,295const llvm::Twine& name,296Type* Ty,297MEM_CLIENT usage)298{299AssertGFXMemoryParams(BasePtr, usage);300301bool bNeedTranslation = false;302if (BasePtr->getType() == mInt64Ty)303{304SWR_ASSERT(Ty);305BasePtr = INT_TO_PTR(BasePtr, Ty, name);306bNeedTranslation = true;307}308std::vector<Value*> valIndices;309for (auto i : offset)310{311valIndices.push_back(C(i));312}313BasePtr = Builder::GEPA(BasePtr, valIndices, name);314if (bNeedTranslation)315{316BasePtr = PTR_TO_INT(BasePtr, mInt64Ty, name);317}318319return LOAD(BasePtr, name, Ty, usage);320}321322CallInst* BuilderGfxMem::MASKED_LOAD(Value* Ptr,323unsigned Align,324Value* Mask,325Value* PassThru,326const Twine& Name,327Type* Ty,328MEM_CLIENT usage)329{330AssertGFXMemoryParams(Ptr, usage);331TrackerHelper(Ptr, Ty, usage, true);332333Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);334return Builder::MASKED_LOAD(Ptr, Align, Mask, PassThru, Name, Ty, usage);335}336337StoreInst*338BuilderGfxMem::STORE(Value* Val, Value* Ptr, bool isVolatile, Type* Ty, MEM_CLIENT usage)339{340AssertGFXMemoryParams(Ptr, usage);341TrackerHelper(Ptr, Ty, usage, false);342343Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);344return Builder::STORE(Val, Ptr, isVolatile, Ty, usage);345}346347StoreInst* BuilderGfxMem::STORE(Value* Val,348Value* BasePtr,349const std::initializer_list<uint32_t>& offset,350Type* Ty,351MEM_CLIENT usage)352{353AssertGFXMemoryParams(BasePtr, usage);354TrackerHelper(BasePtr, Ty, usage, false);355356BasePtr = TranslationHelper(BasePtr, Ty, mpfnTranslateGfxAddressForRead);357return Builder::STORE(Val, BasePtr, offset, Ty, usage);358}359360CallInst* BuilderGfxMem::MASKED_STORE(361Value* Val, Value* Ptr, unsigned Align, Value* Mask, Type* Ty, MEM_CLIENT usage)362{363AssertGFXMemoryParams(Ptr, usage);364365TrackerHelper(Ptr, Ty, usage, false);366367Ptr = TranslationHelper(Ptr, Ty, mpfnTranslateGfxAddressForRead);368return Builder::MASKED_STORE(Val, Ptr, Align, Mask, Ty, usage);369}370371Value* BuilderGfxMem::TranslateGfxAddressForRead(Value* xpGfxAddress,372Type* PtrTy,373const Twine& Name,374MEM_CLIENT /* usage */)375{376if (PtrTy == nullptr)377{378PtrTy = mInt8PtrTy;379}380return INT_TO_PTR(xpGfxAddress, PtrTy, Name);381}382383Value* BuilderGfxMem::TranslateGfxAddressForWrite(Value* xpGfxAddress,384Type* PtrTy,385const Twine& Name,386MEM_CLIENT /* usage */)387{388if (PtrTy == nullptr)389{390PtrTy = mInt8PtrTy;391}392return INT_TO_PTR(xpGfxAddress, PtrTy, Name);393}394395} // namespace SwrJit396397398