111 lines
3.3 KiB
C++
111 lines
3.3 KiB
C++
//===- 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();
|
|
}
|