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