| //===- DXILOpLower.cpp - Lowering LLVM intrinsic to DIXLOp function -------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// | |
| /// \file This file contains passes and utilities to lower llvm intrinsic call | |
| /// to DXILOp function call. | |
| //===----------------------------------------------------------------------===// | |
| #include "DXILConstants.h" | |
| #include "DXILOpBuilder.h" | |
| #include "DirectX.h" | |
| #include "llvm/ADT/SmallVector.h" | |
| #include "llvm/CodeGen/Passes.h" | |
| #include "llvm/IR/IRBuilder.h" | |
| #include "llvm/IR/Instruction.h" | |
| #include "llvm/IR/Intrinsics.h" | |
| #include "llvm/IR/IntrinsicsDirectX.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/IR/PassManager.h" | |
| #include "llvm/Pass.h" | |
| #include "llvm/Support/ErrorHandling.h" | |
| #define DEBUG_TYPE "dxil-op-lower" | |
| using namespace llvm; | |
| using namespace llvm::dxil; | |
| static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { | |
| IRBuilder<> B(M.getContext()); | |
| Value *DXILOpArg = B.getInt32(static_cast<unsigned>(DXILOp)); | |
| DXILOpBuilder DXILB(M, B); | |
| Type *OverloadTy = | |
| DXILB.getOverloadTy(DXILOp, F.getFunctionType(), /*NoOpCodeParam*/ true); | |
| for (User *U : make_early_inc_range(F.users())) { | |
| CallInst *CI = dyn_cast<CallInst>(U); | |
| if (!CI) | |
| continue; | |
| SmallVector<Value *> Args; | |
| Args.emplace_back(DXILOpArg); | |
| Args.append(CI->arg_begin(), CI->arg_end()); | |
| B.SetInsertPoint(CI); | |
| CallInst *DXILCI = DXILB.createDXILOpCall(DXILOp, OverloadTy, CI->args()); | |
| CI->replaceAllUsesWith(DXILCI); | |
| CI->eraseFromParent(); | |
| } | |
| if (F.user_empty()) | |
| F.eraseFromParent(); | |
| } | |
| static bool lowerIntrinsics(Module &M) { | |
| bool Updated = false; | |
| #define DXIL_OP_INTRINSIC_MAP | |
| #include "DXILOperation.inc" | |
| #undef DXIL_OP_INTRINSIC_MAP | |
| for (Function &F : make_early_inc_range(M.functions())) { | |
| if (!F.isDeclaration()) | |
| continue; | |
| Intrinsic::ID ID = F.getIntrinsicID(); | |
| if (ID == Intrinsic::not_intrinsic) | |
| continue; | |
| auto LowerIt = LowerMap.find(ID); | |
| if (LowerIt == LowerMap.end()) | |
| continue; | |
| lowerIntrinsic(LowerIt->second, F, M); | |
| Updated = true; | |
| } | |
| return Updated; | |
| } | |
| namespace { | |
| /// A pass that transforms external global definitions into declarations. | |
| class DXILOpLowering : public PassInfoMixin<DXILOpLowering> { | |
| public: | |
| PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { | |
| if (lowerIntrinsics(M)) | |
| return PreservedAnalyses::none(); | |
| return PreservedAnalyses::all(); | |
| } | |
| }; | |
| } // namespace | |
| namespace { | |
| class DXILOpLoweringLegacy : public ModulePass { | |
| public: | |
| bool runOnModule(Module &M) override { return lowerIntrinsics(M); } | |
| StringRef getPassName() const override { return "DXIL Op Lowering"; } | |
| DXILOpLoweringLegacy() : ModulePass(ID) {} | |
| static char ID; // Pass identification. | |
| }; | |
| char DXILOpLoweringLegacy::ID = 0; | |
| } // end anonymous namespace | |
| INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", | |
| false, false) | |
| INITIALIZE_PASS_END(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false, | |
| false) | |
| ModulePass *llvm::createDXILOpLoweringLegacyPass() { | |
| return new DXILOpLoweringLegacy(); | |
| } |