| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // DxilPrecisePropagatePass.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/DXIL/DxilModule.h"
- #include "dxc/HLSL/DxilGenerationPass.h"
- #include "dxc/HLSL/HLModule.h"
- #include "dxc/HLSL/HLOperations.h"
- #include "llvm/Pass.h"
- #include "llvm/IR/Function.h"
- #include "llvm/IR/Instruction.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/Operator.h"
- #include "llvm/IR/Module.h"
- #include "llvm/Support/Casting.h"
- #include <unordered_set>
- #include <vector>
- using namespace llvm;
- using namespace hlsl;
- namespace {
- class DxilPrecisePropagatePass : public ModulePass {
- public:
- static char ID; // Pass identification, replacement for typeid
- explicit DxilPrecisePropagatePass() : ModulePass(ID) {}
- const char *getPassName() const override { return "DXIL Precise Propagate"; }
- bool runOnModule(Module &M) override {
- DxilModule &dxilModule = M.GetOrCreateDxilModule();
- DxilTypeSystem &typeSys = dxilModule.GetTypeSystem();
- std::unordered_set<Instruction*> processedSet;
- std::vector<Function*> deadList;
- for (Function &F : M.functions()) {
- if (HLModule::HasPreciseAttribute(&F)) {
- PropagatePreciseOnFunctionUser(F, typeSys, processedSet);
- deadList.emplace_back(&F);
- }
- }
- for (Function *F : deadList)
- F->eraseFromParent();
- return true;
- }
- private:
- void PropagatePreciseOnFunctionUser(
- Function &F, DxilTypeSystem &typeSys,
- std::unordered_set<Instruction *> &processedSet);
- };
- char DxilPrecisePropagatePass::ID = 0;
- }
- static void PropagatePreciseAttribute(Instruction *I, DxilTypeSystem &typeSys,
- std::unordered_set<Instruction *> &processedSet);
- static void PropagatePreciseAttributeOnOperand(
- Value *V, DxilTypeSystem &typeSys, LLVMContext &Context,
- std::unordered_set<Instruction *> &processedSet) {
- Instruction *I = dyn_cast<Instruction>(V);
- // Skip none inst.
- if (!I)
- return;
- FPMathOperator *FPMath = dyn_cast<FPMathOperator>(I);
- // Skip none FPMath
- if (!FPMath)
- return;
- // Skip inst already marked.
- if (processedSet.count(I) > 0)
- return;
- // TODO: skip precise on integer type, sample instruction...
- processedSet.insert(I);
- // Set precise fast math on those instructions that support it.
- if (DxilModule::PreservesFastMathFlags(I))
- DxilModule::SetPreciseFastMathFlags(I);
- // Fast math not work on call, use metadata.
- if (CallInst *CI = dyn_cast<CallInst>(I))
- HLModule::MarkPreciseAttributeWithMetadata(CI);
- PropagatePreciseAttribute(I, typeSys, processedSet);
- }
- static void PropagatePreciseAttributeOnPointer(
- Value *Ptr, DxilTypeSystem &typeSys, LLVMContext &Context,
- std::unordered_set<Instruction *> &processedSet) {
- // Find all store and propagate on the val operand of store.
- // For CallInst, if Ptr is used as out parameter, mark it.
- for (User *U : Ptr->users()) {
- Instruction *user = cast<Instruction>(U);
- if (StoreInst *stInst = dyn_cast<StoreInst>(user)) {
- Value *val = stInst->getValueOperand();
- PropagatePreciseAttributeOnOperand(val, typeSys, Context, processedSet);
- } else if (CallInst *CI = dyn_cast<CallInst>(user)) {
- bool bReadOnly = true;
- Function *F = CI->getCalledFunction();
- const DxilFunctionAnnotation *funcAnnotation =
- typeSys.GetFunctionAnnotation(F);
- for (unsigned i = 0; i < CI->getNumArgOperands(); ++i) {
- if (Ptr != CI->getArgOperand(i))
- continue;
- const DxilParameterAnnotation ¶mAnnotation =
- funcAnnotation->GetParameterAnnotation(i);
- // OutputPatch and OutputStream will be checked after scalar repl.
- // Here only check out/inout
- if (paramAnnotation.GetParamInputQual() == DxilParamInputQual::Out ||
- paramAnnotation.GetParamInputQual() == DxilParamInputQual::Inout) {
- bReadOnly = false;
- break;
- }
- }
- if (!bReadOnly)
- PropagatePreciseAttributeOnOperand(CI, typeSys, Context, processedSet);
- }
- }
- }
- static void
- PropagatePreciseAttribute(Instruction *I, DxilTypeSystem &typeSys,
- std::unordered_set<Instruction *> &processedSet) {
- LLVMContext &Context = I->getContext();
- if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
- PropagatePreciseAttributeOnPointer(AI, typeSys, Context, processedSet);
- } else if (dyn_cast<CallInst>(I)) {
- // Propagate every argument.
- // TODO: only propagate precise argument.
- for (Value *src : I->operands())
- PropagatePreciseAttributeOnOperand(src, typeSys, Context, processedSet);
- } else if (dyn_cast<FPMathOperator>(I)) {
- // TODO: only propagate precise argument.
- for (Value *src : I->operands())
- PropagatePreciseAttributeOnOperand(src, typeSys, Context, processedSet);
- } else if (LoadInst *ldInst = dyn_cast<LoadInst>(I)) {
- Value *Ptr = ldInst->getPointerOperand();
- PropagatePreciseAttributeOnPointer(Ptr, typeSys, Context, processedSet);
- } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I))
- PropagatePreciseAttributeOnPointer(GEP, typeSys, Context, processedSet);
- // TODO: support more case which need
- }
- void DxilPrecisePropagatePass::PropagatePreciseOnFunctionUser(
- Function &F, DxilTypeSystem &typeSys,
- std::unordered_set<Instruction *> &processedSet) {
- LLVMContext &Context = F.getContext();
- for (auto U = F.user_begin(), E = F.user_end(); U != E;) {
- CallInst *CI = cast<CallInst>(*(U++));
- Value *V = CI->getArgOperand(0);
- PropagatePreciseAttributeOnOperand(V, typeSys, Context, processedSet);
- CI->eraseFromParent();
- }
- }
- ModulePass *llvm::createDxilPrecisePropagatePass() {
- return new DxilPrecisePropagatePass();
- }
- INITIALIZE_PASS(DxilPrecisePropagatePass, "hlsl-dxil-precise", "DXIL precise attribute propagate", false, false)
|