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"
15#include "DirectXIRPasses/PointerTypeAnalysis.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/IR/AttributeMask.h"
20#include "llvm/IR/IRBuilder.h"
21#include "llvm/IR/Instruction.h"
22#include "llvm/IR/Module.h"
23#include "llvm/InitializePasses.h"
24#include "llvm/Pass.h"
25#include "llvm/Support/Compiler.h"
26
27#define DEBUG_TYPE "dxil-prepare"
28
29using namespace llvm;
30using namespace llvm::dxil;
31
32namespace {
33
34constexpr bool isValidForDXIL(Attribute::AttrKind Attr) {
35 return is_contained({Attribute::Alignment,
36 Attribute::AlwaysInline,
37 Attribute::Builtin,
38 Attribute::ByVal,
39 Attribute::InAlloca,
40 Attribute::Cold,
41 Attribute::Convergent,
42 Attribute::InlineHint,
43 Attribute::InReg,
44 Attribute::JumpTable,
45 Attribute::MinSize,
46 Attribute::Naked,
47 Attribute::Nest,
48 Attribute::NoAlias,
49 Attribute::NoBuiltin,
50 Attribute::NoCapture,
51 Attribute::NoDuplicate,
52 Attribute::NoImplicitFloat,
53 Attribute::NoInline,
54 Attribute::NonLazyBind,
55 Attribute::NonNull,
56 Attribute::Dereferenceable,
57 Attribute::DereferenceableOrNull,
58 Attribute::Memory,
59 Attribute::NoRedZone,
60 Attribute::NoReturn,
61 Attribute::NoUnwind,
62 Attribute::OptimizeForSize,
63 Attribute::OptimizeNone,
64 Attribute::ReadNone,
65 Attribute::ReadOnly,
66 Attribute::Returned,
67 Attribute::ReturnsTwice,
68 Attribute::SExt,
69 Attribute::StackAlignment,
70 Attribute::StackProtect,
71 Attribute::StackProtectReq,
72 Attribute::StackProtectStrong,
73 Attribute::SafeStack,
74 Attribute::StructRet,
75 Attribute::SanitizeAddress,
76 Attribute::SanitizeThread,
77 Attribute::SanitizeMemory,
78 Attribute::UWTable,
79 Attribute::ZExt},
80 Attr);
81}
82
83class DXILPrepareModule : public ModulePass {
84
85 static Value *maybeGenerateBitcast(IRBuilder<> &Builder,
86 PointerTypeMap &PointerTypes,
87 Instruction &Inst, Value *Operand,
88 Type *Ty) {
89 // Omit bitcasts if the incoming value matches the instruction type.
90 auto It = PointerTypes.find(Val: Operand);
91 if (It != PointerTypes.end())
92 if (cast<TypedPointerType>(Val: It->second)->getElementType() == Ty)
93 return nullptr;
94 // Insert bitcasts where we are removing the instruction.
95 Builder.SetInsertPoint(&Inst);
96 // This code only gets hit in opaque-pointer mode, so the type of the
97 // pointer doesn't matter.
98 PointerType *PtrTy = cast<PointerType>(Val: Operand->getType());
99 return Builder.Insert(
100 I: CastInst::Create(Instruction::BitCast, S: Operand,
101 Ty: Builder.getPtrTy(AddrSpace: PtrTy->getAddressSpace())));
102 }
103
104public:
105 bool runOnModule(Module &M) override {
106 PointerTypeMap PointerTypes = PointerTypeAnalysis::run(M);
107 AttributeMask AttrMask;
108 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
109 I = Attribute::AttrKind(I + 1)) {
110 if (!isValidForDXIL(I))
111 AttrMask.addAttribute(Val: I);
112 }
113 for (auto &F : M.functions()) {
114 F.removeFnAttrs(Attrs: AttrMask);
115 F.removeRetAttrs(Attrs: AttrMask);
116 for (size_t Idx = 0, End = F.arg_size(); Idx < End; ++Idx)
117 F.removeParamAttrs(ArgNo: Idx, Attrs: AttrMask);
118
119 for (auto &BB : F) {
120 IRBuilder<> Builder(&BB);
121 for (auto &I : make_early_inc_range(Range&: BB)) {
122 if (I.getOpcode() == Instruction::FNeg) {
123 Builder.SetInsertPoint(&I);
124 Value *In = I.getOperand(i: 0);
125 Value *Zero = ConstantFP::get(Ty: In->getType(), V: -0.0);
126 I.replaceAllUsesWith(V: Builder.CreateFSub(L: Zero, R: In));
127 I.eraseFromParent();
128 continue;
129 }
130
131 // Emtting NoOp bitcast instructions allows the ValueEnumerator to be
132 // unmodified as it reserves instruction IDs during contruction.
133 if (auto LI = dyn_cast<LoadInst>(Val: &I)) {
134 if (Value *NoOpBitcast = maybeGenerateBitcast(
135 Builder, PointerTypes, Inst&: I, Operand: LI->getPointerOperand(),
136 Ty: LI->getType())) {
137 LI->replaceAllUsesWith(
138 V: Builder.CreateLoad(Ty: LI->getType(), Ptr: NoOpBitcast));
139 LI->eraseFromParent();
140 }
141 continue;
142 }
143 if (auto SI = dyn_cast<StoreInst>(Val: &I)) {
144 if (Value *NoOpBitcast = maybeGenerateBitcast(
145 Builder, PointerTypes, Inst&: I, Operand: SI->getPointerOperand(),
146 Ty: SI->getValueOperand()->getType())) {
147
148 SI->replaceAllUsesWith(
149 V: Builder.CreateStore(Val: SI->getValueOperand(), Ptr: NoOpBitcast));
150 SI->eraseFromParent();
151 }
152 continue;
153 }
154 if (auto GEP = dyn_cast<GetElementPtrInst>(Val: &I)) {
155 if (Value *NoOpBitcast = maybeGenerateBitcast(
156 Builder, PointerTypes, Inst&: I, Operand: GEP->getPointerOperand(),
157 Ty: GEP->getSourceElementType()))
158 GEP->setOperand(i_nocapture: 0, Val_nocapture: NoOpBitcast);
159 continue;
160 }
161 if (auto *CB = dyn_cast<CallBase>(Val: &I)) {
162 CB->removeFnAttrs(AttrsToRemove: AttrMask);
163 CB->removeRetAttrs(AttrsToRemove: AttrMask);
164 for (size_t Idx = 0, End = CB->arg_size(); Idx < End; ++Idx)
165 CB->removeParamAttrs(ArgNo: Idx, AttrsToRemove: AttrMask);
166 continue;
167 }
168 }
169 }
170 }
171 return true;
172 }
173
174 DXILPrepareModule() : ModulePass(ID) {}
175
176 static char ID; // Pass identification.
177};
178char DXILPrepareModule::ID = 0;
179
180} // end anonymous namespace
181
182INITIALIZE_PASS_BEGIN(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module",
183 false, false)
184INITIALIZE_PASS_END(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module", false,
185 false)
186
187ModulePass *llvm::createDXILPrepareModulePass() {
188 return new DXILPrepareModule();
189}
190

source code of llvm/lib/Target/DirectX/DXILPrepare.cpp