LLVM 22.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/InstrTypes.h"
20#include "llvm/IR/Instruction.h"
22#include "llvm/IR/Intrinsics.h"
23#include "llvm/IR/IntrinsicsDirectX.h"
24#include "llvm/IR/Module.h"
25#include "llvm/IR/PassManager.h"
26#include "llvm/IR/Type.h"
27#include "llvm/Pass.h"
31
32#define DEBUG_TYPE "dxil-intrinsic-expansion"
33
34using namespace llvm;
35
37
38public:
39 bool runOnModule(Module &M) override;
41
42 static char ID; // Pass identification.
43};
44
45static bool resourceAccessNeeds64BitExpansion(Module *M, Type *OverloadTy,
46 bool IsRaw) {
47 if (IsRaw && M->getTargetTriple().getDXILVersion() > VersionTuple(1, 2))
48 return false;
49
50 Type *ScalarTy = OverloadTy->getScalarType();
51 return ScalarTy->isDoubleTy() || ScalarTy->isIntegerTy(64);
52}
53
55 Module *M = Orig->getModule();
56 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
57 return nullptr;
58
59 Value *Val = Orig->getOperand(0);
60 Type *ValTy = Val->getType();
61 if (!ValTy->getScalarType()->isHalfTy())
62 return nullptr;
63
64 IRBuilder<> Builder(Orig);
65 Type *IType = Type::getInt16Ty(M->getContext());
66 Constant *PosInf =
67 ValTy->isVectorTy()
71 ConstantInt::get(IType, 0x7c00))
72 : ConstantInt::get(IType, 0x7c00);
73
74 Constant *NegInf =
75 ValTy->isVectorTy()
79 ConstantInt::get(IType, 0xfc00))
80 : ConstantInt::get(IType, 0xfc00);
81
82 Value *IVal = Builder.CreateBitCast(Val, PosInf->getType());
83 Value *B1 = Builder.CreateICmpEQ(IVal, PosInf);
84 Value *B2 = Builder.CreateICmpEQ(IVal, NegInf);
85 Value *B3 = Builder.CreateOr(B1, B2);
86 return B3;
87}
88
90 Module *M = Orig->getModule();
91 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
92 return nullptr;
93
94 Value *Val = Orig->getOperand(0);
95 Type *ValTy = Val->getType();
96 if (!ValTy->getScalarType()->isHalfTy())
97 return nullptr;
98
99 IRBuilder<> Builder(Orig);
100 Type *IType = Type::getInt16Ty(M->getContext());
101
102 Constant *ExpBitMask =
103 ValTy->isVectorTy()
107 ConstantInt::get(IType, 0x7c00))
108 : ConstantInt::get(IType, 0x7c00);
109 Constant *SigBitMask =
110 ValTy->isVectorTy()
114 ConstantInt::get(IType, 0x3ff))
115 : ConstantInt::get(IType, 0x3ff);
116
117 Constant *Zero =
118 ValTy->isVectorTy()
122 ConstantInt::get(IType, 0))
123 : ConstantInt::get(IType, 0);
124
125 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
126 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
127 Value *B1 = Builder.CreateICmpEQ(Exp, ExpBitMask);
128
129 Value *Sig = Builder.CreateAnd(IVal, SigBitMask);
130 Value *B2 = Builder.CreateICmpNE(Sig, Zero);
131 Value *B3 = Builder.CreateAnd(B1, B2);
132 return B3;
133}
134
136 Module *M = Orig->getModule();
137 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
138 return nullptr;
139
140 Value *Val = Orig->getOperand(0);
141 Type *ValTy = Val->getType();
142 if (!ValTy->getScalarType()->isHalfTy())
143 return nullptr;
144
145 IRBuilder<> Builder(Orig);
146 Type *IType = Type::getInt16Ty(M->getContext());
147
148 Constant *ExpBitMask =
149 ValTy->isVectorTy()
153 ConstantInt::get(IType, 0x7c00))
154 : ConstantInt::get(IType, 0x7c00);
155
156 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
157 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
158 Value *B1 = Builder.CreateICmpNE(Exp, ExpBitMask);
159 return B1;
160}
161
163 Module *M = Orig->getModule();
164 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
165 return nullptr;
166
167 Value *Val = Orig->getOperand(0);
168 Type *ValTy = Val->getType();
169 if (!ValTy->getScalarType()->isHalfTy())
170 return nullptr;
171
172 IRBuilder<> Builder(Orig);
173 Type *IType = Type::getInt16Ty(M->getContext());
174
175 Constant *ExpBitMask =
176 ValTy->isVectorTy()
180 ConstantInt::get(IType, 0x7c00))
181 : ConstantInt::get(IType, 0x7c00);
182 Constant *Zero =
183 ValTy->isVectorTy()
187 ConstantInt::get(IType, 0))
188 : ConstantInt::get(IType, 0);
189
190 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
191 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
192 Value *NotAllZeroes = Builder.CreateICmpNE(Exp, Zero);
193 Value *NotAllOnes = Builder.CreateICmpNE(Exp, ExpBitMask);
194 Value *B1 = Builder.CreateAnd(NotAllZeroes, NotAllOnes);
195 return B1;
196}
197
199 switch (F.getIntrinsicID()) {
200 case Intrinsic::abs:
201 case Intrinsic::atan2:
202 case Intrinsic::exp:
203 case Intrinsic::is_fpclass:
204 case Intrinsic::log:
205 case Intrinsic::log10:
206 case Intrinsic::pow:
207 case Intrinsic::powi:
208 case Intrinsic::dx_all:
209 case Intrinsic::dx_any:
210 case Intrinsic::dx_cross:
211 case Intrinsic::dx_uclamp:
212 case Intrinsic::dx_sclamp:
213 case Intrinsic::dx_nclamp:
214 case Intrinsic::dx_degrees:
215 case Intrinsic::dx_isinf:
216 case Intrinsic::dx_isnan:
217 case Intrinsic::dx_lerp:
218 case Intrinsic::dx_normalize:
219 case Intrinsic::dx_fdot:
220 case Intrinsic::dx_sdot:
221 case Intrinsic::dx_udot:
222 case Intrinsic::dx_sign:
223 case Intrinsic::dx_step:
224 case Intrinsic::dx_radians:
225 case Intrinsic::usub_sat:
226 case Intrinsic::vector_reduce_add:
227 case Intrinsic::vector_reduce_fadd:
228 return true;
229 case Intrinsic::dx_resource_load_rawbuffer:
231 F.getParent(), F.getReturnType()->getStructElementType(0),
232 /*IsRaw*/ true);
233 case Intrinsic::dx_resource_load_typedbuffer:
235 F.getParent(), F.getReturnType()->getStructElementType(0),
236 /*IsRaw*/ false);
237 case Intrinsic::dx_resource_store_rawbuffer:
239 F.getParent(), F.getFunctionType()->getParamType(3), /*IsRaw*/ true);
240 case Intrinsic::dx_resource_store_typedbuffer:
242 F.getParent(), F.getFunctionType()->getParamType(2), /*IsRaw*/ false);
243 }
244 return false;
245}
246
248 Value *A = Orig->getArgOperand(0);
249 Value *B = Orig->getArgOperand(1);
250 Type *Ty = A->getType();
251
252 IRBuilder<> Builder(Orig);
253
254 Value *Cmp = Builder.CreateICmpULT(A, B, "usub.cmp");
255 Value *Sub = Builder.CreateSub(A, B, "usub.sub");
256 Value *Zero = ConstantInt::get(Ty, 0);
257 return Builder.CreateSelect(Cmp, Zero, Sub, "usub.sat");
258}
259
260static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
261 assert(IntrinsicId == Intrinsic::vector_reduce_add ||
262 IntrinsicId == Intrinsic::vector_reduce_fadd);
263
264 IRBuilder<> Builder(Orig);
265 bool IsFAdd = (IntrinsicId == Intrinsic::vector_reduce_fadd);
266
267 Value *X = Orig->getOperand(IsFAdd ? 1 : 0);
268 Type *Ty = X->getType();
269 auto *XVec = dyn_cast<FixedVectorType>(Ty);
270 unsigned XVecSize = XVec->getNumElements();
271 Value *Sum = Builder.CreateExtractElement(X, static_cast<uint64_t>(0));
272
273 // Handle the initial start value for floating-point addition.
274 if (IsFAdd) {
275 Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
276 if (StartValue && !StartValue->isZeroValue())
277 Sum = Builder.CreateFAdd(Sum, StartValue);
278 }
279
280 // Accumulate the remaining vector elements.
281 for (unsigned I = 1; I < XVecSize; I++) {
282 Value *Elt = Builder.CreateExtractElement(X, I);
283 if (IsFAdd)
284 Sum = Builder.CreateFAdd(Sum, Elt);
285 else
286 Sum = Builder.CreateAdd(Sum, Elt);
287 }
288
289 return Sum;
290}
291
292static Value *expandAbs(CallInst *Orig) {
293 Value *X = Orig->getOperand(0);
294 IRBuilder<> Builder(Orig);
295 Type *Ty = X->getType();
296 Type *EltTy = Ty->getScalarType();
297 Constant *Zero = Ty->isVectorTy()
301 ConstantInt::get(EltTy, 0))
302 : ConstantInt::get(EltTy, 0);
303 auto *V = Builder.CreateSub(Zero, X);
304 return Builder.CreateIntrinsic(Ty, Intrinsic::smax, {X, V}, nullptr,
305 "dx.max");
306}
307
309
310 VectorType *VT = cast<VectorType>(Orig->getType());
312 reportFatalUsageError("return vector must have exactly 3 elements");
313
314 Value *op0 = Orig->getOperand(0);
315 Value *op1 = Orig->getOperand(1);
316 IRBuilder<> Builder(Orig);
317
318 Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0, "x0");
319 Value *op0_y = Builder.CreateExtractElement(op0, 1, "x1");
320 Value *op0_z = Builder.CreateExtractElement(op0, 2, "x2");
321
322 Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "y0");
323 Value *op1_y = Builder.CreateExtractElement(op1, 1, "y1");
324 Value *op1_z = Builder.CreateExtractElement(op1, 2, "y2");
325
326 auto MulSub = [&](Value *x0, Value *y0, Value *x1, Value *y1) -> Value * {
327 Value *xy = Builder.CreateFMul(x0, y1);
328 Value *yx = Builder.CreateFMul(y0, x1);
329 return Builder.CreateFSub(xy, yx, Orig->getName());
330 };
331
332 Value *yz_zy = MulSub(op0_y, op0_z, op1_y, op1_z);
333 Value *zx_xz = MulSub(op0_z, op0_x, op1_z, op1_x);
334 Value *xy_yx = MulSub(op0_x, op0_y, op1_x, op1_y);
335
336 Value *cross = PoisonValue::get(VT);
337 cross = Builder.CreateInsertElement(cross, yz_zy, (uint64_t)0);
338 cross = Builder.CreateInsertElement(cross, zx_xz, 1);
339 cross = Builder.CreateInsertElement(cross, xy_yx, 2);
340 return cross;
341}
342
343// Create appropriate DXIL float dot intrinsic for the given A and B operands
344// The appropriate opcode will be determined by the size of the operands
345// The dot product is placed in the position indicated by Orig
347 Type *ATy = A->getType();
348 [[maybe_unused]] Type *BTy = B->getType();
349 assert(ATy->isVectorTy() && BTy->isVectorTy());
350
351 IRBuilder<> Builder(Orig);
352
353 auto *AVec = dyn_cast<FixedVectorType>(ATy);
354
356
357 Intrinsic::ID DotIntrinsic = Intrinsic::dx_dot4;
358 int NumElts = AVec->getNumElements();
359 switch (NumElts) {
360 case 2:
361 DotIntrinsic = Intrinsic::dx_dot2;
362 break;
363 case 3:
364 DotIntrinsic = Intrinsic::dx_dot3;
365 break;
366 case 4:
367 DotIntrinsic = Intrinsic::dx_dot4;
368 break;
369 default:
371 "Invalid dot product input vector: length is outside 2-4");
372 return nullptr;
373 }
374
376 for (int I = 0; I < NumElts; ++I)
377 Args.push_back(Builder.CreateExtractElement(A, Builder.getInt32(I)));
378 for (int I = 0; I < NumElts; ++I)
379 Args.push_back(Builder.CreateExtractElement(B, Builder.getInt32(I)));
380 return Builder.CreateIntrinsic(ATy->getScalarType(), DotIntrinsic, Args,
381 nullptr, "dot");
382}
383
384// Create the appropriate DXIL float dot intrinsic for the operands of Orig
385// The appropriate opcode will be determined by the size of the operands
386// The dot product is placed in the position indicated by Orig
388 return expandFloatDotIntrinsic(Orig, Orig->getOperand(0),
389 Orig->getOperand(1));
390}
391
392// Expand integer dot product to multiply and add ops
394 Intrinsic::ID DotIntrinsic) {
395 assert(DotIntrinsic == Intrinsic::dx_sdot ||
396 DotIntrinsic == Intrinsic::dx_udot);
397 Value *A = Orig->getOperand(0);
398 Value *B = Orig->getOperand(1);
399 Type *ATy = A->getType();
400 [[maybe_unused]] Type *BTy = B->getType();
401 assert(ATy->isVectorTy() && BTy->isVectorTy());
402
403 IRBuilder<> Builder(Orig);
404
405 auto *AVec = dyn_cast<FixedVectorType>(ATy);
406
408
409 Value *Result;
410 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
411 ? Intrinsic::dx_imad
412 : Intrinsic::dx_umad;
413 Value *Elt0 = Builder.CreateExtractElement(A, (uint64_t)0);
414 Value *Elt1 = Builder.CreateExtractElement(B, (uint64_t)0);
415 Result = Builder.CreateMul(Elt0, Elt1);
416 for (unsigned I = 1; I < AVec->getNumElements(); I++) {
417 Elt0 = Builder.CreateExtractElement(A, I);
418 Elt1 = Builder.CreateExtractElement(B, I);
419 Result = Builder.CreateIntrinsic(Result->getType(), MadIntrinsic,
420 ArrayRef<Value *>{Elt0, Elt1, Result},
421 nullptr, "dx.mad");
422 }
423 return Result;
424}
425
427 Value *X = Orig->getOperand(0);
428 IRBuilder<> Builder(Orig);
429 Type *Ty = X->getType();
430 Type *EltTy = Ty->getScalarType();
431 Constant *Log2eConst =
432 Ty->isVectorTy() ? ConstantVector::getSplat(
435 ConstantFP::get(EltTy, numbers::log2ef))
436 : ConstantFP::get(EltTy, numbers::log2ef);
437 Value *NewX = Builder.CreateFMul(Log2eConst, X);
438 auto *Exp2Call =
439 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
440 Exp2Call->setTailCall(Orig->isTailCall());
441 Exp2Call->setAttributes(Orig->getAttributes());
442 return Exp2Call;
443}
444
446 Value *T = Orig->getArgOperand(1);
447 auto *TCI = dyn_cast<ConstantInt>(T);
448
449 // These FPClassTest cases have DXIL opcodes, so they will be handled in
450 // DXIL Op Lowering instead for all non f16 cases.
451 switch (TCI->getZExtValue()) {
453 return expand16BitIsInf(Orig);
455 return expand16BitIsNaN(Orig);
457 return expand16BitIsNormal(Orig);
459 return expand16BitIsFinite(Orig);
460 }
461
462 IRBuilder<> Builder(Orig);
463
464 Value *F = Orig->getArgOperand(0);
465 Type *FTy = F->getType();
466 unsigned FNumElem = 0; // 0 => F is not a vector
467
468 unsigned BitWidth; // Bit width of F or the ElemTy of F
469 Type *BitCastTy; // An IntNTy of the same bitwidth as F or ElemTy of F
470
471 if (auto *FVecTy = dyn_cast<FixedVectorType>(FTy)) {
472 Type *ElemTy = FVecTy->getElementType();
473 FNumElem = FVecTy->getNumElements();
474 BitWidth = ElemTy->getPrimitiveSizeInBits();
475 BitCastTy = FixedVectorType::get(Builder.getIntNTy(BitWidth), FNumElem);
476 } else {
478 BitCastTy = Builder.getIntNTy(BitWidth);
479 }
480
481 Value *FBitCast = Builder.CreateBitCast(F, BitCastTy);
482 switch (TCI->getZExtValue()) {
484 Value *NegZero =
485 ConstantInt::get(Builder.getIntNTy(BitWidth), 1 << (BitWidth - 1));
486 Value *RetVal;
487 if (FNumElem) {
488 Value *NegZeroSplat = Builder.CreateVectorSplat(FNumElem, NegZero);
489 RetVal =
490 Builder.CreateICmpEQ(FBitCast, NegZeroSplat, "is.fpclass.negzero");
491 } else
492 RetVal = Builder.CreateICmpEQ(FBitCast, NegZero, "is.fpclass.negzero");
493 return RetVal;
494 }
495 default:
496 reportFatalUsageError("Unsupported FPClassTest");
497 }
498}
499
501 Intrinsic::ID IntrinsicId) {
502 Value *X = Orig->getOperand(0);
503 IRBuilder<> Builder(Orig);
504 Type *Ty = X->getType();
505 Type *EltTy = Ty->getScalarType();
506
507 auto ApplyOp = [&Builder](Intrinsic::ID IntrinsicId, Value *Result,
508 Value *Elt) {
509 if (IntrinsicId == Intrinsic::dx_any)
510 return Builder.CreateOr(Result, Elt);
511 assert(IntrinsicId == Intrinsic::dx_all);
512 return Builder.CreateAnd(Result, Elt);
513 };
514
515 Value *Result = nullptr;
516 if (!Ty->isVectorTy()) {
517 Result = EltTy->isFloatingPointTy()
518 ? Builder.CreateFCmpUNE(X, ConstantFP::get(EltTy, 0))
519 : Builder.CreateICmpNE(X, ConstantInt::get(EltTy, 0));
520 } else {
521 auto *XVec = dyn_cast<FixedVectorType>(Ty);
522 Value *Cond =
523 EltTy->isFloatingPointTy()
524 ? Builder.CreateFCmpUNE(
526 ElementCount::getFixed(XVec->getNumElements()),
527 ConstantFP::get(EltTy, 0)))
528 : Builder.CreateICmpNE(
530 ElementCount::getFixed(XVec->getNumElements()),
531 ConstantInt::get(EltTy, 0)));
532 Result = Builder.CreateExtractElement(Cond, (uint64_t)0);
533 for (unsigned I = 1; I < XVec->getNumElements(); I++) {
534 Value *Elt = Builder.CreateExtractElement(Cond, I);
535 Result = ApplyOp(IntrinsicId, Result, Elt);
536 }
537 }
538 return Result;
539}
540
542 Value *X = Orig->getOperand(0);
543 Value *Y = Orig->getOperand(1);
544 Value *S = Orig->getOperand(2);
545 IRBuilder<> Builder(Orig);
546 auto *V = Builder.CreateFSub(Y, X);
547 V = Builder.CreateFMul(S, V);
548 return Builder.CreateFAdd(X, V, "dx.lerp");
549}
550
552 float LogConstVal = numbers::ln2f) {
553 Value *X = Orig->getOperand(0);
554 IRBuilder<> Builder(Orig);
555 Type *Ty = X->getType();
556 Type *EltTy = Ty->getScalarType();
557 Constant *Ln2Const =
558 Ty->isVectorTy() ? ConstantVector::getSplat(
561 ConstantFP::get(EltTy, LogConstVal))
562 : ConstantFP::get(EltTy, LogConstVal);
563 auto *Log2Call =
564 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
565 Log2Call->setTailCall(Orig->isTailCall());
566 Log2Call->setAttributes(Orig->getAttributes());
567 return Builder.CreateFMul(Ln2Const, Log2Call);
568}
572
573// Use dot product of vector operand with itself to calculate the length.
574// Divide the vector by that length to normalize it.
576 Value *X = Orig->getOperand(0);
577 Type *Ty = Orig->getType();
578 Type *EltTy = Ty->getScalarType();
579 IRBuilder<> Builder(Orig);
580
581 auto *XVec = dyn_cast<FixedVectorType>(Ty);
582 if (!XVec) {
583 if (auto *constantFP = dyn_cast<ConstantFP>(X)) {
584 const APFloat &fpVal = constantFP->getValueAPF();
585 if (fpVal.isZero())
586 reportFatalUsageError("Invalid input scalar: length is zero");
587 }
588 return Builder.CreateFDiv(X, X);
589 }
590
591 Value *DotProduct = expandFloatDotIntrinsic(Orig, X, X);
592
593 // verify that the length is non-zero
594 // (if the dot product is non-zero, then the length is non-zero)
595 if (auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) {
596 const APFloat &fpVal = constantFP->getValueAPF();
597 if (fpVal.isZero())
598 reportFatalUsageError("Invalid input vector: length is zero");
599 }
600
601 Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt,
602 ArrayRef<Value *>{DotProduct},
603 nullptr, "dx.rsqrt");
604
605 Value *MultiplicandVec =
606 Builder.CreateVectorSplat(XVec->getNumElements(), Multiplicand);
607 return Builder.CreateFMul(X, MultiplicandVec);
608}
609
611 Value *Y = Orig->getOperand(0);
612 Value *X = Orig->getOperand(1);
613 Type *Ty = X->getType();
614 IRBuilder<> Builder(Orig);
615 Builder.setFastMathFlags(Orig->getFastMathFlags());
616
617 Value *Tan = Builder.CreateFDiv(Y, X);
618
619 CallInst *Atan =
620 Builder.CreateIntrinsic(Ty, Intrinsic::atan, {Tan}, nullptr, "Elt.Atan");
621 Atan->setTailCall(Orig->isTailCall());
622 Atan->setAttributes(Orig->getAttributes());
623
624 // Modify atan result based on https://en.wikipedia.org/wiki/Atan2.
625 Constant *Pi = ConstantFP::get(Ty, llvm::numbers::pi);
626 Constant *HalfPi = ConstantFP::get(Ty, llvm::numbers::pi / 2);
627 Constant *NegHalfPi = ConstantFP::get(Ty, -llvm::numbers::pi / 2);
628 Constant *Zero = ConstantFP::get(Ty, 0);
629 Value *AtanAddPi = Builder.CreateFAdd(Atan, Pi);
630 Value *AtanSubPi = Builder.CreateFSub(Atan, Pi);
631
632 // x > 0 -> atan.
633 Value *Result = Atan;
634 Value *XLt0 = Builder.CreateFCmpOLT(X, Zero);
635 Value *XEq0 = Builder.CreateFCmpOEQ(X, Zero);
636 Value *YGe0 = Builder.CreateFCmpOGE(Y, Zero);
637 Value *YLt0 = Builder.CreateFCmpOLT(Y, Zero);
638
639 // x < 0, y >= 0 -> atan + pi.
640 Value *XLt0AndYGe0 = Builder.CreateAnd(XLt0, YGe0);
641 Result = Builder.CreateSelect(XLt0AndYGe0, AtanAddPi, Result);
642
643 // x < 0, y < 0 -> atan - pi.
644 Value *XLt0AndYLt0 = Builder.CreateAnd(XLt0, YLt0);
645 Result = Builder.CreateSelect(XLt0AndYLt0, AtanSubPi, Result);
646
647 // x == 0, y < 0 -> -pi/2
648 Value *XEq0AndYLt0 = Builder.CreateAnd(XEq0, YLt0);
649 Result = Builder.CreateSelect(XEq0AndYLt0, NegHalfPi, Result);
650
651 // x == 0, y > 0 -> pi/2
652 Value *XEq0AndYGe0 = Builder.CreateAnd(XEq0, YGe0);
653 Result = Builder.CreateSelect(XEq0AndYGe0, HalfPi, Result);
654
655 return Result;
656}
657
658static Value *expandPowIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId) {
659
660 Value *X = Orig->getOperand(0);
661 Value *Y = Orig->getOperand(1);
662 Type *Ty = X->getType();
663 IRBuilder<> Builder(Orig);
664
665 if (IntrinsicId == Intrinsic::powi)
666 Y = Builder.CreateSIToFP(Y, Ty);
667
668 auto *Log2Call =
669 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
670 auto *Mul = Builder.CreateFMul(Log2Call, Y);
671 auto *Exp2Call =
672 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2");
673 Exp2Call->setTailCall(Orig->isTailCall());
674 Exp2Call->setAttributes(Orig->getAttributes());
675 return Exp2Call;
676}
677
679
680 Value *X = Orig->getOperand(0);
681 Value *Y = Orig->getOperand(1);
682 Type *Ty = X->getType();
683 IRBuilder<> Builder(Orig);
684
685 Constant *One = ConstantFP::get(Ty->getScalarType(), 1.0);
686 Constant *Zero = ConstantFP::get(Ty->getScalarType(), 0.0);
687 Value *Cond = Builder.CreateFCmpOLT(Y, X);
688
689 if (Ty != Ty->getScalarType()) {
690 auto *XVec = dyn_cast<FixedVectorType>(Ty);
692 ElementCount::getFixed(XVec->getNumElements()), One);
694 ElementCount::getFixed(XVec->getNumElements()), Zero);
695 }
696
697 return Builder.CreateSelect(Cond, Zero, One);
698}
699
701 Value *X = Orig->getOperand(0);
702 Type *Ty = X->getType();
703 IRBuilder<> Builder(Orig);
704 Value *PiOver180 = ConstantFP::get(Ty, llvm::numbers::pi / 180.0);
705 return Builder.CreateFMul(X, PiOver180);
706}
707
708static bool expandBufferLoadIntrinsic(CallInst *Orig, bool IsRaw) {
709 IRBuilder<> Builder(Orig);
710
711 Type *BufferTy = Orig->getType()->getStructElementType(0);
712 Type *ScalarTy = BufferTy->getScalarType();
713 bool IsDouble = ScalarTy->isDoubleTy();
714 assert(IsDouble || ScalarTy->isIntegerTy(64) &&
715 "Only expand double or int64 scalars or vectors");
716 bool IsVector = false;
717 unsigned ExtractNum = 2;
718 if (auto *VT = dyn_cast<FixedVectorType>(BufferTy)) {
719 ExtractNum = 2 * VT->getNumElements();
720 IsVector = true;
721 assert(IsRaw || ExtractNum == 4 && "TypedBufferLoad vector must be size 2");
722 }
723
725 Value *Result = PoisonValue::get(BufferTy);
726 unsigned Base = 0;
727 // If we need to extract more than 4 i32; we need to break it up into
728 // more than one load. LoadNum tells us how many i32s we are loading in
729 // each load
730 while (ExtractNum > 0) {
731 unsigned LoadNum = std::min(ExtractNum, 4u);
732 Type *Ty = VectorType::get(Builder.getInt32Ty(), LoadNum, false);
733
734 Type *LoadType = StructType::get(Ty, Builder.getInt1Ty());
735 Intrinsic::ID LoadIntrinsic = Intrinsic::dx_resource_load_typedbuffer;
736 SmallVector<Value *, 3> Args = {Orig->getOperand(0), Orig->getOperand(1)};
737 if (IsRaw) {
738 LoadIntrinsic = Intrinsic::dx_resource_load_rawbuffer;
739 Value *Tmp = Builder.getInt32(4 * Base * 2);
740 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
741 }
742
743 CallInst *Load = Builder.CreateIntrinsic(LoadType, LoadIntrinsic, Args);
744 Loads.push_back(Load);
745
746 // extract the buffer load's result
747 Value *Extract = Builder.CreateExtractValue(Load, {0});
748
749 SmallVector<Value *> ExtractElements;
750 for (unsigned I = 0; I < LoadNum; ++I)
751 ExtractElements.push_back(
752 Builder.CreateExtractElement(Extract, Builder.getInt32(I)));
753
754 // combine into double(s) or int64(s)
755 for (unsigned I = 0; I < LoadNum; I += 2) {
756 Value *Combined = nullptr;
757 if (IsDouble)
758 // For doubles, use dx_asdouble intrinsic
759 Combined = Builder.CreateIntrinsic(
760 Builder.getDoubleTy(), Intrinsic::dx_asdouble,
761 {ExtractElements[I], ExtractElements[I + 1]});
762 else {
763 // For int64, manually combine two int32s
764 // First, zero-extend both values to i64
765 Value *Lo =
766 Builder.CreateZExt(ExtractElements[I], Builder.getInt64Ty());
767 Value *Hi =
768 Builder.CreateZExt(ExtractElements[I + 1], Builder.getInt64Ty());
769 // Shift the high bits left by 32 bits
770 Value *ShiftedHi = Builder.CreateShl(Hi, Builder.getInt64(32));
771 // OR the high and low bits together
772 Combined = Builder.CreateOr(Lo, ShiftedHi);
773 }
774
775 if (IsVector)
776 Result = Builder.CreateInsertElement(Result, Combined,
777 Builder.getInt32((I / 2) + Base));
778 else
779 Result = Combined;
780 }
781
782 ExtractNum -= LoadNum;
783 Base += LoadNum / 2;
784 }
785
786 Value *CheckBit = nullptr;
787 for (User *U : make_early_inc_range(Orig->users())) {
788 // If it's not a ExtractValueInst, we don't know how to
789 // handle it
790 auto *EVI = dyn_cast<ExtractValueInst>(U);
791 if (!EVI)
792 llvm_unreachable("Unexpected user of typedbufferload");
793
794 ArrayRef<unsigned> Indices = EVI->getIndices();
795 assert(Indices.size() == 1);
796
797 if (Indices[0] == 0) {
798 // Use of the value(s)
799 EVI->replaceAllUsesWith(Result);
800 } else {
801 // Use of the check bit
802 assert(Indices[0] == 1 && "Unexpected type for typedbufferload");
803 // Note: This does not always match the historical behaviour of DXC.
804 // See https://github.com/microsoft/DirectXShaderCompiler/issues/7622
805 if (!CheckBit) {
806 SmallVector<Value *, 2> CheckBits;
807 for (Value *L : Loads)
808 CheckBits.push_back(Builder.CreateExtractValue(L, {1}));
809 CheckBit = Builder.CreateAnd(CheckBits);
810 }
811 EVI->replaceAllUsesWith(CheckBit);
812 }
813 EVI->eraseFromParent();
814 }
815 Orig->eraseFromParent();
816 return true;
817}
818
819static bool expandBufferStoreIntrinsic(CallInst *Orig, bool IsRaw) {
820 IRBuilder<> Builder(Orig);
821
822 unsigned ValIndex = IsRaw ? 3 : 2;
823 Type *BufferTy = Orig->getFunctionType()->getParamType(ValIndex);
824 Type *ScalarTy = BufferTy->getScalarType();
825 bool IsDouble = ScalarTy->isDoubleTy();
826 assert((IsDouble || ScalarTy->isIntegerTy(64)) &&
827 "Only expand double or int64 scalars or vectors");
828
829 // Determine if we're dealing with a vector or scalar
830 bool IsVector = false;
831 unsigned ExtractNum = 2;
832 unsigned VecLen = 0;
833 if (auto *VT = dyn_cast<FixedVectorType>(BufferTy)) {
834 VecLen = VT->getNumElements();
835 assert(IsRaw || VecLen == 2 && "TypedBufferStore vector must be size 2");
836 ExtractNum = VecLen * 2;
837 IsVector = true;
838 }
839
840 // Create the appropriate vector type for the result
841 Type *Int32Ty = Builder.getInt32Ty();
842 Type *ResultTy = VectorType::get(Int32Ty, ExtractNum, false);
843 Value *Val = PoisonValue::get(ResultTy);
844
845 Type *SplitElementTy = Int32Ty;
846 if (IsVector)
847 SplitElementTy = VectorType::get(SplitElementTy, VecLen, false);
848
849 Value *LowBits = nullptr;
850 Value *HighBits = nullptr;
851 // Split the 64-bit values into 32-bit components
852 if (IsDouble) {
853 auto *SplitTy = llvm::StructType::get(SplitElementTy, SplitElementTy);
854 Value *Split = Builder.CreateIntrinsic(SplitTy, Intrinsic::dx_splitdouble,
855 {Orig->getOperand(ValIndex)});
856 LowBits = Builder.CreateExtractValue(Split, 0);
857 HighBits = Builder.CreateExtractValue(Split, 1);
858 } else {
859 // Handle int64 type(s)
860 Value *InputVal = Orig->getOperand(ValIndex);
861 Constant *ShiftAmt = Builder.getInt64(32);
862 if (IsVector)
863 ShiftAmt =
865
866 // Split into low and high 32-bit parts
867 LowBits = Builder.CreateTrunc(InputVal, SplitElementTy);
868 Value *ShiftedVal = Builder.CreateLShr(InputVal, ShiftAmt);
869 HighBits = Builder.CreateTrunc(ShiftedVal, SplitElementTy);
870 }
871
872 if (IsVector) {
874 for (unsigned I = 0; I < VecLen; ++I) {
875 Mask.push_back(I);
876 Mask.push_back(I + VecLen);
877 }
878 Val = Builder.CreateShuffleVector(LowBits, HighBits, Mask);
879 } else {
880 Val = Builder.CreateInsertElement(Val, LowBits, Builder.getInt32(0));
881 Val = Builder.CreateInsertElement(Val, HighBits, Builder.getInt32(1));
882 }
883
884 // If we need to extract more than 4 i32; we need to break it up into
885 // more than one store. StoreNum tells us how many i32s we are storing in
886 // each store
887 unsigned Base = 0;
888 while (ExtractNum > 0) {
889 unsigned StoreNum = std::min(ExtractNum, 4u);
890
891 Intrinsic::ID StoreIntrinsic = Intrinsic::dx_resource_store_typedbuffer;
892 SmallVector<Value *, 4> Args = {Orig->getOperand(0), Orig->getOperand(1)};
893 if (IsRaw) {
894 StoreIntrinsic = Intrinsic::dx_resource_store_rawbuffer;
895 Value *Tmp = Builder.getInt32(4 * Base);
896 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
897 }
898
900 for (unsigned I = 0; I < StoreNum; ++I) {
901 Mask.push_back(Base + I);
902 }
903
904 Value *SubVal = Val;
905 if (VecLen > 2)
906 SubVal = Builder.CreateShuffleVector(Val, Mask);
907
908 Args.push_back(SubVal);
909 // Create the final intrinsic call
910 Builder.CreateIntrinsic(Builder.getVoidTy(), StoreIntrinsic, Args);
911
912 ExtractNum -= StoreNum;
913 Base += StoreNum;
914 }
915 Orig->eraseFromParent();
916 return true;
917}
918
920 if (ClampIntrinsic == Intrinsic::dx_uclamp)
921 return Intrinsic::umax;
922 if (ClampIntrinsic == Intrinsic::dx_sclamp)
923 return Intrinsic::smax;
924 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
925 return Intrinsic::maxnum;
926}
927
929 if (ClampIntrinsic == Intrinsic::dx_uclamp)
930 return Intrinsic::umin;
931 if (ClampIntrinsic == Intrinsic::dx_sclamp)
932 return Intrinsic::smin;
933 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
934 return Intrinsic::minnum;
935}
936
938 Intrinsic::ID ClampIntrinsic) {
939 Value *X = Orig->getOperand(0);
940 Value *Min = Orig->getOperand(1);
941 Value *Max = Orig->getOperand(2);
942 Type *Ty = X->getType();
943 IRBuilder<> Builder(Orig);
944 auto *MaxCall = Builder.CreateIntrinsic(Ty, getMaxForClamp(ClampIntrinsic),
945 {X, Min}, nullptr, "dx.max");
946 return Builder.CreateIntrinsic(Ty, getMinForClamp(ClampIntrinsic),
947 {MaxCall, Max}, nullptr, "dx.min");
948}
949
951 Value *X = Orig->getOperand(0);
952 Type *Ty = X->getType();
953 IRBuilder<> Builder(Orig);
954 Value *DegreesRatio = ConstantFP::get(Ty, 180.0 * llvm::numbers::inv_pi);
955 return Builder.CreateFMul(X, DegreesRatio);
956}
957
959 Value *X = Orig->getOperand(0);
960 Type *Ty = X->getType();
961 Type *ScalarTy = Ty->getScalarType();
962 Type *RetTy = Orig->getType();
964
965 IRBuilder<> Builder(Orig);
966
967 Value *GT;
968 Value *LT;
969 if (ScalarTy->isFloatingPointTy()) {
970 GT = Builder.CreateFCmpOLT(Zero, X);
971 LT = Builder.CreateFCmpOLT(X, Zero);
972 } else {
973 assert(ScalarTy->isIntegerTy());
974 GT = Builder.CreateICmpSLT(Zero, X);
975 LT = Builder.CreateICmpSLT(X, Zero);
976 }
977
978 Value *ZextGT = Builder.CreateZExt(GT, RetTy);
979 Value *ZextLT = Builder.CreateZExt(LT, RetTy);
980
981 return Builder.CreateSub(ZextGT, ZextLT);
982}
983
984static bool expandIntrinsic(Function &F, CallInst *Orig) {
985 Value *Result = nullptr;
986 Intrinsic::ID IntrinsicId = F.getIntrinsicID();
987 switch (IntrinsicId) {
988 case Intrinsic::abs:
989 Result = expandAbs(Orig);
990 break;
991 case Intrinsic::atan2:
992 Result = expandAtan2Intrinsic(Orig);
993 break;
994 case Intrinsic::exp:
995 Result = expandExpIntrinsic(Orig);
996 break;
997 case Intrinsic::is_fpclass:
998 Result = expandIsFPClass(Orig);
999 break;
1000 case Intrinsic::log:
1001 Result = expandLogIntrinsic(Orig);
1002 break;
1003 case Intrinsic::log10:
1004 Result = expandLog10Intrinsic(Orig);
1005 break;
1006 case Intrinsic::pow:
1007 case Intrinsic::powi:
1008 Result = expandPowIntrinsic(Orig, IntrinsicId);
1009 break;
1010 case Intrinsic::dx_all:
1011 case Intrinsic::dx_any:
1012 Result = expandAnyOrAllIntrinsic(Orig, IntrinsicId);
1013 break;
1014 case Intrinsic::dx_cross:
1015 Result = expandCrossIntrinsic(Orig);
1016 break;
1017 case Intrinsic::dx_uclamp:
1018 case Intrinsic::dx_sclamp:
1019 case Intrinsic::dx_nclamp:
1020 Result = expandClampIntrinsic(Orig, IntrinsicId);
1021 break;
1022 case Intrinsic::dx_degrees:
1023 Result = expandDegreesIntrinsic(Orig);
1024 break;
1025 case Intrinsic::dx_isinf:
1026 Result = expand16BitIsInf(Orig);
1027 break;
1028 case Intrinsic::dx_isnan:
1029 Result = expand16BitIsNaN(Orig);
1030 break;
1031 case Intrinsic::dx_lerp:
1032 Result = expandLerpIntrinsic(Orig);
1033 break;
1034 case Intrinsic::dx_normalize:
1035 Result = expandNormalizeIntrinsic(Orig);
1036 break;
1037 case Intrinsic::dx_fdot:
1038 Result = expandFloatDotIntrinsic(Orig);
1039 break;
1040 case Intrinsic::dx_sdot:
1041 case Intrinsic::dx_udot:
1042 Result = expandIntegerDotIntrinsic(Orig, IntrinsicId);
1043 break;
1044 case Intrinsic::dx_sign:
1045 Result = expandSignIntrinsic(Orig);
1046 break;
1047 case Intrinsic::dx_step:
1048 Result = expandStepIntrinsic(Orig);
1049 break;
1050 case Intrinsic::dx_radians:
1051 Result = expandRadiansIntrinsic(Orig);
1052 break;
1053 case Intrinsic::dx_resource_load_rawbuffer:
1054 if (expandBufferLoadIntrinsic(Orig, /*IsRaw*/ true))
1055 return true;
1056 break;
1057 case Intrinsic::dx_resource_store_rawbuffer:
1058 if (expandBufferStoreIntrinsic(Orig, /*IsRaw*/ true))
1059 return true;
1060 break;
1061 case Intrinsic::dx_resource_load_typedbuffer:
1062 if (expandBufferLoadIntrinsic(Orig, /*IsRaw*/ false))
1063 return true;
1064 break;
1065 case Intrinsic::dx_resource_store_typedbuffer:
1066 if (expandBufferStoreIntrinsic(Orig, /*IsRaw*/ false))
1067 return true;
1068 break;
1069 case Intrinsic::usub_sat:
1070 Result = expandUsubSat(Orig);
1071 break;
1072 case Intrinsic::vector_reduce_add:
1073 case Intrinsic::vector_reduce_fadd:
1074 Result = expandVecReduceAdd(Orig, IntrinsicId);
1075 break;
1076 }
1077 if (Result) {
1078 Orig->replaceAllUsesWith(Result);
1079 Orig->eraseFromParent();
1080 return true;
1081 }
1082 return false;
1083}
1084
1086 for (auto &F : make_early_inc_range(M.functions())) {
1087 if (!isIntrinsicExpansion(F))
1088 continue;
1089 bool IntrinsicExpanded = false;
1090 for (User *U : make_early_inc_range(F.users())) {
1091 auto *IntrinsicCall = dyn_cast<CallInst>(U);
1092 if (!IntrinsicCall)
1093 continue;
1094 IntrinsicExpanded = expandIntrinsic(F, IntrinsicCall);
1095 }
1096 if (F.user_empty() && IntrinsicExpanded)
1097 F.eraseFromParent();
1098 }
1099 return true;
1100}
1101
1108
1112
1114
1116 "DXIL Intrinsic Expansion", false, false)
1118 "DXIL Intrinsic Expansion", false, false)
1119
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static Value * expand16BitIsNormal(CallInst *Orig)
static Value * expandNormalizeIntrinsic(CallInst *Orig)
static bool expandIntrinsic(Function &F, CallInst *Orig)
static Value * expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic)
static Value * expand16BitIsInf(CallInst *Orig)
static bool expansionIntrinsics(Module &M)
static Value * expand16BitIsFinite(CallInst *Orig)
static Value * expandLerpIntrinsic(CallInst *Orig)
static Value * expandCrossIntrinsic(CallInst *Orig)
static Value * expandUsubSat(CallInst *Orig)
static Value * expandAnyOrAllIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId)
static Value * expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId)
static Value * expandAtan2Intrinsic(CallInst *Orig)
static Value * expandLog10Intrinsic(CallInst *Orig)
static Intrinsic::ID getMinForClamp(Intrinsic::ID ClampIntrinsic)
static Value * expandStepIntrinsic(CallInst *Orig)
static Value * expandIntegerDotIntrinsic(CallInst *Orig, Intrinsic::ID DotIntrinsic)
static bool expandBufferStoreIntrinsic(CallInst *Orig, bool IsRaw)
static Value * expandLogIntrinsic(CallInst *Orig, float LogConstVal=numbers::ln2f)
static Value * expandDegreesIntrinsic(CallInst *Orig)
static Value * expandPowIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId)
static bool resourceAccessNeeds64BitExpansion(Module *M, Type *OverloadTy, bool IsRaw)
static Value * expandExpIntrinsic(CallInst *Orig)
static Value * expand16BitIsNaN(CallInst *Orig)
static Value * expandSignIntrinsic(CallInst *Orig)
static Intrinsic::ID getMaxForClamp(Intrinsic::ID ClampIntrinsic)
static Value * expandAbs(CallInst *Orig)
static Value * expandFloatDotIntrinsic(CallInst *Orig, Value *A, Value *B)
static Value * expandRadiansIntrinsic(CallInst *Orig)
static bool isIntrinsicExpansion(Function &F)
static bool expandBufferLoadIntrinsic(CallInst *Orig, bool IsRaw)
static Value * expandIsFPClass(CallInst *Orig)
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
#define T
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
const SmallVectorImpl< MachineOperand > & Cond
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.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
BinaryOperator * Mul
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
bool isZero() const
Definition APFloat.h:1445
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
void setTailCall(bool IsTc=true)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI bool isZeroValue() const
Return true if the value is negative zero or null value.
Definition Constants.cpp:76
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:803
Type * getParamType(unsigned i) const
Parameter type accessors.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2780
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
ModulePass(char &pid)
Definition Pass.h:257
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:414
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:273
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:352
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:198
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
Definition Type.cpp:296
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:156
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:240
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:301
Value * getOperand(unsigned i) const
Definition User.h:232
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:546
iterator_range< user_iterator > users()
Definition Value.h:426
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Represents a version number in the form major[.minor[.subminor[.build]]].
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr double inv_pi
Definition MathExtras.h:54
constexpr float ln10f
Definition MathExtras.h:65
constexpr float log2ef
Definition MathExtras.h:66
constexpr double pi
Definition MathExtras.h:53
constexpr float ln2f
Definition MathExtras.h:64
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
Definition InstrProf.h:296
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:634
ModulePass * createDXILIntrinsicExpansionLegacyPass()
Pass to expand intrinsic operations that lack DXIL opCodes.
@ Sub
Subtraction of integers.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:180