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 "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/CodeGen/Passes.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/Instruction.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/InitializePasses.h"
22 #include "llvm/Pass.h"
23 #include "llvm/Support/Compiler.h"
24 
25 #define DEBUG_TYPE "dxil-prepare"
26 
27 using namespace llvm;
28 
29 namespace {
30 
31 constexpr bool isValidForDXIL(Attribute::AttrKind Attr) {
32   return is_contained({Attribute::Alignment,
33                        Attribute::AlwaysInline,
34                        Attribute::Builtin,
35                        Attribute::ByVal,
36                        Attribute::InAlloca,
37                        Attribute::Cold,
38                        Attribute::Convergent,
39                        Attribute::InlineHint,
40                        Attribute::InReg,
41                        Attribute::JumpTable,
42                        Attribute::MinSize,
43                        Attribute::Naked,
44                        Attribute::Nest,
45                        Attribute::NoAlias,
46                        Attribute::NoBuiltin,
47                        Attribute::NoCapture,
48                        Attribute::NoDuplicate,
49                        Attribute::NoImplicitFloat,
50                        Attribute::NoInline,
51                        Attribute::NonLazyBind,
52                        Attribute::NonNull,
53                        Attribute::Dereferenceable,
54                        Attribute::DereferenceableOrNull,
55                        Attribute::NoRedZone,
56                        Attribute::NoReturn,
57                        Attribute::NoUnwind,
58                        Attribute::OptimizeForSize,
59                        Attribute::OptimizeNone,
60                        Attribute::ReadNone,
61                        Attribute::ReadOnly,
62                        Attribute::ArgMemOnly,
63                        Attribute::Returned,
64                        Attribute::ReturnsTwice,
65                        Attribute::SExt,
66                        Attribute::StackAlignment,
67                        Attribute::StackProtect,
68                        Attribute::StackProtectReq,
69                        Attribute::StackProtectStrong,
70                        Attribute::SafeStack,
71                        Attribute::StructRet,
72                        Attribute::SanitizeAddress,
73                        Attribute::SanitizeThread,
74                        Attribute::SanitizeMemory,
75                        Attribute::UWTable,
76                        Attribute::ZExt},
77                       Attr);
78 }
79 
80 class DXILPrepareModule : public ModulePass {
81 public:
82   bool runOnModule(Module &M) override {
83     AttributeMask AttrMask;
84     for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
85          I = Attribute::AttrKind(I + 1)) {
86       if (!isValidForDXIL(I))
87         AttrMask.addAttribute(I);
88     }
89     for (auto &F : M.functions()) {
90       F.removeFnAttrs(AttrMask);
91       F.removeRetAttrs(AttrMask);
92       for (size_t Idx = 0; Idx < F.arg_size(); ++Idx)
93         F.removeParamAttrs(Idx, AttrMask);
94 
95       for (auto &BB : F) {
96         IRBuilder<> Builder(&BB);
97         for (auto &I : make_early_inc_range(BB)) {
98           if (I.getOpcode() == Instruction::FNeg) {
99             Builder.SetInsertPoint(&I);
100             Value *In = I.getOperand(0);
101             Value *Zero = ConstantFP::get(In->getType(), -0.0);
102             I.replaceAllUsesWith(Builder.CreateFSub(Zero, In));
103             I.eraseFromParent();
104           }
105         }
106       }
107     }
108     return true;
109   }
110 
111   DXILPrepareModule() : ModulePass(ID) {}
112 
113   static char ID; // Pass identification.
114 };
115 char DXILPrepareModule::ID = 0;
116 
117 } // end anonymous namespace
118 
119 INITIALIZE_PASS_BEGIN(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module",
120                       false, false)
121 INITIALIZE_PASS_END(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module", false,
122                     false)
123 
124 ModulePass *llvm::createDXILPrepareModulePass() {
125   return new DXILPrepareModule();
126 }
127