DirectXShaderCompiler/lib/HLSL/DxilNoOptLegalize.cpp

148 строки
4.4 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// //
// DxilNoOptLegalize.cpp //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "dxc/HLSL/DxilGenerationPass.h"
#include "dxc/HLSL/DxilNoops.h"
#include "dxc/Support/Global.h"
#include "llvm/Analysis/DxilValueCache.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
using namespace llvm;
class DxilNoOptLegalize : public ModulePass {
SmallVector<Value *, 16> Worklist;
public:
static char ID;
DxilNoOptLegalize() : ModulePass(ID) {
initializeDxilNoOptLegalizePass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override;
bool RemoveStoreUndefsFromPtr(Value *V);
bool RemoveStoreUndefs(Module &M);
};
char DxilNoOptLegalize::ID;
bool DxilNoOptLegalize::RemoveStoreUndefsFromPtr(Value *Ptr) {
bool Changed = false;
Worklist.clear();
Worklist.push_back(Ptr);
while (Worklist.size()) {
Value *V = Worklist.back();
Worklist.pop_back();
if (isa<AllocaInst>(V) || isa<GlobalVariable>(V) || isa<GEPOperator>(V)) {
for (User *U : V->users())
Worklist.push_back(U);
} else if (StoreInst *Store = dyn_cast<StoreInst>(V)) {
if (isa<UndefValue>(Store->getValueOperand())) {
Store->eraseFromParent();
Changed = true;
}
}
}
return Changed;
}
bool DxilNoOptLegalize::RemoveStoreUndefs(Module &M) {
bool Changed = false;
for (GlobalVariable &GV : M.globals()) {
Changed |= RemoveStoreUndefsFromPtr(&GV);
}
for (Function &F : M) {
if (F.empty())
continue;
BasicBlock &Entry = F.getEntryBlock();
for (Instruction &I : Entry) {
if (isa<AllocaInst>(&I))
Changed |= RemoveStoreUndefsFromPtr(&I);
}
}
return Changed;
}
bool DxilNoOptLegalize::runOnModule(Module &M) {
bool Changed = false;
Changed |= RemoveStoreUndefs(M);
return Changed;
}
ModulePass *llvm::createDxilNoOptLegalizePass() {
return new DxilNoOptLegalize();
}
INITIALIZE_PASS(DxilNoOptLegalize, "dxil-o0-legalize", "DXIL No-Opt Legalize",
false, false)
class DxilNoOptSimplifyInstructions : public ModulePass {
SmallVector<Value *, 16> Worklist;
public:
static char ID;
DxilNoOptSimplifyInstructions() : ModulePass(ID) {
initializeDxilNoOptSimplifyInstructionsPass(
*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<DxilValueCache>();
}
bool runOnModule(Module &M) override {
bool Changed = false;
DxilValueCache *DVC = &getAnalysis<DxilValueCache>();
for (Function &F : M) {
for (BasicBlock &BB : F) {
for (auto it = BB.begin(), end = BB.end(); it != end;) {
Instruction *I = &*(it++);
if (I->getOpcode() == Instruction::Select) {
if (hlsl::IsPreserve(I))
continue;
if (Value *C = DVC->GetValue(I)) {
I->replaceAllUsesWith(C);
I->eraseFromParent();
Changed = true;
}
} else if (PHINode *Phi = dyn_cast<PHINode>(I)) {
// Replace all simple phi values (such as those inserted by lcssa)
// with the value itself. This avoids phis in places they are not
// expected because the normal simplify passes will clean them up.
if (Value *NewPhi =
llvm::SimplifyInstruction(Phi, M.getDataLayout())) {
Phi->replaceAllUsesWith(NewPhi);
Phi->eraseFromParent();
Changed = true;
}
}
}
}
}
return Changed;
}
};
char DxilNoOptSimplifyInstructions::ID;
ModulePass *llvm::createDxilNoOptSimplifyInstructionsPass() {
return new DxilNoOptSimplifyInstructions();
}
INITIALIZE_PASS(DxilNoOptSimplifyInstructions, "dxil-o0-simplify-inst",
"DXIL No-Opt Simplify Inst", false, false)