LLVM 19.0.0git
DXILOpLowering.cpp
Go to the documentation of this file.
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"
15#include "DXILOpBuilder.h"
16#include "DirectX.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/Instruction.h"
21#include "llvm/IR/Intrinsics.h"
22#include "llvm/IR/IntrinsicsDirectX.h"
23#include "llvm/IR/Module.h"
24#include "llvm/IR/PassManager.h"
25#include "llvm/Pass.h"
27
28#define DEBUG_TYPE "dxil-op-lower"
29
30using namespace llvm;
31using namespace llvm::dxil;
32
34 switch (F.getIntrinsicID()) {
35 case Intrinsic::dx_dot2:
36 case Intrinsic::dx_dot3:
37 case Intrinsic::dx_dot4:
38 return true;
39 }
40 return false;
41}
42
44 SmallVector<Value *, 4> ExtractedElements;
45 auto *VecArg = dyn_cast<FixedVectorType>(Arg->getType());
46 for (unsigned I = 0; I < VecArg->getNumElements(); ++I) {
47 Value *Index = ConstantInt::get(Type::getInt32Ty(Arg->getContext()), I);
48 Value *ExtractedElement = Builder.CreateExtractElement(Arg, Index);
49 ExtractedElements.push_back(ExtractedElement);
50 }
51 return ExtractedElements;
52}
53
55 IRBuilder<> &Builder) {
56 // Note: arg[NumOperands-1] is a pointer and is not needed by our flattening.
57 unsigned NumOperands = Orig->getNumOperands() - 1;
58 assert(NumOperands > 0);
59 Value *Arg0 = Orig->getOperand(0);
60 [[maybe_unused]] auto *VecArg0 = dyn_cast<FixedVectorType>(Arg0->getType());
61 assert(VecArg0);
62 SmallVector<Value *> NewOperands = populateOperands(Arg0, Builder);
63 for (unsigned I = 1; I < NumOperands; ++I) {
64 Value *Arg = Orig->getOperand(I);
65 [[maybe_unused]] auto *VecArg = dyn_cast<FixedVectorType>(Arg->getType());
66 assert(VecArg);
67 assert(VecArg0->getElementType() == VecArg->getElementType());
68 assert(VecArg0->getNumElements() == VecArg->getNumElements());
69 auto NextOperandList = populateOperands(Arg, Builder);
70 NewOperands.append(NextOperandList.begin(), NextOperandList.end());
71 }
72 return NewOperands;
73}
74
75static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) {
76 IRBuilder<> B(M.getContext());
77 DXILOpBuilder DXILB(M, B);
78 Type *OverloadTy = DXILB.getOverloadTy(DXILOp, F.getFunctionType());
79 for (User *U : make_early_inc_range(F.users())) {
80 CallInst *CI = dyn_cast<CallInst>(U);
81 if (!CI)
82 continue;
83
85 Value *DXILOpArg = B.getInt32(static_cast<unsigned>(DXILOp));
86 Args.emplace_back(DXILOpArg);
87 B.SetInsertPoint(CI);
90 Args.append(NewArgs.begin(), NewArgs.end());
91 } else
92 Args.append(CI->arg_begin(), CI->arg_end());
93
94 CallInst *DXILCI =
95 DXILB.createDXILOpCall(DXILOp, F.getReturnType(), OverloadTy, Args);
96
97 CI->replaceAllUsesWith(DXILCI);
98 CI->eraseFromParent();
99 }
100 if (F.user_empty())
101 F.eraseFromParent();
102}
103
104static bool lowerIntrinsics(Module &M) {
105 bool Updated = false;
106
107#define DXIL_OP_INTRINSIC_MAP
108#include "DXILOperation.inc"
109#undef DXIL_OP_INTRINSIC_MAP
110
111 for (Function &F : make_early_inc_range(M.functions())) {
112 if (!F.isDeclaration())
113 continue;
114 Intrinsic::ID ID = F.getIntrinsicID();
116 continue;
117 auto LowerIt = LowerMap.find(ID);
118 if (LowerIt == LowerMap.end())
119 continue;
120 lowerIntrinsic(LowerIt->second, F, M);
121 Updated = true;
122 }
123 return Updated;
124}
125
126namespace {
127/// A pass that transforms external global definitions into declarations.
128class DXILOpLowering : public PassInfoMixin<DXILOpLowering> {
129public:
131 if (lowerIntrinsics(M))
133 return PreservedAnalyses::all();
134 }
135};
136} // namespace
137
138namespace {
139class DXILOpLoweringLegacy : public ModulePass {
140public:
141 bool runOnModule(Module &M) override { return lowerIntrinsics(M); }
142 StringRef getPassName() const override { return "DXIL Op Lowering"; }
143 DXILOpLoweringLegacy() : ModulePass(ID) {}
144
145 static char ID; // Pass identification.
146 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
147 // Specify the passes that your pass depends on
149 }
150};
151char DXILOpLoweringLegacy::ID = 0;
152} // end anonymous namespace
153
154INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering",
155 false, false)
156INITIALIZE_PASS_END(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false,
157 false)
158
160 return new DXILOpLoweringLegacy();
161}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isVectorArgExpansion(Function &F)
static SmallVector< Value * > argVectorFlatten(CallInst *Orig, IRBuilder<> &Builder)
static SmallVector< Value * > populateOperands(Value *Arg, IRBuilder<> &Builder)
static bool lowerIntrinsics(Module &M)
DXIL Op Lowering
#define DEBUG_TYPE
static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M)
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:321
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Definition: InstrTypes.h:1662
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
Definition: InstrTypes.h:1668
This class represents a function call, abstracting a target machine's calling convention.
This class represents an Operation in the Expression.
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2460
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2666
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:109
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:115
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:696
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static IntegerType * getInt32Ty(LLVMContext &C)
Value * getOperand(unsigned i) const
Definition: User.h:169
unsigned getNumOperands() const
Definition: User.h:191
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:1074
Type * getOverloadTy(dxil::OpCode OpCode, FunctionType *FT)
CallInst * createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy, Type *OverloadTy, SmallVector< Value * > Args)
Create an instruction that calls DXIL Op with return type, specified opcode, and call arguments.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:656
ModulePass * createDXILOpLoweringLegacyPass()
Pass to lowering LLVM intrinsic call to DXIL op function call.
A CRTP mix-in to automatically provide informational APIs needed for passes.
Definition: PassManager.h:74