1 //===- DXILOpLower.cpp - Lowering LLVM intrinsic to DIXLOp function -------===// 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 passes and utilities to lower llvm intrinsic call 10 /// to DXILOp function call. 11 //===----------------------------------------------------------------------===// 12 13 #include "DXILConstants.h" 14 #include "DXILOpBuilder.h" 15 #include "DirectX.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/Intrinsics.h" 21 #include "llvm/IR/IntrinsicsDirectX.h" 22 #include "llvm/IR/Module.h" 23 #include "llvm/IR/PassManager.h" 24 #include "llvm/Pass.h" 25 #include "llvm/Support/ErrorHandling.h" 26 27 #define DEBUG_TYPE "dxil-op-lower" 28 29 using namespace llvm; 30 using namespace llvm::dxil; 31 32 static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { 33 IRBuilder<> B(M.getContext()); 34 Value *DXILOpArg = B.getInt32(static_cast<unsigned>(DXILOp)); 35 DXILOpBuilder DXILB(M, B); 36 Type *OverloadTy = 37 DXILB.getOverloadTy(DXILOp, F.getFunctionType(), /*NoOpCodeParam*/ true); 38 for (User *U : make_early_inc_range(F.users())) { 39 CallInst *CI = dyn_cast<CallInst>(U); 40 if (!CI) 41 continue; 42 43 SmallVector<Value *> Args; 44 Args.emplace_back(DXILOpArg); 45 Args.append(CI->arg_begin(), CI->arg_end()); 46 B.SetInsertPoint(CI); 47 CallInst *DXILCI = DXILB.createDXILOpCall(DXILOp, OverloadTy, CI->args()); 48 49 CI->replaceAllUsesWith(DXILCI); 50 CI->eraseFromParent(); 51 } 52 if (F.user_empty()) 53 F.eraseFromParent(); 54 } 55 56 static bool lowerIntrinsics(Module &M) { 57 bool Updated = false; 58 59 #define DXIL_OP_INTRINSIC_MAP 60 #include "DXILOperation.inc" 61 #undef DXIL_OP_INTRINSIC_MAP 62 63 for (Function &F : make_early_inc_range(M.functions())) { 64 if (!F.isDeclaration()) 65 continue; 66 Intrinsic::ID ID = F.getIntrinsicID(); 67 if (ID == Intrinsic::not_intrinsic) 68 continue; 69 auto LowerIt = LowerMap.find(ID); 70 if (LowerIt == LowerMap.end()) 71 continue; 72 lowerIntrinsic(LowerIt->second, F, M); 73 Updated = true; 74 } 75 return Updated; 76 } 77 78 namespace { 79 /// A pass that transforms external global definitions into declarations. 80 class DXILOpLowering : public PassInfoMixin<DXILOpLowering> { 81 public: 82 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { 83 if (lowerIntrinsics(M)) 84 return PreservedAnalyses::none(); 85 return PreservedAnalyses::all(); 86 } 87 }; 88 } // namespace 89 90 namespace { 91 class DXILOpLoweringLegacy : public ModulePass { 92 public: 93 bool runOnModule(Module &M) override { return lowerIntrinsics(M); } 94 StringRef getPassName() const override { return "DXIL Op Lowering"; } 95 DXILOpLoweringLegacy() : ModulePass(ID) {} 96 97 static char ID; // Pass identification. 98 }; 99 char DXILOpLoweringLegacy::ID = 0; 100 101 } // end anonymous namespace 102 103 INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", 104 false, false) 105 INITIALIZE_PASS_END(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false, 106 false) 107 108 ModulePass *llvm::createDXILOpLoweringLegacyPass() { 109 return new DXILOpLoweringLegacy(); 110 } 111