LLVM 17.0.0git
DXILPrepare.cpp
Go to the documentation of this file.
1//===- DXILPrepare.cpp - Prepare LLVM Module for DXIL encoding ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file This file contains pases and utilities to convert a modern LLVM
10/// module into a module compatible with the LLVM 3.7-based DirectX Intermediate
11/// Language (DXIL).
12//===----------------------------------------------------------------------===//
13
14#include "DirectX.h"
16#include "llvm/ADT/STLExtras.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/Instruction.h"
21#include "llvm/IR/Module.h"
23#include "llvm/Pass.h"
25
26#define DEBUG_TYPE "dxil-prepare"
27
28using namespace llvm;
29using namespace llvm::dxil;
30
31namespace {
32
33constexpr bool isValidForDXIL(Attribute::AttrKind Attr) {
34 return is_contained({Attribute::Alignment,
35 Attribute::AlwaysInline,
36 Attribute::Builtin,
37 Attribute::ByVal,
38 Attribute::InAlloca,
39 Attribute::Cold,
40 Attribute::Convergent,
41 Attribute::InlineHint,
42 Attribute::InReg,
43 Attribute::JumpTable,
44 Attribute::MinSize,
45 Attribute::Naked,
46 Attribute::Nest,
47 Attribute::NoAlias,
48 Attribute::NoBuiltin,
49 Attribute::NoCapture,
50 Attribute::NoDuplicate,
51 Attribute::NoImplicitFloat,
52 Attribute::NoInline,
53 Attribute::NonLazyBind,
54 Attribute::NonNull,
55 Attribute::Dereferenceable,
56 Attribute::DereferenceableOrNull,
57 Attribute::Memory,
58 Attribute::NoRedZone,
59 Attribute::NoReturn,
60 Attribute::NoUnwind,
61 Attribute::OptimizeForSize,
62 Attribute::OptimizeNone,
63 Attribute::ReadNone,
64 Attribute::ReadOnly,
65 Attribute::Returned,
66 Attribute::ReturnsTwice,
67 Attribute::SExt,
68 Attribute::StackAlignment,
69 Attribute::StackProtect,
70 Attribute::StackProtectReq,
71 Attribute::StackProtectStrong,
72 Attribute::SafeStack,
73 Attribute::StructRet,
74 Attribute::SanitizeAddress,
75 Attribute::SanitizeThread,
76 Attribute::SanitizeMemory,
77 Attribute::UWTable,
78 Attribute::ZExt},
79 Attr);
80}
81
82class DXILPrepareModule : public ModulePass {
83
84 static Value *maybeGenerateBitcast(IRBuilder<> &Builder,
85 PointerTypeMap &PointerTypes,
86 Instruction &Inst, Value *Operand,
87 Type *Ty) {
88 // Omit bitcasts if the incoming value matches the instruction type.
89 auto It = PointerTypes.find(Operand);
90 if (It != PointerTypes.end())
91 if (cast<TypedPointerType>(It->second)->getElementType() == Ty)
92 return nullptr;
93 // Insert bitcasts where we are removing the instruction.
94 Builder.SetInsertPoint(&Inst);
95 // This code only gets hit in opaque-pointer mode, so the type of the
96 // pointer doesn't matter.
97 PointerType *PtrTy = cast<PointerType>(Operand->getType());
98 return Builder.Insert(
99 CastInst::Create(Instruction::BitCast, Operand,
100 Builder.getInt8PtrTy(PtrTy->getAddressSpace())));
101 }
102
103public:
104 bool runOnModule(Module &M) override {
106 AttributeMask AttrMask;
108 I = Attribute::AttrKind(I + 1)) {
109 if (!isValidForDXIL(I))
110 AttrMask.addAttribute(I);
111 }
112 for (auto &F : M.functions()) {
113 F.removeFnAttrs(AttrMask);
114 F.removeRetAttrs(AttrMask);
115 for (size_t Idx = 0, End = F.arg_size(); Idx < End; ++Idx)
116 F.removeParamAttrs(Idx, AttrMask);
117
118 for (auto &BB : F) {
119 IRBuilder<> Builder(&BB);
120 for (auto &I : make_early_inc_range(BB)) {
121 if (I.getOpcode() == Instruction::FNeg) {
122 Builder.SetInsertPoint(&I);
123 Value *In = I.getOperand(0);
124 Value *Zero = ConstantFP::get(In->getType(), -0.0);
125 I.replaceAllUsesWith(Builder.CreateFSub(Zero, In));
126 I.eraseFromParent();
127 continue;
128 }
129 // Only insert bitcasts if the IR is using opaque pointers.
130 if (M.getContext().supportsTypedPointers())
131 continue;
132
133 // Emtting NoOp bitcast instructions allows the ValueEnumerator to be
134 // unmodified as it reserves instruction IDs during contruction.
135 if (auto LI = dyn_cast<LoadInst>(&I)) {
136 if (Value *NoOpBitcast = maybeGenerateBitcast(
137 Builder, PointerTypes, I, LI->getPointerOperand(),
138 LI->getType())) {
139 LI->replaceAllUsesWith(
140 Builder.CreateLoad(LI->getType(), NoOpBitcast));
141 LI->eraseFromParent();
142 }
143 continue;
144 }
145 if (auto SI = dyn_cast<StoreInst>(&I)) {
146 if (Value *NoOpBitcast = maybeGenerateBitcast(
147 Builder, PointerTypes, I, SI->getPointerOperand(),
148 SI->getValueOperand()->getType())) {
149
150 SI->replaceAllUsesWith(
151 Builder.CreateStore(SI->getValueOperand(), NoOpBitcast));
152 SI->eraseFromParent();
153 }
154 continue;
155 }
156 if (auto GEP = dyn_cast<GetElementPtrInst>(&I)) {
157 if (Value *NoOpBitcast = maybeGenerateBitcast(
158 Builder, PointerTypes, I, GEP->getPointerOperand(),
159 GEP->getResultElementType()))
160 GEP->setOperand(0, NoOpBitcast);
161 continue;
162 }
163 if (auto *CB = dyn_cast<CallBase>(&I)) {
164 CB->removeFnAttrs(AttrMask);
165 CB->removeRetAttrs(AttrMask);
166 for (size_t Idx = 0, End = CB->arg_size(); Idx < End; ++Idx)
167 CB->removeParamAttrs(Idx, AttrMask);
168 continue;
169 }
170 }
171 }
172 }
173 return true;
174 }
175
176 DXILPrepareModule() : ModulePass(ID) {}
177
178 static char ID; // Pass identification.
179};
180char DXILPrepareModule::ID = 0;
181
182} // end anonymous namespace
183
184INITIALIZE_PASS_BEGIN(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module",
185 false, false)
186INITIALIZE_PASS_END(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module", false,
187 false)
188
190 return new DXILPrepareModule();
191}
assume Assume Builder
#define DEBUG_TYPE
Definition: DXILPrepare.cpp:26
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
bool End
Definition: ELF_riscv.cpp:464
Hexagon Common GEP
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
@ SI
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
Definition: Attributes.h:1006
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition: Attributes.h:87
@ None
No attributes have been set.
Definition: Attributes.h:89
@ EndAttrKinds
Sentinal value useful for loops.
Definition: Attributes.h:92
static CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", Instruction *InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
Definition: Constants.cpp:927
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2564
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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...
Definition: STLExtras.h:748
ModulePass * createDXILPrepareModulePass()
Pass to convert modules into DXIL-compatable modules.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1976