33#define DEBUG_TYPE "dxil-prepare"
42 Attribute::AlwaysInline,
47 Attribute::Convergent,
48 Attribute::InlineHint,
56 Attribute::NoDuplicate,
57 Attribute::NoImplicitFloat,
59 Attribute::NonLazyBind,
61 Attribute::Dereferenceable,
62 Attribute::DereferenceableOrNull,
67 Attribute::OptimizeForSize,
68 Attribute::OptimizeNone,
72 Attribute::ReturnsTwice,
74 Attribute::StackAlignment,
75 Attribute::StackProtect,
76 Attribute::StackProtectReq,
77 Attribute::StackProtectStrong,
80 Attribute::SanitizeAddress,
81 Attribute::SanitizeThread,
82 Attribute::SanitizeMemory,
90 bool AllowExperimental) {
91 for (
auto &Attr : AS) {
92 if (!Attr.isStringAttribute())
97 if (AllowExperimental &&
Key.starts_with(
"exp-"))
103static void removeStringFunctionAttributes(
Function &
F,
104 bool AllowExperimental) {
105 AttributeList Attrs =
F.getAttributes();
106 const StringSet<> LiveKeys = {
"waveops-include-helper-lanes",
110 collectDeadStringAttrs(DeadAttrs, Attrs.getFnAttrs(), LiveKeys,
112 collectDeadStringAttrs(DeadAttrs, Attrs.getRetAttrs(), LiveKeys,
115 F.removeFnAttrs(DeadAttrs);
116 F.removeRetAttrs(DeadAttrs);
119static void cleanModuleFlags(
Module &M) {
125 M.getModuleFlagsMetadata(FlagEntries);
126 bool Updated =
false;
127 for (
auto &Flag : FlagEntries) {
140 for (
auto &Flag : FlagEntries)
141 M.addModuleFlag(Flag.Behavior, Flag.Key->getString(), Flag.Val);
151 auto It = PointerTypes.
find(Operand);
152 if (It != PointerTypes.
end()) {
161 ValTy = GlobalVar->getValueType();
164 ValTy = AI->getAllocatedType();
167 Type *ElTy = ArrTy->getElementType();
175 while (GEPInstr->getOpcode() == Instruction::GetElementPtr) {
176 Value *OpArg = GEPInstr->getOperand(0);
178 GEPInstr = NewGEPInstr;
183 ValTy = GlobalVar->getValueType();
185 ValTy = AI->getAllocatedType();
187 Type *ElTy = ArrTy->getElementType();
196 Builder.SetInsertPoint(&Inst);
200 return Builder.Insert(
202 Builder.getPtrTy(PtrTy->getAddressSpace())));
205 static std::array<unsigned, 6> getCompatibleInstructionMDs(
llvm::Module &M) {
206 return {M.getMDKindID(
"dx.nonuniform"),
207 M.getMDKindID(
"dx.controlflow.hints"),
208 M.getMDKindID(
"dx.precise"),
209 llvm::LLVMContext::MD_range,
210 llvm::LLVMContext::MD_alias_scope,
211 llvm::LLVMContext::MD_noalias};
215 bool runOnModule(
Module &M)
override {
220 if (!isValidForDXIL(
I))
225 getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
230 std::array<unsigned, 6> DXILCompatibleMDs = getCompatibleInstructionMDs(M);
232 for (
auto &
F : M.functions()) {
233 F.removeFnAttrs(AttrMask);
234 F.removeRetAttrs(AttrMask);
238 removeStringFunctionAttributes(
F, SkipValidation);
239 for (
size_t Idx = 0, End =
F.arg_size(); Idx < End; ++Idx)
240 F.removeParamAttrs(Idx, AttrMask);
246 I.dropUnknownNonDebugMetadata(DXILCompatibleMDs);
251 if (
Value *NoOpBitcast = maybeGenerateBitcast(
252 Builder, PointerTypes,
I, LI->getPointerOperand(),
254 LI->replaceAllUsesWith(
255 Builder.CreateLoad(LI->getType(), NoOpBitcast));
256 LI->eraseFromParent();
261 if (
Value *NoOpBitcast = maybeGenerateBitcast(
262 Builder, PointerTypes,
I,
SI->getPointerOperand(),
263 SI->getValueOperand()->getType())) {
265 SI->replaceAllUsesWith(
266 Builder.CreateStore(
SI->getValueOperand(), NoOpBitcast));
267 SI->eraseFromParent();
272 if (
Value *NoOpBitcast = maybeGenerateBitcast(
273 Builder, PointerTypes,
I,
GEP->getPointerOperand(),
274 GEP->getSourceElementType()))
275 GEP->setOperand(0, NoOpBitcast);
279 CB->removeFnAttrs(AttrMask);
280 CB->removeRetAttrs(AttrMask);
281 for (
size_t Idx = 0, End = CB->arg_size(); Idx < End; ++Idx)
282 CB->removeParamAttrs(Idx, AttrMask);
294 if (
NamedMDNode *RootSignature = M.getNamedMetadata(
"dx.rootsignatures"))
295 RootSignature->eraseFromParent();
311char DXILPrepareModule::ID = 0;
323 return new DXILPrepareModule();
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
StringSet - A set-like wrapper for the StringMap.
Defines the llvm::VersionTuple class, which represents a version in the form major[....
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
This class holds the attributes for a particular argument, parameter, function, or return value.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
@ None
No attributes have been set.
@ EndAttrKinds
Sentinel value useful for loops.
static LLVM_ABI CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
A constant value that is initialized with an expression using other constant values.
iterator find(const_arg_type_t< KeyT > Val)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
@ AppendUnique
Appends the two values, which are required to be metadata nodes.
@ Warning
Emits a warning if two values disagree.
LLVM_ABI void eraseFromParent()
Drop all references and remove the node from parent module.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
StringSet - A wrapper for StringMap that provides set-like functionality.
bool contains(StringRef key) const
Check if the set contains the given key.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
Represents a version number in the form major[.minor[.subminor[.build]]].
unsigned getMajor() const
Retrieve the major version number.
std::optional< unsigned > getMinor() const
Retrieve the minor version number, if provided.
Wrapper pass for the legacy pass manager.
Wrapper pass for the legacy pass manager.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
DenseMap< const Value *, Type * > PointerTypeMap
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
ModulePass * createDXILPrepareModulePass()
Pass to convert modules into DXIL-compatable modules.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.