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
lowerIntrinsic(dxil::OpCode DXILOp,Function & F,Module & M)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
lowerIntrinsics(Module & M)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:
run(Module & M,ModuleAnalysisManager &)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:
runOnModule(Module & M)93 bool runOnModule(Module &M) override { return lowerIntrinsics(M); }
getPassName() const94 StringRef getPassName() const override { return "DXIL Op Lowering"; }
DXILOpLoweringLegacy()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
createDXILOpLoweringLegacyPass()108 ModulePass *llvm::createDXILOpLoweringLegacyPass() {
109 return new DXILOpLoweringLegacy();
110 }
111