LLVM 20.0.0git
DXILIntrinsicExpansion.cpp
Go to the documentation of this file.
1//===- DXILIntrinsicExpansion.cpp - Prepare LLVM Module for DXIL encoding--===//
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 DXIL intrinsic expansions for those that don't have
10// opcodes in DirectX Intermediate Language (DXIL).
11//===----------------------------------------------------------------------===//
12
14#include "DirectX.h"
15#include "llvm/ADT/STLExtras.h"
17#include "llvm/CodeGen/Passes.h"
18#include "llvm/IR/IRBuilder.h"
19#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/IR/Type.h"
26#include "llvm/Pass.h"
29
30#define DEBUG_TYPE "dxil-intrinsic-expansion"
31
32using namespace llvm;
33
35 switch (F.getIntrinsicID()) {
36 case Intrinsic::abs:
37 case Intrinsic::exp:
38 case Intrinsic::log:
39 case Intrinsic::log10:
40 case Intrinsic::pow:
41 case Intrinsic::dx_any:
42 case Intrinsic::dx_clamp:
43 case Intrinsic::dx_uclamp:
44 case Intrinsic::dx_lerp:
45 case Intrinsic::dx_length:
46 case Intrinsic::dx_normalize:
47 case Intrinsic::dx_sdot:
48 case Intrinsic::dx_udot:
49 return true;
50 }
51 return false;
52}
53
54static bool expandAbs(CallInst *Orig) {
55 Value *X = Orig->getOperand(0);
56 IRBuilder<> Builder(Orig->getParent());
57 Builder.SetInsertPoint(Orig);
58 Type *Ty = X->getType();
59 Type *EltTy = Ty->getScalarType();
60 Constant *Zero = Ty->isVectorTy()
63 cast<FixedVectorType>(Ty)->getNumElements()),
64 ConstantInt::get(EltTy, 0))
65 : ConstantInt::get(EltTy, 0);
66 auto *V = Builder.CreateSub(Zero, X);
67 auto *MaxCall =
68 Builder.CreateIntrinsic(Ty, Intrinsic::smax, {X, V}, nullptr, "dx.max");
69 Orig->replaceAllUsesWith(MaxCall);
70 Orig->eraseFromParent();
71 return true;
72}
73
74static bool expandIntegerDot(CallInst *Orig, Intrinsic::ID DotIntrinsic) {
75 assert(DotIntrinsic == Intrinsic::dx_sdot ||
76 DotIntrinsic == Intrinsic::dx_udot);
77 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
78 ? Intrinsic::dx_imad
79 : Intrinsic::dx_umad;
80 Value *A = Orig->getOperand(0);
81 Value *B = Orig->getOperand(1);
82 [[maybe_unused]] Type *ATy = A->getType();
83 [[maybe_unused]] Type *BTy = B->getType();
84 assert(ATy->isVectorTy() && BTy->isVectorTy());
85
86 IRBuilder<> Builder(Orig->getParent());
87 Builder.SetInsertPoint(Orig);
88
89 auto *AVec = dyn_cast<FixedVectorType>(A->getType());
90 Value *Elt0 = Builder.CreateExtractElement(A, (uint64_t)0);
91 Value *Elt1 = Builder.CreateExtractElement(B, (uint64_t)0);
92 Value *Result = Builder.CreateMul(Elt0, Elt1);
93 for (unsigned I = 1; I < AVec->getNumElements(); I++) {
94 Elt0 = Builder.CreateExtractElement(A, I);
95 Elt1 = Builder.CreateExtractElement(B, I);
96 Result = Builder.CreateIntrinsic(Result->getType(), MadIntrinsic,
97 ArrayRef<Value *>{Elt0, Elt1, Result},
98 nullptr, "dx.mad");
99 }
100 Orig->replaceAllUsesWith(Result);
101 Orig->eraseFromParent();
102 return true;
103}
104
105static bool expandExpIntrinsic(CallInst *Orig) {
106 Value *X = Orig->getOperand(0);
107 IRBuilder<> Builder(Orig->getParent());
108 Builder.SetInsertPoint(Orig);
109 Type *Ty = X->getType();
110 Type *EltTy = Ty->getScalarType();
111 Constant *Log2eConst =
114 cast<FixedVectorType>(Ty)->getNumElements()),
115 ConstantFP::get(EltTy, numbers::log2ef))
116 : ConstantFP::get(EltTy, numbers::log2ef);
117 Value *NewX = Builder.CreateFMul(Log2eConst, X);
118 auto *Exp2Call =
119 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
120 Exp2Call->setTailCall(Orig->isTailCall());
121 Exp2Call->setAttributes(Orig->getAttributes());
122 Orig->replaceAllUsesWith(Exp2Call);
123 Orig->eraseFromParent();
124 return true;
125}
126
127static bool expandAnyIntrinsic(CallInst *Orig) {
128 Value *X = Orig->getOperand(0);
129 IRBuilder<> Builder(Orig->getParent());
130 Builder.SetInsertPoint(Orig);
131 Type *Ty = X->getType();
132 Type *EltTy = Ty->getScalarType();
133
134 if (!Ty->isVectorTy()) {
135 Value *Cond = EltTy->isFloatingPointTy()
136 ? Builder.CreateFCmpUNE(X, ConstantFP::get(EltTy, 0))
137 : Builder.CreateICmpNE(X, ConstantInt::get(EltTy, 0));
139 } else {
140 auto *XVec = dyn_cast<FixedVectorType>(Ty);
141 Value *Cond =
142 EltTy->isFloatingPointTy()
143 ? Builder.CreateFCmpUNE(
145 ElementCount::getFixed(XVec->getNumElements()),
146 ConstantFP::get(EltTy, 0)))
147 : Builder.CreateICmpNE(
149 ElementCount::getFixed(XVec->getNumElements()),
150 ConstantInt::get(EltTy, 0)));
151 Value *Result = Builder.CreateExtractElement(Cond, (uint64_t)0);
152 for (unsigned I = 1; I < XVec->getNumElements(); I++) {
153 Value *Elt = Builder.CreateExtractElement(Cond, I);
154 Result = Builder.CreateOr(Result, Elt);
155 }
156 Orig->replaceAllUsesWith(Result);
157 }
158 Orig->eraseFromParent();
159 return true;
160}
161
162static bool expandLengthIntrinsic(CallInst *Orig) {
163 Value *X = Orig->getOperand(0);
164 IRBuilder<> Builder(Orig->getParent());
165 Builder.SetInsertPoint(Orig);
166 Type *Ty = X->getType();
167 Type *EltTy = Ty->getScalarType();
168
169 // Though dx.length does work on scalar type, we can optimize it to just emit
170 // fabs, in CGBuiltin.cpp. We shouldn't see a scalar type here because
171 // CGBuiltin.cpp should have emitted a fabs call.
172 Value *Elt = Builder.CreateExtractElement(X, (uint64_t)0);
173 auto *XVec = dyn_cast<FixedVectorType>(Ty);
174 unsigned XVecSize = XVec->getNumElements();
175 if (!(Ty->isVectorTy() && XVecSize > 1))
176 report_fatal_error(Twine("Invalid input type for length intrinsic"),
177 /* gen_crash_diag=*/false);
178
179 Value *Sum = Builder.CreateFMul(Elt, Elt);
180 for (unsigned I = 1; I < XVecSize; I++) {
181 Elt = Builder.CreateExtractElement(X, I);
182 Value *Mul = Builder.CreateFMul(Elt, Elt);
183 Sum = Builder.CreateFAdd(Sum, Mul);
184 }
185 Value *Result = Builder.CreateIntrinsic(
186 EltTy, Intrinsic::sqrt, ArrayRef<Value *>{Sum}, nullptr, "elt.sqrt");
187
188 Orig->replaceAllUsesWith(Result);
189 Orig->eraseFromParent();
190 return true;
191}
192
193static bool expandLerpIntrinsic(CallInst *Orig) {
194 Value *X = Orig->getOperand(0);
195 Value *Y = Orig->getOperand(1);
196 Value *S = Orig->getOperand(2);
197 IRBuilder<> Builder(Orig->getParent());
198 Builder.SetInsertPoint(Orig);
199 auto *V = Builder.CreateFSub(Y, X);
200 V = Builder.CreateFMul(S, V);
201 auto *Result = Builder.CreateFAdd(X, V, "dx.lerp");
202 Orig->replaceAllUsesWith(Result);
203 Orig->eraseFromParent();
204 return true;
205}
206
207static bool expandLogIntrinsic(CallInst *Orig,
208 float LogConstVal = numbers::ln2f) {
209 Value *X = Orig->getOperand(0);
210 IRBuilder<> Builder(Orig->getParent());
211 Builder.SetInsertPoint(Orig);
212 Type *Ty = X->getType();
213 Type *EltTy = Ty->getScalarType();
214 Constant *Ln2Const =
217 cast<FixedVectorType>(Ty)->getNumElements()),
218 ConstantFP::get(EltTy, LogConstVal))
219 : ConstantFP::get(EltTy, LogConstVal);
220 auto *Log2Call =
221 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
222 Log2Call->setTailCall(Orig->isTailCall());
223 Log2Call->setAttributes(Orig->getAttributes());
224 auto *Result = Builder.CreateFMul(Ln2Const, Log2Call);
225 Orig->replaceAllUsesWith(Result);
226 Orig->eraseFromParent();
227 return true;
228}
229static bool expandLog10Intrinsic(CallInst *Orig) {
231}
232
234 Value *X = Orig->getOperand(0);
235 Type *Ty = Orig->getType();
236 Type *EltTy = Ty->getScalarType();
237 IRBuilder<> Builder(Orig->getParent());
238 Builder.SetInsertPoint(Orig);
239
240 auto *XVec = dyn_cast<FixedVectorType>(Ty);
241 if (!XVec) {
242 if (auto *constantFP = dyn_cast<ConstantFP>(X)) {
243 const APFloat &fpVal = constantFP->getValueAPF();
244 if (fpVal.isZero())
245 report_fatal_error(Twine("Invalid input scalar: length is zero"),
246 /* gen_crash_diag=*/false);
247 }
248 Value *Result = Builder.CreateFDiv(X, X);
249
250 Orig->replaceAllUsesWith(Result);
251 Orig->eraseFromParent();
252 return true;
253 }
254
255 Value *Elt = Builder.CreateExtractElement(X, (uint64_t)0);
256 unsigned XVecSize = XVec->getNumElements();
257 Value *DotProduct = nullptr;
258 // use the dot intrinsic corresponding to the vector size
259 switch (XVecSize) {
260 case 1:
261 report_fatal_error(Twine("Invalid input vector: length is zero"),
262 /* gen_crash_diag=*/false);
263 break;
264 case 2:
265 DotProduct = Builder.CreateIntrinsic(
266 EltTy, Intrinsic::dx_dot2, ArrayRef<Value *>{X, X}, nullptr, "dx.dot2");
267 break;
268 case 3:
269 DotProduct = Builder.CreateIntrinsic(
270 EltTy, Intrinsic::dx_dot3, ArrayRef<Value *>{X, X}, nullptr, "dx.dot3");
271 break;
272 case 4:
273 DotProduct = Builder.CreateIntrinsic(
274 EltTy, Intrinsic::dx_dot4, ArrayRef<Value *>{X, X}, nullptr, "dx.dot4");
275 break;
276 default:
277 report_fatal_error(Twine("Invalid input vector: vector size is invalid."),
278 /* gen_crash_diag=*/false);
279 }
280
281 // verify that the length is non-zero
282 // (if the dot product is non-zero, then the length is non-zero)
283 if (auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) {
284 const APFloat &fpVal = constantFP->getValueAPF();
285 if (fpVal.isZero())
286 report_fatal_error(Twine("Invalid input vector: length is zero"),
287 /* gen_crash_diag=*/false);
288 }
289
290 Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt,
291 ArrayRef<Value *>{DotProduct},
292 nullptr, "dx.rsqrt");
293
294 Value *MultiplicandVec = Builder.CreateVectorSplat(XVecSize, Multiplicand);
295 Value *Result = Builder.CreateFMul(X, MultiplicandVec);
296
297 Orig->replaceAllUsesWith(Result);
298 Orig->eraseFromParent();
299 return true;
300}
301
302static bool expandPowIntrinsic(CallInst *Orig) {
303
304 Value *X = Orig->getOperand(0);
305 Value *Y = Orig->getOperand(1);
306 Type *Ty = X->getType();
307 IRBuilder<> Builder(Orig->getParent());
308 Builder.SetInsertPoint(Orig);
309
310 auto *Log2Call =
311 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
312 auto *Mul = Builder.CreateFMul(Log2Call, Y);
313 auto *Exp2Call =
314 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2");
315 Exp2Call->setTailCall(Orig->isTailCall());
316 Exp2Call->setAttributes(Orig->getAttributes());
317 Orig->replaceAllUsesWith(Exp2Call);
318 Orig->eraseFromParent();
319 return true;
320}
321
323 Intrinsic::ID ClampIntrinsic) {
324 if (ClampIntrinsic == Intrinsic::dx_uclamp)
325 return Intrinsic::umax;
326 assert(ClampIntrinsic == Intrinsic::dx_clamp);
327 if (ElemTy->isVectorTy())
328 ElemTy = ElemTy->getScalarType();
329 if (ElemTy->isIntegerTy())
330 return Intrinsic::smax;
331 assert(ElemTy->isFloatingPointTy());
332 return Intrinsic::maxnum;
333}
334
336 Intrinsic::ID ClampIntrinsic) {
337 if (ClampIntrinsic == Intrinsic::dx_uclamp)
338 return Intrinsic::umin;
339 assert(ClampIntrinsic == Intrinsic::dx_clamp);
340 if (ElemTy->isVectorTy())
341 ElemTy = ElemTy->getScalarType();
342 if (ElemTy->isIntegerTy())
343 return Intrinsic::smin;
344 assert(ElemTy->isFloatingPointTy());
345 return Intrinsic::minnum;
346}
347
348static bool expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic) {
349 Value *X = Orig->getOperand(0);
350 Value *Min = Orig->getOperand(1);
351 Value *Max = Orig->getOperand(2);
352 Type *Ty = X->getType();
353 IRBuilder<> Builder(Orig->getParent());
354 Builder.SetInsertPoint(Orig);
355 auto *MaxCall = Builder.CreateIntrinsic(
356 Ty, getMaxForClamp(Ty, ClampIntrinsic), {X, Min}, nullptr, "dx.max");
357 auto *MinCall =
358 Builder.CreateIntrinsic(Ty, getMinForClamp(Ty, ClampIntrinsic),
359 {MaxCall, Max}, nullptr, "dx.min");
360
361 Orig->replaceAllUsesWith(MinCall);
362 Orig->eraseFromParent();
363 return true;
364}
365
366static bool expandIntrinsic(Function &F, CallInst *Orig) {
367 switch (F.getIntrinsicID()) {
368 case Intrinsic::abs:
369 return expandAbs(Orig);
370 case Intrinsic::exp:
371 return expandExpIntrinsic(Orig);
372 case Intrinsic::log:
373 return expandLogIntrinsic(Orig);
374 case Intrinsic::log10:
375 return expandLog10Intrinsic(Orig);
376 case Intrinsic::pow:
377 return expandPowIntrinsic(Orig);
378 case Intrinsic::dx_any:
379 return expandAnyIntrinsic(Orig);
380 case Intrinsic::dx_uclamp:
381 case Intrinsic::dx_clamp:
382 return expandClampIntrinsic(Orig, F.getIntrinsicID());
383 case Intrinsic::dx_lerp:
384 return expandLerpIntrinsic(Orig);
385 case Intrinsic::dx_length:
386 return expandLengthIntrinsic(Orig);
387 case Intrinsic::dx_normalize:
388 return expandNormalizeIntrinsic(Orig);
389 case Intrinsic::dx_sdot:
390 case Intrinsic::dx_udot:
391 return expandIntegerDot(Orig, F.getIntrinsicID());
392 }
393 return false;
394}
395
397 for (auto &F : make_early_inc_range(M.functions())) {
399 continue;
400 bool IntrinsicExpanded = false;
401 for (User *U : make_early_inc_range(F.users())) {
402 auto *IntrinsicCall = dyn_cast<CallInst>(U);
403 if (!IntrinsicCall)
404 continue;
405 IntrinsicExpanded = expandIntrinsic(F, IntrinsicCall);
406 }
407 if (F.user_empty() && IntrinsicExpanded)
408 F.eraseFromParent();
409 }
410 return true;
411}
412
415 if (expansionIntrinsics(M))
417 return PreservedAnalyses::all();
418}
419
421 return expansionIntrinsics(M);
422}
423
425
427 "DXIL Intrinsic Expansion", false, false)
429 "DXIL Intrinsic Expansion", false, false)
430
432 return new DXILIntrinsicExpansionLegacy();
433}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
DXIL Intrinsic Expansion
static bool expandIntrinsic(Function &F, CallInst *Orig)
static bool expandLog10Intrinsic(CallInst *Orig)
static bool expansionIntrinsics(Module &M)
static bool expandAbs(CallInst *Orig)
static bool expandExpIntrinsic(CallInst *Orig)
static bool expandLengthIntrinsic(CallInst *Orig)
static bool expandPowIntrinsic(CallInst *Orig)
static bool expandAnyIntrinsic(CallInst *Orig)
static bool expandIntegerDot(CallInst *Orig, Intrinsic::ID DotIntrinsic)
static bool expandLogIntrinsic(CallInst *Orig, float LogConstVal=numbers::ln2f)
static Intrinsic::ID getMaxForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic)
static Intrinsic::ID getMinForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic)
static bool expandNormalizeIntrinsic(CallInst *Orig)
static bool isIntrinsicExpansion(Function &F)
static bool expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic)
static bool expandLerpIntrinsic(CallInst *Orig)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define DEBUG_TYPE
#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.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:57
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getNumElements(Type *Ty)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
BinaryOperator * Mul
bool isZero() const
Definition: APFloat.h:1356
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
AttributeList getAttributes() const
Return the parameter attributes for this call.
Definition: InstrTypes.h:1542
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
void setTailCall(bool IsTc=true)
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
Definition: Constants.cpp:1450
This is an important base class in LLVM.
Definition: Constant.h:42
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition: TypeSize.h:311
Value * CreateFSub(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1565
Value * CreateFDiv(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1619
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2468
Value * CreateFAdd(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1538
Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Definition: IRBuilder.cpp:1193
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:933
Value * CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2354
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2253
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1349
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1502
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:177
Value * CreateFMul(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1592
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1366
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2674
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:92
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:114
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:261
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition: Type.h:184
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:224
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition: Type.h:343
Value * getOperand(unsigned i) const
Definition: User.h:169
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
const ParentTy * getParent() const
Definition: ilist_node.h:32
constexpr float ln10f
Definition: MathExtras.h:65
constexpr float log2ef
Definition: MathExtras.h:66
constexpr float ln2f
Definition: MathExtras.h:64
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
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
ModulePass * createDXILIntrinsicExpansionLegacyPass()
Pass to expand intrinsic operations that lack DXIL opCodes.