|
@@ -20,6 +20,7 @@
|
|
|
#include "dxc/HLSL/DxilTypeSystem.h"
|
|
|
#include "dxc/HLSL/HLOperationLower.h"
|
|
|
#include "HLSignatureLower.h"
|
|
|
+#include "dxc/HLSL/DxilUtil.h"
|
|
|
|
|
|
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
|
|
#include "llvm/IR/IRBuilder.h"
|
|
@@ -31,7 +32,6 @@
|
|
|
#include "llvm/IR/PassManager.h"
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
|
#include "llvm/Pass.h"
|
|
|
-#include "llvm/Transforms/Utils/Local.h"
|
|
|
#include "llvm/Transforms/Utils/SSAUpdater.h"
|
|
|
#include "llvm/Analysis/AssumptionCache.h"
|
|
|
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
|
|
@@ -328,33 +328,6 @@ private:
|
|
|
// Input module is not optimized.
|
|
|
bool NotOptimized;
|
|
|
};
|
|
|
-
|
|
|
-class SimplifyInst : public FunctionPass {
|
|
|
-public:
|
|
|
- static char ID;
|
|
|
-
|
|
|
- SimplifyInst() : FunctionPass(ID) {
|
|
|
- initializeScalarizerPass(*PassRegistry::getPassRegistry());
|
|
|
- }
|
|
|
-
|
|
|
- bool runOnFunction(Function &F) override;
|
|
|
-
|
|
|
-private:
|
|
|
-};
|
|
|
-}
|
|
|
-
|
|
|
-char SimplifyInst::ID = 0;
|
|
|
-
|
|
|
-FunctionPass *llvm::createSimplifyInstPass() { return new SimplifyInst(); }
|
|
|
-
|
|
|
-INITIALIZE_PASS(SimplifyInst, "simplify-inst", "Simplify Instructions", false, false)
|
|
|
-
|
|
|
-bool SimplifyInst::runOnFunction(Function &F) {
|
|
|
- for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
|
|
|
- BasicBlock *BB = BBI;
|
|
|
- llvm::SimplifyInstructionsInBlock(BB, nullptr);
|
|
|
- }
|
|
|
- return true;
|
|
|
}
|
|
|
|
|
|
static Value *MergeImmResClass(Value *resClass) {
|
|
@@ -1329,306 +1302,6 @@ ModulePass *llvm::createHLEnsureMetadataPass() {
|
|
|
|
|
|
INITIALIZE_PASS(HLEnsureMetadata, "hlsl-hlensure", "HLSL High-Level Metadata Ensure", false, false)
|
|
|
|
|
|
-///////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-namespace {
|
|
|
-class DxilLoadMetadata : public ModulePass {
|
|
|
-public:
|
|
|
- static char ID; // Pass identification, replacement for typeid
|
|
|
- explicit DxilLoadMetadata () : ModulePass(ID) {}
|
|
|
-
|
|
|
- const char *getPassName() const override { return "HLSL load DxilModule from metadata"; }
|
|
|
-
|
|
|
- bool runOnModule(Module &M) override {
|
|
|
- if (!M.HasDxilModule()) {
|
|
|
- (void)M.GetOrCreateDxilModule();
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-};
|
|
|
-}
|
|
|
-
|
|
|
-char DxilLoadMetadata::ID = 0;
|
|
|
-
|
|
|
-ModulePass *llvm::createDxilLoadMetadataPass() {
|
|
|
- return new DxilLoadMetadata();
|
|
|
-}
|
|
|
-
|
|
|
-INITIALIZE_PASS(DxilLoadMetadata, "hlsl-dxilload", "HLSL load DxilModule from metadata", false, false)
|
|
|
-
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-namespace {
|
|
|
-
|
|
|
-Function *StripFunctionParameter(Function *F, DxilModule &DM,
|
|
|
- DenseMap<const Function *, DISubprogram *> &FunctionDIs) {
|
|
|
- Module &M = *DM.GetModule();
|
|
|
- Type *VoidTy = Type::getVoidTy(M.getContext());
|
|
|
- FunctionType *FT = FunctionType::get(VoidTy, false);
|
|
|
- for (auto &arg : F->args()) {
|
|
|
- if (!arg.user_empty())
|
|
|
- return nullptr;
|
|
|
- DbgDeclareInst *DDI = llvm::FindAllocaDbgDeclare(&arg);
|
|
|
- if (DDI) {
|
|
|
- DDI->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Function *NewFunc = Function::Create(FT, F->getLinkage());
|
|
|
- M.getFunctionList().insert(F, NewFunc);
|
|
|
- // Splice the body of the old function right into the new function.
|
|
|
- NewFunc->getBasicBlockList().splice(NewFunc->begin(), F->getBasicBlockList());
|
|
|
-
|
|
|
- // Patch the pointer to LLVM function in debug info descriptor.
|
|
|
- auto DI = FunctionDIs.find(F);
|
|
|
- if (DI != FunctionDIs.end()) {
|
|
|
- DISubprogram *SP = DI->second;
|
|
|
- SP->replaceFunction(NewFunc);
|
|
|
- // Ensure the map is updated so it can be reused on subsequent argument
|
|
|
- // promotions of the same function.
|
|
|
- FunctionDIs.erase(DI);
|
|
|
- FunctionDIs[NewFunc] = SP;
|
|
|
- }
|
|
|
- NewFunc->takeName(F);
|
|
|
- if (DM.HasDxilFunctionProps(F)) {
|
|
|
- DM.ReplaceDxilEntrySignature(F, NewFunc);
|
|
|
- DM.ReplaceDxilFunctionProps(F, NewFunc);
|
|
|
- }
|
|
|
-
|
|
|
- DM.GetTypeSystem().EraseFunctionAnnotation(F);
|
|
|
- F->eraseFromParent();
|
|
|
- DM.GetTypeSystem().AddFunctionAnnotation(NewFunc);
|
|
|
- return NewFunc;
|
|
|
-}
|
|
|
-
|
|
|
-void CheckInBoundForTGSM(GlobalVariable &GV, const DataLayout &DL) {
|
|
|
- for (User *U : GV.users()) {
|
|
|
- if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
|
|
|
- bool allImmIndex = true;
|
|
|
- for (auto Idx = GEP->idx_begin(), E = GEP->idx_end(); Idx != E; Idx++) {
|
|
|
- if (!isa<ConstantInt>(Idx)) {
|
|
|
- allImmIndex = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!allImmIndex)
|
|
|
- GEP->setIsInBounds(false);
|
|
|
- else {
|
|
|
- Value *Ptr = GEP->getPointerOperand();
|
|
|
- unsigned size =
|
|
|
- DL.getTypeAllocSize(Ptr->getType()->getPointerElementType());
|
|
|
- unsigned valSize =
|
|
|
- DL.getTypeAllocSize(GEP->getType()->getPointerElementType());
|
|
|
- SmallVector<Value *, 8> Indices(GEP->idx_begin(), GEP->idx_end());
|
|
|
- unsigned offset =
|
|
|
- DL.getIndexedOffset(GEP->getPointerOperandType(), Indices);
|
|
|
- if ((offset + valSize) > size)
|
|
|
- GEP->setIsInBounds(false);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class DxilEmitMetadata : public ModulePass {
|
|
|
-public:
|
|
|
- static char ID; // Pass identification, replacement for typeid
|
|
|
- explicit DxilEmitMetadata() : ModulePass(ID) {}
|
|
|
-
|
|
|
- const char *getPassName() const override { return "HLSL DXIL Metadata Emit"; }
|
|
|
-
|
|
|
- void patchValidation_1_1(Module &M) {
|
|
|
- for (iplist<Function>::iterator F : M.getFunctionList()) {
|
|
|
- for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE;
|
|
|
- ++BBI) {
|
|
|
- BasicBlock *BB = BBI;
|
|
|
- for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE;
|
|
|
- ++II) {
|
|
|
- Instruction *I = II;
|
|
|
- if (I->hasMetadataOtherThanDebugLoc()) {
|
|
|
- SmallVector<std::pair<unsigned, MDNode*>, 2> MDs;
|
|
|
- I->getAllMetadataOtherThanDebugLoc(MDs);
|
|
|
- for (auto &MD : MDs) {
|
|
|
- unsigned kind = MD.first;
|
|
|
- // Remove Metadata which validation_1_0 not allowed.
|
|
|
- bool bNeedPatch = kind == LLVMContext::MD_tbaa ||
|
|
|
- kind == LLVMContext::MD_prof ||
|
|
|
- (kind > LLVMContext::MD_fpmath &&
|
|
|
- kind <= LLVMContext::MD_dereferenceable_or_null);
|
|
|
- if (bNeedPatch)
|
|
|
- I->setMetadata(kind, nullptr);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- bool runOnModule(Module &M) override {
|
|
|
- if (M.HasDxilModule()) {
|
|
|
- DxilModule &DM = M.GetDxilModule();
|
|
|
- // Remove store undef output.
|
|
|
- hlsl::OP *hlslOP = M.GetDxilModule().GetOP();
|
|
|
- unsigned ValMajor = 0;
|
|
|
- unsigned ValMinor = 0;
|
|
|
- M.GetDxilModule().GetValidatorVersion(ValMajor, ValMinor);
|
|
|
- if (ValMajor == 1 && ValMinor <= 1) {
|
|
|
- patchValidation_1_1(M);
|
|
|
- }
|
|
|
- for (iplist<Function>::iterator F : M.getFunctionList()) {
|
|
|
- if (!hlslOP->IsDxilOpFunc(F))
|
|
|
- continue;
|
|
|
-
|
|
|
- // Check store output.
|
|
|
- FunctionType *FT = F->getFunctionType();
|
|
|
- // Num params not match.
|
|
|
- if (FT->getNumParams() !=
|
|
|
- (DXIL::OperandIndex::kStoreOutputValOpIdx + 1))
|
|
|
- continue;
|
|
|
-
|
|
|
- Type *overloadTy =
|
|
|
- FT->getParamType(DXIL::OperandIndex::kStoreOutputValOpIdx);
|
|
|
- // overload illegal.
|
|
|
- if (!hlslOP->IsOverloadLegal(DXIL::OpCode::StoreOutput, overloadTy))
|
|
|
- continue;
|
|
|
- Function *storeOutput =
|
|
|
- hlslOP->GetOpFunc(DXIL::OpCode::StoreOutput, overloadTy);
|
|
|
- // Not store output.
|
|
|
- if (storeOutput != F)
|
|
|
- continue;
|
|
|
-
|
|
|
- for (auto it = F->user_begin(); it != F->user_end();) {
|
|
|
- CallInst *CI = dyn_cast<CallInst>(*(it++));
|
|
|
- if (!CI)
|
|
|
- continue;
|
|
|
-
|
|
|
- Value *V =
|
|
|
- CI->getArgOperand(DXIL::OperandIndex::kStoreOutputValOpIdx);
|
|
|
- // Remove the store of undef.
|
|
|
- if (isa<UndefValue>(V))
|
|
|
- CI->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
- // Remove unused external functions.
|
|
|
- // For none library profile, remove unused functions except entry and
|
|
|
- // patchconstant function.
|
|
|
- Function *EntryFunc = DM.GetEntryFunction();
|
|
|
- Function *PatchConstantFunc = DM.GetPatchConstantFunction();
|
|
|
- bool IsLib = DM.GetShaderModel()->IsLib();
|
|
|
-
|
|
|
- std::vector<Function *> deadList;
|
|
|
- for (iplist<Function>::iterator F : M.getFunctionList()) {
|
|
|
- if (&(*F) == EntryFunc || &(*F) == PatchConstantFunc)
|
|
|
- continue;
|
|
|
- if (F->isDeclaration() || !IsLib) {
|
|
|
- if (F->user_empty())
|
|
|
- deadList.emplace_back(F);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (Function *F : deadList)
|
|
|
- F->eraseFromParent();
|
|
|
-
|
|
|
- // Remove unused internal global.
|
|
|
- std::vector<GlobalVariable *> staticGVs;
|
|
|
- for (GlobalVariable &GV : M.globals()) {
|
|
|
- if (HLModule::IsStaticGlobal(&GV) ||
|
|
|
- HLModule::IsSharedMemoryGlobal(&GV)) {
|
|
|
- staticGVs.emplace_back(&GV);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (GlobalVariable *GV : staticGVs) {
|
|
|
- bool onlyStoreUse = true;
|
|
|
- for (User *user : GV->users()) {
|
|
|
- if (isa<StoreInst>(user))
|
|
|
- continue;
|
|
|
- if (isa<ConstantExpr>(user) && user->user_empty())
|
|
|
- continue;
|
|
|
- onlyStoreUse = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- if (onlyStoreUse) {
|
|
|
- for (auto UserIt = GV->user_begin(); UserIt != GV->user_end();) {
|
|
|
- Value *User = *(UserIt++);
|
|
|
- if (Instruction *I = dyn_cast<Instruction>(User)) {
|
|
|
- I->eraseFromParent();
|
|
|
- } else {
|
|
|
- ConstantExpr *CE = cast<ConstantExpr>(User);
|
|
|
- CE->dropAllReferences();
|
|
|
- }
|
|
|
- }
|
|
|
- GV->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const DataLayout &DL = M.getDataLayout();
|
|
|
- // Clear inbound for GEP which has none-const index.
|
|
|
- for (GlobalVariable &GV : M.globals()) {
|
|
|
- if (HLModule::IsSharedMemoryGlobal(&GV)) {
|
|
|
- CheckInBoundForTGSM(GV, DL);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- DenseMap<const Function *, DISubprogram *> FunctionDIs =
|
|
|
- makeSubprogramMap(M);
|
|
|
- // Strip parameters of entry function.
|
|
|
- if (!IsLib) {
|
|
|
- if (Function *PatchConstantFunc = DM.GetPatchConstantFunction()) {
|
|
|
- PatchConstantFunc =
|
|
|
- StripFunctionParameter(PatchConstantFunc, DM, FunctionDIs);
|
|
|
- if (PatchConstantFunc)
|
|
|
- DM.SetPatchConstantFunction(PatchConstantFunc);
|
|
|
- }
|
|
|
-
|
|
|
- if (Function *EntryFunc = DM.GetEntryFunction()) {
|
|
|
- StringRef Name = DM.GetEntryFunctionName();
|
|
|
- EntryFunc->setName(Name);
|
|
|
- EntryFunc = StripFunctionParameter(EntryFunc, DM, FunctionDIs);
|
|
|
- if (EntryFunc)
|
|
|
- DM.SetEntryFunction(EntryFunc);
|
|
|
- }
|
|
|
- } else {
|
|
|
- std::vector<Function *> entries;
|
|
|
- for (iplist<Function>::iterator F : M.getFunctionList()) {
|
|
|
- if (DM.HasDxilFunctionProps(F)) {
|
|
|
- entries.emplace_back(F);
|
|
|
- }
|
|
|
- }
|
|
|
- for (Function *entry : entries) {
|
|
|
- DxilFunctionProps &props = DM.GetDxilFunctionProps(entry);
|
|
|
- if (props.IsHS()) {
|
|
|
- // Strip patch constant function first.
|
|
|
- Function *patchConstFunc = StripFunctionParameter(
|
|
|
- props.ShaderProps.HS.patchConstantFunc, DM, FunctionDIs);
|
|
|
- props.ShaderProps.HS.patchConstantFunc = patchConstFunc;
|
|
|
- }
|
|
|
- StripFunctionParameter(entry, DM, FunctionDIs);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- DM.CollectShaderFlags(); // Update flags to reflect any changes.
|
|
|
- // Update Validator Version
|
|
|
- DM.UpgradeToMinValidatorVersion();
|
|
|
- DM.EmitDxilMetadata();
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-};
|
|
|
-}
|
|
|
-
|
|
|
-char DxilEmitMetadata::ID = 0;
|
|
|
-
|
|
|
-ModulePass *llvm::createDxilEmitMetadataPass() {
|
|
|
- return new DxilEmitMetadata();
|
|
|
-}
|
|
|
-
|
|
|
-INITIALIZE_PASS(DxilEmitMetadata, "hlsl-dxilemit", "HLSL DXIL Metadata Emit", false, false)
|
|
|
-
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
// Precise propagate.
|
|
@@ -1877,7 +1550,7 @@ void DxilLegalizeResourceUsePass::PromoteLocalResource(Function &F) {
|
|
|
// the entry node
|
|
|
for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I)
|
|
|
if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) { // Is it an alloca?
|
|
|
- if (HandleTy == HLModule::GetArrayEltTy(AI->getAllocatedType())) {
|
|
|
+ if (HandleTy == dxilutil::GetArrayEltTy(AI->getAllocatedType())) {
|
|
|
DXASSERT(isAllocaPromotable(AI), "otherwise, non-promotable resource array alloca found");
|
|
|
Allocas.push_back(AI);
|
|
|
}
|
|
@@ -1920,7 +1593,7 @@ void DxilLegalizeStaticResourceUsePass::PromoteStaticGlobalResources(
|
|
|
std::set<GlobalVariable *> staticResources;
|
|
|
for (auto &GV : M.globals()) {
|
|
|
if (GV.getLinkage() == GlobalValue::LinkageTypes::InternalLinkage &&
|
|
|
- HandleTy == HLModule::GetArrayEltTy(GV.getType())) {
|
|
|
+ HandleTy == dxilutil::GetArrayEltTy(GV.getType())) {
|
|
|
staticResources.insert(&GV);
|
|
|
}
|
|
|
}
|