blob: b3bc6efa79a923dfbf91e9c44730fe9dd70c82cc [file] [edit]
///////////////////////////////////////////////////////////////////////////////
// //
// ComputeViewIdSets.h //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// Computes output registers dependent on ViewID. //
// Computes sets of input registers on which output registers depend. //
// Computes which input/output shapes are dynamically indexed. //
// //
///////////////////////////////////////////////////////////////////////////////
#pragma once
#include "llvm/Pass.h"
#include "dxc/HLSL/ControlDependence.h"
#include "llvm/Support/GenericDomTree.h"
#include <memory>
#include <bitset>
#include <unordered_set>
#include <unordered_map>
#include <set>
#include <map>
namespace llvm {
class Module;
class Function;
class BasicBlock;
class Instruction;
class ReturnInst;
class Value;
class PHINode;
class AnalysisUsage;
class CallGraph;
class CallGraphNode;
class ModulePass;
class raw_ostream;
}
namespace hlsl {
class DxilModule;
class DxilSignature;
class DxilSignatureElement;
class DxilViewIdState {
static const unsigned kNumComps = 4;
static const unsigned kMaxSigScalars = 32*4;
public:
using OutputsDependentOnViewIdType = std::bitset<kMaxSigScalars>;
using InputsContributingToOutputType = std::map<unsigned, std::set<unsigned>>;
DxilViewIdState(DxilModule *pDxilModule);
unsigned getNumInputSigScalars() const;
unsigned getNumOutputSigScalars(unsigned StreamId) const;
unsigned getNumPCSigScalars() const;
const OutputsDependentOnViewIdType &getOutputsDependentOnViewId(unsigned StreamId) const;
const OutputsDependentOnViewIdType &getPCOutputsDependentOnViewId() const;
const InputsContributingToOutputType &getInputsContributingToOutputs(unsigned StreamId) const;
const InputsContributingToOutputType &getInputsContributingToPCOutputs() const;
const InputsContributingToOutputType &getPCInputsContributingToOutputs() const;
void Compute();
void Serialize();
const std::vector<unsigned> &GetSerialized();
const std::vector<unsigned> &GetSerialized() const; // returns previously serialized data
void Deserialize(const unsigned *pData, unsigned DataSizeInUINTs);
void PrintSets(llvm::raw_ostream &OS);
private:
static const unsigned kNumStreams = 4;
DxilModule *m_pModule;
bool m_bUsesViewId = false;
unsigned m_NumInputSigScalars = 0;
unsigned m_NumOutputSigScalars[kNumStreams] = {0,0,0,0};
unsigned m_NumPCSigScalars = 0;
// Dynamically indexed components of signature elements.
using DynamicallyIndexedElemsType = std::unordered_map<unsigned, unsigned>;
DynamicallyIndexedElemsType m_InpSigDynIdxElems;
DynamicallyIndexedElemsType m_OutSigDynIdxElems;
DynamicallyIndexedElemsType m_PCSigDynIdxElems;
// Set of scalar outputs dependent on ViewID.
OutputsDependentOnViewIdType m_OutputsDependentOnViewId[kNumStreams];
OutputsDependentOnViewIdType m_PCOutputsDependentOnViewId;
// Set of scalar inputs contributing to computation of scalar outputs.
InputsContributingToOutputType m_InputsContributingToOutputs[kNumStreams];
InputsContributingToOutputType m_InputsContributingToPCOutputs; // HS PC only.
InputsContributingToOutputType m_PCInputsContributingToOutputs; // DS only.
// Information per entry point.
using FunctionSetType = std::unordered_set<llvm::Function *>;
using InstructionSetType = std::unordered_set<llvm::Instruction *>;
struct EntryInfo {
llvm::Function *pEntryFunc = nullptr;
// Sets of functions that may be reachable from an entry.
FunctionSetType Functions;
// Outputs to analyze.
InstructionSetType Outputs;
// Contributing instructions per output.
std::unordered_map<unsigned, InstructionSetType> ContributingInstructions[kNumStreams];
void Clear();
};
EntryInfo m_Entry;
EntryInfo m_PCEntry;
// Information per function.
using FunctionReturnSet = std::unordered_set<llvm::ReturnInst *>;
struct FuncInfo {
FunctionReturnSet Returns;
ControlDependence CtrlDep;
std::unique_ptr<llvm::DominatorTreeBase<llvm::BasicBlock> > pDomTree;
void Clear();
};
std::unordered_map<llvm::Function *, std::unique_ptr<FuncInfo>> m_FuncInfo;
// Cache of decls (global/alloca) reaching a pointer value.
using ValueSetType = std::unordered_set<llvm::Value *>;
std::unordered_map<llvm::Value *, ValueSetType> m_ReachingDeclsCache;
// Cache of stores for each decl.
std::unordered_map<llvm::Value *, ValueSetType> m_StoresPerDeclCache;
// Serialized form.
std::vector<unsigned> m_SerializedState;
void Clear();
void DetermineMaxPackedLocation(DxilSignature &DxilSig, unsigned *pMaxSigLoc, unsigned NumStreams);
void ComputeReachableFunctionsRec(llvm::CallGraph &CG, llvm::CallGraphNode *pNode, FunctionSetType &FuncSet);
void AnalyzeFunctions(EntryInfo &Entry);
void CollectValuesContributingToOutputs(EntryInfo &Entry);
void CollectValuesContributingToOutputRec(EntryInfo &Entry,
llvm::Value *pContributingValue,
InstructionSetType &ContributingInstructions);
void CollectPhiCFValuesContributingToOutputRec(llvm::PHINode *pPhi,
EntryInfo &Entry,
InstructionSetType &ContributingInstructions);
const ValueSetType &CollectReachingDecls(llvm::Value *pValue);
void CollectReachingDeclsRec(llvm::Value *pValue, ValueSetType &ReachingDecls, ValueSetType &Visited);
const ValueSetType &CollectStores(llvm::Value *pValue);
void CollectStoresRec(llvm::Value *pValue, ValueSetType &Stores, ValueSetType &Visited);
void UpdateDynamicIndexUsageState() const;
void CreateViewIdSets(const std::unordered_map<unsigned, InstructionSetType> &ContributingInstructions,
OutputsDependentOnViewIdType &OutputsDependentOnViewId,
InputsContributingToOutputType &InputsContributingToOutputs, bool bPC);
void UpdateDynamicIndexUsageStateForSig(DxilSignature &Sig, const DynamicallyIndexedElemsType &DynIdxElems) const;
void SerializeOutputsDependentOnViewId(unsigned NumOutputs,
const OutputsDependentOnViewIdType &OutputsDependentOnViewId,
unsigned *&pData);
void SerializeInputsContributingToOutput(unsigned NumInputs, unsigned NumOutputs,
const InputsContributingToOutputType &InputsContributingToOutputs,
unsigned *&pData);
unsigned DeserializeOutputsDependentOnViewId(unsigned NumOutputs,
OutputsDependentOnViewIdType &OutputsDependentOnViewId,
const unsigned *pData, unsigned DataSize);
unsigned DeserializeInputsContributingToOutput(unsigned NumInputs, unsigned NumOutputs,
InputsContributingToOutputType &InputsContributingToOutputs,
const unsigned *pData, unsigned DataSize);
unsigned GetLinearIndex(DxilSignatureElement &SigElem, int row, unsigned col) const;
void PrintOutputsDependentOnViewId(llvm::raw_ostream &OS,
llvm::StringRef SetName, unsigned NumOutputs,
const OutputsDependentOnViewIdType &OutputsDependentOnViewId);
void PrintInputsContributingToOutputs(llvm::raw_ostream &OS,
llvm::StringRef InputSetName, llvm::StringRef OutputSetName,
const InputsContributingToOutputType &InputsContributingToOutputs);
};
} // end of hlsl namespace
namespace llvm {
class ComputeViewIdState : public ModulePass {
public:
static char ID; // Pass ID, replacement for typeid
ComputeViewIdState();
bool runOnModule(Module &M) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
void initializeComputeViewIdStatePass(llvm::PassRegistry &);
llvm::ModulePass *createComputeViewIdStatePass();
} // end of llvm namespace