185285be9SXiang Li //===- DXILOpLower.cpp - Lowering LLVM intrinsic to DIXLOp function -------===//
285285be9SXiang Li //
385285be9SXiang Li // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
485285be9SXiang Li // See https://llvm.org/LICENSE.txt for license information.
585285be9SXiang Li // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
685285be9SXiang Li //
785285be9SXiang Li //===----------------------------------------------------------------------===//
885285be9SXiang Li ///
985285be9SXiang Li /// \file This file contains passes and utilities to lower llvm intrinsic call
1085285be9SXiang Li /// to DXILOp function call.
1185285be9SXiang Li //===----------------------------------------------------------------------===//
1285285be9SXiang Li 
1385285be9SXiang Li #include "DXILConstants.h"
14*57006b14SXiang Li #include "DXILOpBuilder.h"
1585285be9SXiang Li #include "DirectX.h"
1685285be9SXiang Li #include "llvm/ADT/SmallVector.h"
1785285be9SXiang Li #include "llvm/CodeGen/Passes.h"
1885285be9SXiang Li #include "llvm/IR/IRBuilder.h"
1985285be9SXiang Li #include "llvm/IR/Instruction.h"
2085285be9SXiang Li #include "llvm/IR/Intrinsics.h"
2143dc3190SXiang Li #include "llvm/IR/IntrinsicsDirectX.h"
2285285be9SXiang Li #include "llvm/IR/Module.h"
2385285be9SXiang Li #include "llvm/IR/PassManager.h"
2485285be9SXiang Li #include "llvm/Pass.h"
2585285be9SXiang Li #include "llvm/Support/ErrorHandling.h"
2685285be9SXiang Li 
2785285be9SXiang Li #define DEBUG_TYPE "dxil-op-lower"
2885285be9SXiang Li 
2985285be9SXiang Li using namespace llvm;
3085285be9SXiang Li using namespace llvm::DXIL;
3185285be9SXiang Li 
lowerIntrinsic(DXIL::OpCode DXILOp,Function & F,Module & M)3285285be9SXiang Li static void lowerIntrinsic(DXIL::OpCode DXILOp, Function &F, Module &M) {
3385285be9SXiang Li   IRBuilder<> B(M.getContext());
3485285be9SXiang Li   Value *DXILOpArg = B.getInt32(static_cast<unsigned>(DXILOp));
35*57006b14SXiang Li   DXILOpBuilder DXILB(M, B);
36*57006b14SXiang Li   Type *OverloadTy =
37*57006b14SXiang Li       DXILB.getOverloadTy(DXILOp, F.getFunctionType(), /*NoOpCodeParam*/ true);
3885285be9SXiang Li   for (User *U : make_early_inc_range(F.users())) {
3985285be9SXiang Li     CallInst *CI = dyn_cast<CallInst>(U);
4085285be9SXiang Li     if (!CI)
4185285be9SXiang Li       continue;
4285285be9SXiang Li 
4385285be9SXiang Li     SmallVector<Value *> Args;
4485285be9SXiang Li     Args.emplace_back(DXILOpArg);
4585285be9SXiang Li     Args.append(CI->arg_begin(), CI->arg_end());
4685285be9SXiang Li     B.SetInsertPoint(CI);
47*57006b14SXiang Li     CallInst *DXILCI = DXILB.createDXILOpCall(DXILOp, OverloadTy, CI->args());
48*57006b14SXiang Li 
4985285be9SXiang Li     CI->replaceAllUsesWith(DXILCI);
5085285be9SXiang Li     CI->eraseFromParent();
5185285be9SXiang Li   }
5285285be9SXiang Li   if (F.user_empty())
5385285be9SXiang Li     F.eraseFromParent();
5485285be9SXiang Li }
5585285be9SXiang Li 
lowerIntrinsics(Module & M)5685285be9SXiang Li static bool lowerIntrinsics(Module &M) {
5785285be9SXiang Li   bool Updated = false;
58264c09b7SXiang Li 
59264c09b7SXiang Li #define DXIL_OP_INTRINSIC_MAP
60264c09b7SXiang Li #include "DXILOperation.inc"
61264c09b7SXiang Li #undef DXIL_OP_INTRINSIC_MAP
62264c09b7SXiang Li 
6385285be9SXiang Li   for (Function &F : make_early_inc_range(M.functions())) {
6485285be9SXiang Li     if (!F.isDeclaration())
6585285be9SXiang Li       continue;
6685285be9SXiang Li     Intrinsic::ID ID = F.getIntrinsicID();
67264c09b7SXiang Li     if (ID == Intrinsic::not_intrinsic)
68264c09b7SXiang Li       continue;
6985285be9SXiang Li     auto LowerIt = LowerMap.find(ID);
7085285be9SXiang Li     if (LowerIt == LowerMap.end())
7185285be9SXiang Li       continue;
7285285be9SXiang Li     lowerIntrinsic(LowerIt->second, F, M);
7385285be9SXiang Li     Updated = true;
7485285be9SXiang Li   }
7585285be9SXiang Li   return Updated;
7685285be9SXiang Li }
7785285be9SXiang Li 
7885285be9SXiang Li namespace {
7985285be9SXiang Li /// A pass that transforms external global definitions into declarations.
8085285be9SXiang Li class DXILOpLowering : public PassInfoMixin<DXILOpLowering> {
8185285be9SXiang Li public:
run(Module & M,ModuleAnalysisManager &)8285285be9SXiang Li   PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
8385285be9SXiang Li     if (lowerIntrinsics(M))
8485285be9SXiang Li       return PreservedAnalyses::none();
8585285be9SXiang Li     return PreservedAnalyses::all();
8685285be9SXiang Li   }
8785285be9SXiang Li };
8885285be9SXiang Li } // namespace
8985285be9SXiang Li 
9085285be9SXiang Li namespace {
9185285be9SXiang Li class DXILOpLoweringLegacy : public ModulePass {
9285285be9SXiang Li public:
runOnModule(Module & M)9385285be9SXiang Li   bool runOnModule(Module &M) override { return lowerIntrinsics(M); }
getPassName() const9485285be9SXiang Li   StringRef getPassName() const override { return "DXIL Op Lowering"; }
DXILOpLoweringLegacy()9585285be9SXiang Li   DXILOpLoweringLegacy() : ModulePass(ID) {}
9685285be9SXiang Li 
9785285be9SXiang Li   static char ID; // Pass identification.
9885285be9SXiang Li };
9985285be9SXiang Li char DXILOpLoweringLegacy::ID = 0;
10085285be9SXiang Li 
10185285be9SXiang Li } // end anonymous namespace
10285285be9SXiang Li 
10385285be9SXiang Li INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering",
10485285be9SXiang Li                       false, false)
10585285be9SXiang Li INITIALIZE_PASS_END(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false,
10685285be9SXiang Li                     false)
10785285be9SXiang Li 
createDXILOpLoweringLegacyPass()10885285be9SXiang Li ModulePass *llvm::createDXILOpLoweringLegacyPass() {
10985285be9SXiang Li   return new DXILOpLoweringLegacy();
11085285be9SXiang Li }
111