Keep debug info for handle created by local resource. (#61)

* Keep debug info for handle created by local resource.

* Add IsResourceAlloc to share code.
This commit is contained in:
Xiang Li 2017-02-02 17:00:39 -08:00 коммит произвёл GitHub
Родитель 3c7734c7da
Коммит 199aa5a0b5
3 изменённых файлов: 101 добавлений и 16 удалений

Просмотреть файл

@ -106,8 +106,46 @@ public:
// Mark handle map.
// If cannot find, will return false in run();
if (Instruction *I = dyn_cast<Instruction>(V)) {
if (handleMap.count(I))
handleMap[NewInst] = handleMap[I];
if (handleMap.count(I)) {
Instruction *handle = cast<Instruction>(handleMap[I]);
// Clone the handle to save debug info of LI.
handle = handle->clone();
Builder.Insert(handle);
handleMap[NewInst] = handle;
}
}
}
};
// Collect unused phi of resources and remove them.
class ResourceRemover : public LoadAndStorePromoter {
AllocaInst *AI;
mutable std::unordered_set<PHINode *> unusedPhis;
public:
ResourceRemover(ArrayRef<Instruction *> Insts, SSAUpdater &S)
: LoadAndStorePromoter(Insts, S), AI(nullptr) {}
void run(AllocaInst *AI, const SmallVectorImpl<Instruction *> &Insts) {
// Remember which alloca we're promoting (for isInstInList).
this->AI = AI;
LoadAndStorePromoter::run(Insts);
for (PHINode *P : unusedPhis) {
P->eraseFromParent();
}
}
bool
isInstInList(Instruction *I,
const SmallVectorImpl<Instruction *> &Insts) const override {
if (LoadInst *LI = dyn_cast<LoadInst>(I))
return LI->getOperand(0) == AI;
return cast<StoreInst>(I)->getPointerOperand() == AI;
}
void replaceLoadWithValue(LoadInst *LI, Value *V) const override {
if (PHINode *PHI = dyn_cast<PHINode>(V)) {
if (PHI->user_empty())
unusedPhis.insert(PHI);
}
}
};
@ -315,6 +353,16 @@ public:
GenerateDxilOperations(M, handleMap);
if (NotOptimized || m_HasDbgInfo) {
// For module which not promote mem2reg.
// Remove local resource alloca/load/store/phi.
Module &M = *m_pHLModule->GetModule();
for (Function &F : M.functions()) {
if (!F.isDeclaration())
RemoveLocalDxilResourceAllocas(&F);
}
}
// Translate precise on allocas into function call to keep the information after mem2reg.
// The function calls will be removed after propagate precise attribute.
TranslatePreciseAttribute();
@ -351,6 +399,7 @@ private:
bool HasClipPlanes();
void TranslateLocalDxilResourceUses(Function *F, std::unordered_map<Instruction *, Value *> &handleMap);
void RemoveLocalDxilResourceAllocas(Function *F);
void MapLocalDxilResourceHandles(
std::unordered_map<Instruction *, Value *> &handleMap);
void TranslateDxilResourceUses(
@ -1778,24 +1827,27 @@ static void AddCreateHandleForPhiNode(std::unordered_map<Instruction *, Value *>
}
}
static bool IsResourceAlloc(AllocaInst *AI) {
bool isResource = HLModule::IsHLSLObjectType(AI->getAllocatedType());
if (ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType())) {
Type *EltTy = AT->getElementType();
while (isa<ArrayType>(EltTy)) {
EltTy = EltTy->getArrayElementType();
}
isResource = HLModule::IsHLSLObjectType(EltTy);
// TODO: support local resource array.
DXASSERT(!isResource, "local resource array");
}
return isResource;
}
void DxilGenerationPass::TranslateLocalDxilResourceUses(Function *F, std::unordered_map<Instruction *, Value *> &handleMap) {
BasicBlock &BB = F->getEntryBlock(); // Get the entry node for the function
std::unordered_set<AllocaInst *> localResources;
for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I)
if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) { // Is it an alloca?
bool isResource = HLModule::IsHLSLObjectType(AI->getAllocatedType());
if (ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType())) {
Type *EltTy = AT->getElementType();
while (isa<ArrayType>(EltTy)) {
EltTy = EltTy->getArrayElementType();
}
isResource = HLModule::IsHLSLObjectType(EltTy);
// TODO: support local resource array.
DXASSERT(!isResource, "local resource array");
}
if (isResource) {
if (IsResourceAlloc(AI)) {
localResources.insert(AI);
}
}
@ -1820,6 +1872,30 @@ void DxilGenerationPass::TranslateLocalDxilResourceUses(Function *F, std::unorde
}
}
void DxilGenerationPass::RemoveLocalDxilResourceAllocas(Function *F) {
BasicBlock &BB = F->getEntryBlock(); // Get the entry node for the function
std::unordered_set<AllocaInst *> localResources;
for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I)
if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) { // Is it an alloca?
if (IsResourceAlloc(AI)) {
localResources.insert(AI);
}
}
SSAUpdater SSA;
SmallVector<Instruction *, 4> Insts;
for (AllocaInst *AI : localResources) {
// Build list of instructions to promote.
for (User *U : AI->users())
Insts.emplace_back(cast<Instruction>(U));
ResourceRemover(Insts, SSA).run(AI, Insts);
Insts.clear();
}
}
void DxilGenerationPass::MapLocalDxilResourceHandles(
std::unordered_map<Instruction *, Value *> &handleMap) {
Module &M = *m_pHLModule->GetModule();

Просмотреть файл

@ -1,4 +1,8 @@
// RUN: %dxc -E main -T cs_6_0 %s
// RUN: %dxc -E main -Zi -Od -T cs_6_0 %s | FileCheck %s
// Make sure createHandle has debug info.
// CHECK: @dx.op.createHandle(i32 59, i8 1, i32 0, i32 0, i1 false), !dbg
// CHECK: @dx.op.createHandle(i32 59, i8 1, i32 1, i32 1, i1 false), !dbg
RWBuffer<uint> uav1;
RWBuffer<uint> uav2;

Просмотреть файл

@ -557,6 +557,7 @@ public:
TEST_METHOD(CodeGenBindings1)
TEST_METHOD(CodeGenBindings2)
TEST_METHOD(CodeGenBindings3)
TEST_METHOD(CodeGenResCopy)
TEST_METHOD(CodeGenResourceInStruct)
TEST_METHOD(CodeGenResourceInCB)
TEST_METHOD(CodeGenResourceInCBV)
@ -2732,6 +2733,10 @@ TEST_F(CompilerTest, CodeGenBindings3) {
CodeGenTestCheck(L"..\\CodeGenHLSL\\bindings2.hlsl");
}
TEST_F(CompilerTest, CodeGenResCopy) {
CodeGenTestCheck(L"..\\CodeGenHLSL\\resCopy.hlsl");
}
TEST_F(CompilerTest, CodeGenResourceInStruct) {
CodeGenTestCheck(L"..\\CodeGenHLSL\\resource-in-struct.hlsl");
}