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/Constants.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/InstrTypes.h"
21#include "llvm/IR/Instruction.h"
23#include "llvm/IR/Intrinsics.h"
24#include "llvm/IR/IntrinsicsDirectX.h"
25#include "llvm/IR/Module.h"
26#include "llvm/IR/PassManager.h"
27#include "llvm/IR/Type.h"
28#include "llvm/Pass.h"
32
33#define DEBUG_TYPE "dxil-intrinsic-expansion"
34
35using namespace llvm;
36
38
39public:
40 bool runOnModule(Module &M) override;
42
43 static char ID; // Pass identification.
44};
45
46static bool resourceAccessNeeds64BitExpansion(Module *M, Type *OverloadTy,
47 bool IsRaw) {
48 if (IsRaw && M->getTargetTriple().getDXILVersion() > VersionTuple(1, 2))
49 return false;
50
51 Type *ScalarTy = OverloadTy->getScalarType();
52 return ScalarTy->isDoubleTy() || ScalarTy->isIntegerTy(64);
53}
54
56 Module *M = Orig->getModule();
57 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
58 return nullptr;
59
60 Value *Val = Orig->getOperand(0);
61 Type *ValTy = Val->getType();
62 if (!ValTy->getScalarType()->isHalfTy())
63 return nullptr;
64
65 IRBuilder<> Builder(Orig);
66 Type *IType = Type::getInt16Ty(M->getContext());
67 Constant *PosInf =
68 ValTy->isVectorTy()
72 ConstantInt::get(IType, 0x7c00))
73 : ConstantInt::get(IType, 0x7c00);
74
75 Constant *NegInf =
76 ValTy->isVectorTy()
80 ConstantInt::get(IType, 0xfc00))
81 : ConstantInt::get(IType, 0xfc00);
82
83 Value *IVal = Builder.CreateBitCast(Val, PosInf->getType());
84 Value *B1 = Builder.CreateICmpEQ(IVal, PosInf);
85 Value *B2 = Builder.CreateICmpEQ(IVal, NegInf);
86 Value *B3 = Builder.CreateOr(B1, B2);
87 return B3;
88}
89
91 Module *M = Orig->getModule();
92 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
93 return nullptr;
94
95 Value *Val = Orig->getOperand(0);
96 Type *ValTy = Val->getType();
97 if (!ValTy->getScalarType()->isHalfTy())
98 return nullptr;
99
100 IRBuilder<> Builder(Orig);
101 Type *IType = Type::getInt16Ty(M->getContext());
102
103 Constant *ExpBitMask =
104 ValTy->isVectorTy()
108 ConstantInt::get(IType, 0x7c00))
109 : ConstantInt::get(IType, 0x7c00);
110 Constant *SigBitMask =
111 ValTy->isVectorTy()
115 ConstantInt::get(IType, 0x3ff))
116 : ConstantInt::get(IType, 0x3ff);
117
118 Constant *Zero =
119 ValTy->isVectorTy()
123 ConstantInt::get(IType, 0))
124 : ConstantInt::get(IType, 0);
125
126 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
127 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
128 Value *B1 = Builder.CreateICmpEQ(Exp, ExpBitMask);
129
130 Value *Sig = Builder.CreateAnd(IVal, SigBitMask);
131 Value *B2 = Builder.CreateICmpNE(Sig, Zero);
132 Value *B3 = Builder.CreateAnd(B1, B2);
133 return B3;
134}
135
137 Module *M = Orig->getModule();
138 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
139 return nullptr;
140
141 Value *Val = Orig->getOperand(0);
142 Type *ValTy = Val->getType();
143 if (!ValTy->getScalarType()->isHalfTy())
144 return nullptr;
145
146 IRBuilder<> Builder(Orig);
147 Type *IType = Type::getInt16Ty(M->getContext());
148
149 Constant *ExpBitMask =
150 ValTy->isVectorTy()
154 ConstantInt::get(IType, 0x7c00))
155 : ConstantInt::get(IType, 0x7c00);
156
157 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
158 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
159 Value *B1 = Builder.CreateICmpNE(Exp, ExpBitMask);
160 return B1;
161}
162
164 Module *M = Orig->getModule();
165 if (M->getTargetTriple().getDXILVersion() >= VersionTuple(1, 9))
166 return nullptr;
167
168 Value *Val = Orig->getOperand(0);
169 Type *ValTy = Val->getType();
170 if (!ValTy->getScalarType()->isHalfTy())
171 return nullptr;
172
173 IRBuilder<> Builder(Orig);
174 Type *IType = Type::getInt16Ty(M->getContext());
175
176 Constant *ExpBitMask =
177 ValTy->isVectorTy()
181 ConstantInt::get(IType, 0x7c00))
182 : ConstantInt::get(IType, 0x7c00);
183 Constant *Zero =
184 ValTy->isVectorTy()
188 ConstantInt::get(IType, 0))
189 : ConstantInt::get(IType, 0);
190
191 Value *IVal = Builder.CreateBitCast(Val, ExpBitMask->getType());
192 Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
193 Value *NotAllZeroes = Builder.CreateICmpNE(Exp, Zero);
194 Value *NotAllOnes = Builder.CreateICmpNE(Exp, ExpBitMask);
195 Value *B1 = Builder.CreateAnd(NotAllZeroes, NotAllOnes);
196 return B1;
197}
198
200 switch (F.getIntrinsicID()) {
201 case Intrinsic::assume:
202 case Intrinsic::abs:
203 case Intrinsic::atan2:
204 case Intrinsic::fshl:
205 case Intrinsic::fshr:
206 case Intrinsic::exp:
207 case Intrinsic::is_fpclass:
208 case Intrinsic::log:
209 case Intrinsic::log10:
210 case Intrinsic::pow:
211 case Intrinsic::powi:
212 case Intrinsic::dx_all:
213 case Intrinsic::dx_any:
214 case Intrinsic::dx_cross:
215 case Intrinsic::dx_uclamp:
216 case Intrinsic::dx_sclamp:
217 case Intrinsic::dx_nclamp:
218 case Intrinsic::dx_degrees:
219 case Intrinsic::dx_isinf:
220 case Intrinsic::dx_isnan:
221 case Intrinsic::dx_lerp:
222 case Intrinsic::dx_normalize:
223 case Intrinsic::dx_fdot:
224 case Intrinsic::dx_sdot:
225 case Intrinsic::dx_udot:
226 case Intrinsic::dx_sign:
227 case Intrinsic::dx_step:
228 case Intrinsic::dx_radians:
229 case Intrinsic::usub_sat:
230 case Intrinsic::vector_reduce_add:
231 case Intrinsic::vector_reduce_fadd:
232 return true;
233 case Intrinsic::dx_resource_load_rawbuffer:
235 F.getParent(), F.getReturnType()->getStructElementType(0),
236 /*IsRaw*/ true);
237 case Intrinsic::dx_resource_load_typedbuffer:
239 F.getParent(), F.getReturnType()->getStructElementType(0),
240 /*IsRaw*/ false);
241 case Intrinsic::dx_resource_store_rawbuffer:
243 F.getParent(), F.getFunctionType()->getParamType(3), /*IsRaw*/ true);
244 case Intrinsic::dx_resource_store_typedbuffer:
246 F.getParent(), F.getFunctionType()->getParamType(2), /*IsRaw*/ false);
247 }
248 return false;
249}
250
252 Value *A = Orig->getArgOperand(0);
253 Value *B = Orig->getArgOperand(1);
254 Type *Ty = A->getType();
255
256 IRBuilder<> Builder(Orig);
257
258 Value *Cmp = Builder.CreateICmpULT(A, B, "usub.cmp");
259 Value *Sub = Builder.CreateSub(A, B, "usub.sub");
260 Value *Zero = ConstantInt::get(Ty, 0);
261 return Builder.CreateSelect(Cmp, Zero, Sub, "usub.sat");
262}
263
264static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
265 assert(IntrinsicId == Intrinsic::vector_reduce_add ||
266 IntrinsicId == Intrinsic::vector_reduce_fadd);
267
268 IRBuilder<> Builder(Orig);
269 bool IsFAdd = (IntrinsicId == Intrinsic::vector_reduce_fadd);
270
271 Value *X = Orig->getOperand(IsFAdd ? 1 : 0);
272 Type *Ty = X->getType();
273 auto *XVec = dyn_cast<FixedVectorType>(Ty);
274 unsigned XVecSize = XVec->getNumElements();
275 Value *Sum = Builder.CreateExtractElement(X, static_cast<uint64_t>(0));
276
277 // Handle the initial start value for floating-point addition.
278 if (IsFAdd) {
279 Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
280 if (StartValue && !StartValue->isZeroValue())
281 Sum = Builder.CreateFAdd(Sum, StartValue);
282 }
283
284 // Accumulate the remaining vector elements.
285 for (unsigned I = 1; I < XVecSize; I++) {
286 Value *Elt = Builder.CreateExtractElement(X, I);
287 if (IsFAdd)
288 Sum = Builder.CreateFAdd(Sum, Elt);
289 else
290 Sum = Builder.CreateAdd(Sum, Elt);
291 }
292
293 return Sum;
294}
295
296static Value *expandAbs(CallInst *Orig) {
297 Value *X = Orig->getOperand(0);
298 IRBuilder<> Builder(Orig);
299 Type *Ty = X->getType();
300 Type *EltTy = Ty->getScalarType();
301 Constant *Zero = Ty->isVectorTy()
305 ConstantInt::get(EltTy, 0))
306 : ConstantInt::get(EltTy, 0);
307 auto *V = Builder.CreateSub(Zero, X);
308 return Builder.CreateIntrinsic(Ty, Intrinsic::smax, {X, V}, nullptr,
309 "dx.max");
310}
311
313
314 VectorType *VT = cast<VectorType>(Orig->getType());
316 reportFatalUsageError("return vector must have exactly 3 elements");
317
318 Value *op0 = Orig->getOperand(0);
319 Value *op1 = Orig->getOperand(1);
320 IRBuilder<> Builder(Orig);
321
322 Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0, "x0");
323 Value *op0_y = Builder.CreateExtractElement(op0, 1, "x1");
324 Value *op0_z = Builder.CreateExtractElement(op0, 2, "x2");
325
326 Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "y0");
327 Value *op1_y = Builder.CreateExtractElement(op1, 1, "y1");
328 Value *op1_z = Builder.CreateExtractElement(op1, 2, "y2");
329
330 auto MulSub = [&](Value *x0, Value *y0, Value *x1, Value *y1) -> Value * {
331 Value *xy = Builder.CreateFMul(x0, y1);
332 Value *yx = Builder.CreateFMul(y0, x1);
333 return Builder.CreateFSub(xy, yx, Orig->getName());
334 };
335
336 Value *yz_zy = MulSub(op0_y, op0_z, op1_y, op1_z);
337 Value *zx_xz = MulSub(op0_z, op0_x, op1_z, op1_x);
338 Value *xy_yx = MulSub(op0_x, op0_y, op1_x, op1_y);
339
340 Value *cross = PoisonValue::get(VT);
341 cross = Builder.CreateInsertElement(cross, yz_zy, (uint64_t)0);
342 cross = Builder.CreateInsertElement(cross, zx_xz, 1);
343 cross = Builder.CreateInsertElement(cross, xy_yx, 2);
344 return cross;
345}
346
347// Create appropriate DXIL float dot intrinsic for the given A and B operands
348// The appropriate opcode will be determined by the size of the operands
349// The dot product is placed in the position indicated by Orig
351 Type *ATy = A->getType();
352 [[maybe_unused]] Type *BTy = B->getType();
353 assert(ATy->isVectorTy() && BTy->isVectorTy());
354
355 IRBuilder<> Builder(Orig);
356
357 auto *AVec = dyn_cast<FixedVectorType>(ATy);
358
360
361 Intrinsic::ID DotIntrinsic = Intrinsic::dx_dot4;
362 int NumElts = AVec->getNumElements();
363 switch (NumElts) {
364 case 2:
365 DotIntrinsic = Intrinsic::dx_dot2;
366 break;
367 case 3:
368 DotIntrinsic = Intrinsic::dx_dot3;
369 break;
370 case 4:
371 DotIntrinsic = Intrinsic::dx_dot4;
372 break;
373 default:
375 "Invalid dot product input vector: length is outside 2-4");
376 return nullptr;
377 }
378
380 for (int I = 0; I < NumElts; ++I)
381 Args.push_back(Builder.CreateExtractElement(A, Builder.getInt32(I)));
382 for (int I = 0; I < NumElts; ++I)
383 Args.push_back(Builder.CreateExtractElement(B, Builder.getInt32(I)));
384 return Builder.CreateIntrinsic(ATy->getScalarType(), DotIntrinsic, Args,
385 nullptr, "dot");
386}
387
388// Create the appropriate DXIL float dot intrinsic for the operands of Orig
389// The appropriate opcode will be determined by the size of the operands
390// The dot product is placed in the position indicated by Orig
392 return expandFloatDotIntrinsic(Orig, Orig->getOperand(0),
393 Orig->getOperand(1));
394}
395
396// Expand integer dot product to multiply and add ops
398 Intrinsic::ID DotIntrinsic) {
399 assert(DotIntrinsic == Intrinsic::dx_sdot ||
400 DotIntrinsic == Intrinsic::dx_udot);
401 Value *A = Orig->getOperand(0);
402 Value *B = Orig->getOperand(1);
403 Type *ATy = A->getType();
404 [[maybe_unused]] Type *BTy = B->getType();
405 assert(ATy->isVectorTy() && BTy->isVectorTy());
406
407 IRBuilder<> Builder(Orig);
408
409 auto *AVec = dyn_cast<FixedVectorType>(ATy);
410
412
413 Value *Result;
414 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
415 ? Intrinsic::dx_imad
416 : Intrinsic::dx_umad;
417 Value *Elt0 = Builder.CreateExtractElement(A, (uint64_t)0);
418 Value *Elt1 = Builder.CreateExtractElement(B, (uint64_t)0);
419 Result = Builder.CreateMul(Elt0, Elt1);
420 for (unsigned I = 1; I < AVec->getNumElements(); I++) {
421 Elt0 = Builder.CreateExtractElement(A, I);
422 Elt1 = Builder.CreateExtractElement(B, I);
423 Result = Builder.CreateIntrinsic(Result->getType(), MadIntrinsic,
424 ArrayRef<Value *>{Elt0, Elt1, Result},
425 nullptr, "dx.mad");
426 }
427 return Result;
428}
429
431 Value *X = Orig->getOperand(0);
432 IRBuilder<> Builder(Orig);
433 Type *Ty = X->getType();
434 Type *EltTy = Ty->getScalarType();
435 Constant *Log2eConst =
436 Ty->isVectorTy() ? ConstantVector::getSplat(
439 ConstantFP::get(EltTy, numbers::log2ef))
440 : ConstantFP::get(EltTy, numbers::log2ef);
441 Value *NewX = Builder.CreateFMul(Log2eConst, X);
442 auto *Exp2Call =
443 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
444 Exp2Call->setTailCall(Orig->isTailCall());
445 Exp2Call->setAttributes(Orig->getAttributes());
446 return Exp2Call;
447}
448
450 Value *T = Orig->getArgOperand(1);
451 auto *TCI = dyn_cast<ConstantInt>(T);
452
453 // These FPClassTest cases have DXIL opcodes, so they will be handled in
454 // DXIL Op Lowering instead for all non f16 cases.
455 switch (TCI->getZExtValue()) {
457 return expand16BitIsInf(Orig);
459 return expand16BitIsNaN(Orig);
461 return expand16BitIsNormal(Orig);
463 return expand16BitIsFinite(Orig);
464 }
465
466 IRBuilder<> Builder(Orig);
467
468 Value *F = Orig->getArgOperand(0);
469 Type *FTy = F->getType();
470 unsigned FNumElem = 0; // 0 => F is not a vector
471
472 unsigned BitWidth; // Bit width of F or the ElemTy of F
473 Type *BitCastTy; // An IntNTy of the same bitwidth as F or ElemTy of F
474
475 if (auto *FVecTy = dyn_cast<FixedVectorType>(FTy)) {
476 Type *ElemTy = FVecTy->getElementType();
477 FNumElem = FVecTy->getNumElements();
478 BitWidth = ElemTy->getPrimitiveSizeInBits();
479 BitCastTy = FixedVectorType::get(Builder.getIntNTy(BitWidth), FNumElem);
480 } else {
482 BitCastTy = Builder.getIntNTy(BitWidth);
483 }
484
485 Value *FBitCast = Builder.CreateBitCast(F, BitCastTy);
486 switch (TCI->getZExtValue()) {
488 Value *NegZero =
489 ConstantInt::get(Builder.getIntNTy(BitWidth), 1 << (BitWidth - 1),
490 /*IsSigned=*/true);
491 Value *RetVal;
492 if (FNumElem) {
493 Value *NegZeroSplat = Builder.CreateVectorSplat(FNumElem, NegZero);
494 RetVal =
495 Builder.CreateICmpEQ(FBitCast, NegZeroSplat, "is.fpclass.negzero");
496 } else
497 RetVal = Builder.CreateICmpEQ(FBitCast, NegZero, "is.fpclass.negzero");
498 return RetVal;
499 }
500 default:
501 reportFatalUsageError("Unsupported FPClassTest");
502 }
503}
504
506 Intrinsic::ID IntrinsicId) {
507 Value *X = Orig->getOperand(0);
508 IRBuilder<> Builder(Orig);
509 Type *Ty = X->getType();
510 Type *EltTy = Ty->getScalarType();
511
512 auto ApplyOp = [&Builder](Intrinsic::ID IntrinsicId, Value *Result,
513 Value *Elt) {
514 if (IntrinsicId == Intrinsic::dx_any)
515 return Builder.CreateOr(Result, Elt);
516 assert(IntrinsicId == Intrinsic::dx_all);
517 return Builder.CreateAnd(Result, Elt);
518 };
519
520 Value *Result = nullptr;
521 if (!Ty->isVectorTy()) {
522 Result = EltTy->isFloatingPointTy()
523 ? Builder.CreateFCmpUNE(X, ConstantFP::get(EltTy, 0))
524 : Builder.CreateICmpNE(X, ConstantInt::get(EltTy, 0));
525 } else {
526 auto *XVec = dyn_cast<FixedVectorType>(Ty);
527 Value *Cond =
528 EltTy->isFloatingPointTy()
529 ? Builder.CreateFCmpUNE(
531 ElementCount::getFixed(XVec->getNumElements()),
532 ConstantFP::get(EltTy, 0)))
533 : Builder.CreateICmpNE(
535 ElementCount::getFixed(XVec->getNumElements()),
536 ConstantInt::get(EltTy, 0)));
537 Result = Builder.CreateExtractElement(Cond, (uint64_t)0);
538 for (unsigned I = 1; I < XVec->getNumElements(); I++) {
539 Value *Elt = Builder.CreateExtractElement(Cond, I);
540 Result = ApplyOp(IntrinsicId, Result, Elt);
541 }
542 }
543 return Result;
544}
545
547 Value *X = Orig->getOperand(0);
548 Value *Y = Orig->getOperand(1);
549 Value *S = Orig->getOperand(2);
550 IRBuilder<> Builder(Orig);
551 auto *V = Builder.CreateFSub(Y, X);
552 V = Builder.CreateFMul(S, V);
553 return Builder.CreateFAdd(X, V, "dx.lerp");
554}
555
557 float LogConstVal = numbers::ln2f) {
558 Value *X = Orig->getOperand(0);
559 IRBuilder<> Builder(Orig);
560 Type *Ty = X->getType();
561 Type *EltTy = Ty->getScalarType();
562 Constant *Ln2Const =
563 Ty->isVectorTy() ? ConstantVector::getSplat(
566 ConstantFP::get(EltTy, LogConstVal))
567 : ConstantFP::get(EltTy, LogConstVal);
568 auto *Log2Call =
569 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
570 Log2Call->setTailCall(Orig->isTailCall());
571 Log2Call->setAttributes(Orig->getAttributes());
572 return Builder.CreateFMul(Ln2Const, Log2Call);
573}
577
578// Use dot product of vector operand with itself to calculate the length.
579// Divide the vector by that length to normalize it.
581 Value *X = Orig->getOperand(0);
582 Type *Ty = Orig->getType();
583 Type *EltTy = Ty->getScalarType();
584 IRBuilder<> Builder(Orig);
585
586 auto *XVec = dyn_cast<FixedVectorType>(Ty);
587 if (!XVec) {
588 if (auto *constantFP = dyn_cast<ConstantFP>(X)) {
589 const APFloat &fpVal = constantFP->getValueAPF();
590 if (fpVal.isZero())
591 reportFatalUsageError("Invalid input scalar: length is zero");
592 }
593 return Builder.CreateFDiv(X, X);
594 }
595
596 Value *DotProduct = expandFloatDotIntrinsic(Orig, X, X);
597
598 // verify that the length is non-zero
599 // (if the dot product is non-zero, then the length is non-zero)
600 if (auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) {
601 const APFloat &fpVal = constantFP->getValueAPF();
602 if (fpVal.isZero())
603 reportFatalUsageError("Invalid input vector: length is zero");
604 }
605
606 Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt,
607 ArrayRef<Value *>{DotProduct},
608 nullptr, "dx.rsqrt");
609
610 Value *MultiplicandVec =
611 Builder.CreateVectorSplat(XVec->getNumElements(), Multiplicand);
612 return Builder.CreateFMul(X, MultiplicandVec);
613}
614
616 Value *Y = Orig->getOperand(0);
617 Value *X = Orig->getOperand(1);
618 Type *Ty = X->getType();
619 IRBuilder<> Builder(Orig);
620 Builder.setFastMathFlags(Orig->getFastMathFlags());
621
622 Value *Tan = Builder.CreateFDiv(Y, X);
623
624 CallInst *Atan =
625 Builder.CreateIntrinsic(Ty, Intrinsic::atan, {Tan}, nullptr, "Elt.Atan");
626 Atan->setTailCall(Orig->isTailCall());
627 Atan->setAttributes(Orig->getAttributes());
628
629 // Modify atan result based on https://en.wikipedia.org/wiki/Atan2.
630 Constant *Pi = ConstantFP::get(Ty, llvm::numbers::pi);
631 Constant *HalfPi = ConstantFP::get(Ty, llvm::numbers::pi / 2);
632 Constant *NegHalfPi = ConstantFP::get(Ty, -llvm::numbers::pi / 2);
633 Constant *Zero = ConstantFP::get(Ty, 0);
634 Value *AtanAddPi = Builder.CreateFAdd(Atan, Pi);
635 Value *AtanSubPi = Builder.CreateFSub(Atan, Pi);
636
637 // x > 0 -> atan.
638 Value *Result = Atan;
639 Value *XLt0 = Builder.CreateFCmpOLT(X, Zero);
640 Value *XEq0 = Builder.CreateFCmpOEQ(X, Zero);
641 Value *YGe0 = Builder.CreateFCmpOGE(Y, Zero);
642 Value *YLt0 = Builder.CreateFCmpOLT(Y, Zero);
643
644 // x < 0, y >= 0 -> atan + pi.
645 Value *XLt0AndYGe0 = Builder.CreateAnd(XLt0, YGe0);
646 Result = Builder.CreateSelect(XLt0AndYGe0, AtanAddPi, Result);
647
648 // x < 0, y < 0 -> atan - pi.
649 Value *XLt0AndYLt0 = Builder.CreateAnd(XLt0, YLt0);
650 Result = Builder.CreateSelect(XLt0AndYLt0, AtanSubPi, Result);
651
652 // x == 0, y < 0 -> -pi/2
653 Value *XEq0AndYLt0 = Builder.CreateAnd(XEq0, YLt0);
654 Result = Builder.CreateSelect(XEq0AndYLt0, NegHalfPi, Result);
655
656 // x == 0, y > 0 -> pi/2
657 Value *XEq0AndYGe0 = Builder.CreateAnd(XEq0, YGe0);
658 Result = Builder.CreateSelect(XEq0AndYGe0, HalfPi, Result);
659
660 return Result;
661}
662
663template <bool LeftFunnel>
665 Type *Ty = Orig->getType();
666 Value *A = Orig->getOperand(0);
667 Value *B = Orig->getOperand(1);
668 Value *Shift = Orig->getOperand(2);
669
670 IRBuilder<> Builder(Orig);
671
672 unsigned BitWidth = Ty->getScalarSizeInBits();
674 "Can't use Mask to compute modulo and inverse");
675
676 // Note: if (Shift % BitWidth) == 0 then (BitWidth - Shift) == BitWidth,
677 // shifting by the bitwidth for shl/lshr returns a poisoned result. As such,
678 // we implement the same formula as LegalizerHelper::lowerFunnelShiftAsShifts.
679 //
680 // The funnel shift is expanded like so:
681 // fshl
682 // -> msb_extract((concat(A, B) << (Shift % BitWidth)), BitWidth)
683 // -> A << (Shift % BitWidth) | B >> 1 >> (BitWidth - 1 - (Shift % BitWidth))
684 // fshr
685 // -> lsb_extract((concat(A, B) >> (Shift % BitWidth), BitWidth))
686 // -> A << 1 << (BitWidth - 1 - (Shift % BitWidth)) | B >> (Shift % BitWidth)
687
688 // (BitWidth - 1) -> Mask
689 Constant *Mask = ConstantInt::get(Ty, Ty->getScalarSizeInBits() - 1);
690
691 // Shift % BitWidth
692 // -> Shift & (BitWidth - 1)
693 // -> Shift & Mask
694 Value *MaskedShift = Builder.CreateAnd(Shift, Mask);
695
696 // (BitWidth - 1) - (Shift % BitWidth)
697 // -> ~Shift & (BitWidth - 1)
698 // -> ~Shift & Mask
699 Value *NotShift = Builder.CreateNot(Shift);
700 Value *InverseShift = Builder.CreateAnd(NotShift, Mask);
701
702 Constant *One = ConstantInt::get(Ty, 1);
703 Value *ShiftedA;
704 Value *ShiftedB;
705
706 if (LeftFunnel) {
707 ShiftedA = Builder.CreateShl(A, MaskedShift);
708 Value *ShiftB1 = Builder.CreateLShr(B, One);
709 ShiftedB = Builder.CreateLShr(ShiftB1, InverseShift);
710 } else {
711 Value *ShiftA1 = Builder.CreateShl(A, One);
712 ShiftedA = Builder.CreateShl(ShiftA1, InverseShift);
713 ShiftedB = Builder.CreateLShr(B, MaskedShift);
714 }
715
716 Value *Result = Builder.CreateOr(ShiftedA, ShiftedB);
717 return Result;
718}
719
720static Value *expandPowIntrinsic(CallInst *Orig, Intrinsic::ID IntrinsicId) {
721
722 Value *X = Orig->getOperand(0);
723 Value *Y = Orig->getOperand(1);
724 Type *Ty = X->getType();
725 IRBuilder<> Builder(Orig);
726
727 if (IntrinsicId == Intrinsic::powi)
728 Y = Builder.CreateSIToFP(Y, Ty);
729
730 auto *Log2Call =
731 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
732 auto *Mul = Builder.CreateFMul(Log2Call, Y);
733 auto *Exp2Call =
734 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2");
735 Exp2Call->setTailCall(Orig->isTailCall());
736 Exp2Call->setAttributes(Orig->getAttributes());
737 return Exp2Call;
738}
739
741
742 Value *X = Orig->getOperand(0);
743 Value *Y = Orig->getOperand(1);
744 Type *Ty = X->getType();
745 IRBuilder<> Builder(Orig);
746
747 Constant *One = ConstantFP::get(Ty->getScalarType(), 1.0);
748 Constant *Zero = ConstantFP::get(Ty->getScalarType(), 0.0);
749 Value *Cond = Builder.CreateFCmpOLT(Y, X);
750
751 if (Ty != Ty->getScalarType()) {
752 auto *XVec = dyn_cast<FixedVectorType>(Ty);
754 ElementCount::getFixed(XVec->getNumElements()), One);
756 ElementCount::getFixed(XVec->getNumElements()), Zero);
757 }
758
759 return Builder.CreateSelect(Cond, Zero, One);
760}
761
763 Value *X = Orig->getOperand(0);
764 Type *Ty = X->getType();
765 IRBuilder<> Builder(Orig);
766 Value *PiOver180 = ConstantFP::get(Ty, llvm::numbers::pi / 180.0);
767 return Builder.CreateFMul(X, PiOver180);
768}
769
770static bool expandBufferLoadIntrinsic(CallInst *Orig, bool IsRaw) {
771 IRBuilder<> Builder(Orig);
772
773 Type *BufferTy = Orig->getType()->getStructElementType(0);
774 Type *ScalarTy = BufferTy->getScalarType();
775 bool IsDouble = ScalarTy->isDoubleTy();
776 assert(IsDouble || ScalarTy->isIntegerTy(64) &&
777 "Only expand double or int64 scalars or vectors");
778 bool IsVector = false;
779 unsigned ExtractNum = 2;
780 if (auto *VT = dyn_cast<FixedVectorType>(BufferTy)) {
781 ExtractNum = 2 * VT->getNumElements();
782 IsVector = true;
783 assert(IsRaw || ExtractNum == 4 && "TypedBufferLoad vector must be size 2");
784 }
785
787 Value *Result = PoisonValue::get(BufferTy);
788 unsigned Base = 0;
789 // If we need to extract more than 4 i32; we need to break it up into
790 // more than one load. LoadNum tells us how many i32s we are loading in
791 // each load
792 while (ExtractNum > 0) {
793 unsigned LoadNum = std::min(ExtractNum, 4u);
794 Type *Ty = VectorType::get(Builder.getInt32Ty(), LoadNum, false);
795
796 Type *LoadType = StructType::get(Ty, Builder.getInt1Ty());
797 Intrinsic::ID LoadIntrinsic = Intrinsic::dx_resource_load_typedbuffer;
798 SmallVector<Value *, 3> Args = {Orig->getOperand(0), Orig->getOperand(1)};
799 if (IsRaw) {
800 LoadIntrinsic = Intrinsic::dx_resource_load_rawbuffer;
801 Value *Tmp = Builder.getInt32(4 * Base * 2);
802 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
803 }
804
805 CallInst *Load = Builder.CreateIntrinsic(LoadType, LoadIntrinsic, Args);
806 Loads.push_back(Load);
807
808 // extract the buffer load's result
809 Value *Extract = Builder.CreateExtractValue(Load, {0});
810
811 SmallVector<Value *> ExtractElements;
812 for (unsigned I = 0; I < LoadNum; ++I)
813 ExtractElements.push_back(
814 Builder.CreateExtractElement(Extract, Builder.getInt32(I)));
815
816 // combine into double(s) or int64(s)
817 for (unsigned I = 0; I < LoadNum; I += 2) {
818 Value *Combined = nullptr;
819 if (IsDouble)
820 // For doubles, use dx_asdouble intrinsic
821 Combined = Builder.CreateIntrinsic(
822 Builder.getDoubleTy(), Intrinsic::dx_asdouble,
823 {ExtractElements[I], ExtractElements[I + 1]});
824 else {
825 // For int64, manually combine two int32s
826 // First, zero-extend both values to i64
827 Value *Lo =
828 Builder.CreateZExt(ExtractElements[I], Builder.getInt64Ty());
829 Value *Hi =
830 Builder.CreateZExt(ExtractElements[I + 1], Builder.getInt64Ty());
831 // Shift the high bits left by 32 bits
832 Value *ShiftedHi = Builder.CreateShl(Hi, Builder.getInt64(32));
833 // OR the high and low bits together
834 Combined = Builder.CreateOr(Lo, ShiftedHi);
835 }
836
837 if (IsVector)
838 Result = Builder.CreateInsertElement(Result, Combined,
839 Builder.getInt32((I / 2) + Base));
840 else
841 Result = Combined;
842 }
843
844 ExtractNum -= LoadNum;
845 Base += LoadNum / 2;
846 }
847
848 Value *CheckBit = nullptr;
849 for (User *U : make_early_inc_range(Orig->users())) {
850 // If it's not a ExtractValueInst, we don't know how to
851 // handle it
852 auto *EVI = dyn_cast<ExtractValueInst>(U);
853 if (!EVI)
854 llvm_unreachable("Unexpected user of typedbufferload");
855
856 ArrayRef<unsigned> Indices = EVI->getIndices();
857 assert(Indices.size() == 1);
858
859 if (Indices[0] == 0) {
860 // Use of the value(s)
861 EVI->replaceAllUsesWith(Result);
862 } else {
863 // Use of the check bit
864 assert(Indices[0] == 1 && "Unexpected type for typedbufferload");
865 // Note: This does not always match the historical behaviour of DXC.
866 // See https://github.com/microsoft/DirectXShaderCompiler/issues/7622
867 if (!CheckBit) {
868 SmallVector<Value *, 2> CheckBits;
869 for (Value *L : Loads)
870 CheckBits.push_back(Builder.CreateExtractValue(L, {1}));
871 CheckBit = Builder.CreateAnd(CheckBits);
872 }
873 EVI->replaceAllUsesWith(CheckBit);
874 }
875 EVI->eraseFromParent();
876 }
877 Orig->eraseFromParent();
878 return true;
879}
880
881static bool expandBufferStoreIntrinsic(CallInst *Orig, bool IsRaw) {
882 IRBuilder<> Builder(Orig);
883
884 unsigned ValIndex = IsRaw ? 3 : 2;
885 Type *BufferTy = Orig->getFunctionType()->getParamType(ValIndex);
886 Type *ScalarTy = BufferTy->getScalarType();
887 bool IsDouble = ScalarTy->isDoubleTy();
888 assert((IsDouble || ScalarTy->isIntegerTy(64)) &&
889 "Only expand double or int64 scalars or vectors");
890
891 // Determine if we're dealing with a vector or scalar
892 bool IsVector = false;
893 unsigned ExtractNum = 2;
894 unsigned VecLen = 0;
895 if (auto *VT = dyn_cast<FixedVectorType>(BufferTy)) {
896 VecLen = VT->getNumElements();
897 assert(IsRaw || VecLen == 2 && "TypedBufferStore vector must be size 2");
898 ExtractNum = VecLen * 2;
899 IsVector = true;
900 }
901
902 // Create the appropriate vector type for the result
903 Type *Int32Ty = Builder.getInt32Ty();
904 Type *ResultTy = VectorType::get(Int32Ty, ExtractNum, false);
905 Value *Val = PoisonValue::get(ResultTy);
906
907 Type *SplitElementTy = Int32Ty;
908 if (IsVector)
909 SplitElementTy = VectorType::get(SplitElementTy, VecLen, false);
910
911 Value *LowBits = nullptr;
912 Value *HighBits = nullptr;
913 // Split the 64-bit values into 32-bit components
914 if (IsDouble) {
915 auto *SplitTy = llvm::StructType::get(SplitElementTy, SplitElementTy);
916 Value *Split = Builder.CreateIntrinsic(SplitTy, Intrinsic::dx_splitdouble,
917 {Orig->getOperand(ValIndex)});
918 LowBits = Builder.CreateExtractValue(Split, 0);
919 HighBits = Builder.CreateExtractValue(Split, 1);
920 } else {
921 // Handle int64 type(s)
922 Value *InputVal = Orig->getOperand(ValIndex);
923 Constant *ShiftAmt = Builder.getInt64(32);
924 if (IsVector)
925 ShiftAmt =
927
928 // Split into low and high 32-bit parts
929 LowBits = Builder.CreateTrunc(InputVal, SplitElementTy);
930 Value *ShiftedVal = Builder.CreateLShr(InputVal, ShiftAmt);
931 HighBits = Builder.CreateTrunc(ShiftedVal, SplitElementTy);
932 }
933
934 if (IsVector) {
936 for (unsigned I = 0; I < VecLen; ++I) {
937 Mask.push_back(I);
938 Mask.push_back(I + VecLen);
939 }
940 Val = Builder.CreateShuffleVector(LowBits, HighBits, Mask);
941 } else {
942 Val = Builder.CreateInsertElement(Val, LowBits, Builder.getInt32(0));
943 Val = Builder.CreateInsertElement(Val, HighBits, Builder.getInt32(1));
944 }
945
946 // If we need to extract more than 4 i32; we need to break it up into
947 // more than one store. StoreNum tells us how many i32s we are storing in
948 // each store
949 unsigned Base = 0;
950 while (ExtractNum > 0) {
951 unsigned StoreNum = std::min(ExtractNum, 4u);
952
953 Intrinsic::ID StoreIntrinsic = Intrinsic::dx_resource_store_typedbuffer;
954 SmallVector<Value *, 4> Args = {Orig->getOperand(0), Orig->getOperand(1)};
955 if (IsRaw) {
956 StoreIntrinsic = Intrinsic::dx_resource_store_rawbuffer;
957 Value *Tmp = Builder.getInt32(4 * Base);
958 Args.push_back(Builder.CreateAdd(Orig->getOperand(2), Tmp));
959 }
960
962 for (unsigned I = 0; I < StoreNum; ++I) {
963 Mask.push_back(Base + I);
964 }
965
966 Value *SubVal = Val;
967 if (VecLen > 2)
968 SubVal = Builder.CreateShuffleVector(Val, Mask);
969
970 Args.push_back(SubVal);
971 // Create the final intrinsic call
972 Builder.CreateIntrinsic(Builder.getVoidTy(), StoreIntrinsic, Args);
973
974 ExtractNum -= StoreNum;
975 Base += StoreNum;
976 }
977 Orig->eraseFromParent();
978 return true;
979}
980
982 if (ClampIntrinsic == Intrinsic::dx_uclamp)
983 return Intrinsic::umax;
984 if (ClampIntrinsic == Intrinsic::dx_sclamp)
985 return Intrinsic::smax;
986 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
987 return Intrinsic::maxnum;
988}
989
991 if (ClampIntrinsic == Intrinsic::dx_uclamp)
992 return Intrinsic::umin;
993 if (ClampIntrinsic == Intrinsic::dx_sclamp)
994 return Intrinsic::smin;
995 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
996 return Intrinsic::minnum;
997}
998
1000 Intrinsic::ID ClampIntrinsic) {
1001 Value *X = Orig->getOperand(0);
1002 Value *Min = Orig->getOperand(1);
1003 Value *Max = Orig->getOperand(2);
1004 Type *Ty = X->getType();
1005 IRBuilder<> Builder(Orig);
1006 auto *MaxCall = Builder.CreateIntrinsic(Ty, getMaxForClamp(ClampIntrinsic),
1007 {X, Min}, nullptr, "dx.max");
1008 return Builder.CreateIntrinsic(Ty, getMinForClamp(ClampIntrinsic),
1009 {MaxCall, Max}, nullptr, "dx.min");
1010}
1011
1013 Value *X = Orig->getOperand(0);
1014 Type *Ty = X->getType();
1015 IRBuilder<> Builder(Orig);
1016 Value *DegreesRatio = ConstantFP::get(Ty, 180.0 * llvm::numbers::inv_pi);
1017 return Builder.CreateFMul(X, DegreesRatio);
1018}
1019
1021 Value *X = Orig->getOperand(0);
1022 Type *Ty = X->getType();
1023 Type *ScalarTy = Ty->getScalarType();
1024 Type *RetTy = Orig->getType();
1025 Constant *Zero = Constant::getNullValue(Ty);
1026
1027 IRBuilder<> Builder(Orig);
1028
1029 Value *GT;
1030 Value *LT;
1031 if (ScalarTy->isFloatingPointTy()) {
1032 GT = Builder.CreateFCmpOLT(Zero, X);
1033 LT = Builder.CreateFCmpOLT(X, Zero);
1034 } else {
1035 assert(ScalarTy->isIntegerTy());
1036 GT = Builder.CreateICmpSLT(Zero, X);
1037 LT = Builder.CreateICmpSLT(X, Zero);
1038 }
1039
1040 Value *ZextGT = Builder.CreateZExt(GT, RetTy);
1041 Value *ZextLT = Builder.CreateZExt(LT, RetTy);
1042
1043 return Builder.CreateSub(ZextGT, ZextLT);
1044}
1045
1046static bool expandIntrinsic(Function &F, CallInst *Orig) {
1047 Value *Result = nullptr;
1048 Intrinsic::ID IntrinsicId = F.getIntrinsicID();
1049 switch (IntrinsicId) {
1050 case Intrinsic::abs:
1051 Result = expandAbs(Orig);
1052 break;
1053 case Intrinsic::assume:
1054 Orig->eraseFromParent();
1055 return true;
1056 case Intrinsic::atan2:
1057 Result = expandAtan2Intrinsic(Orig);
1058 break;
1059 case Intrinsic::fshl:
1060 Result = expandFunnelShiftIntrinsic<true>(Orig);
1061 break;
1062 case Intrinsic::fshr:
1063 Result = expandFunnelShiftIntrinsic<false>(Orig);
1064 break;
1065 case Intrinsic::exp:
1066 Result = expandExpIntrinsic(Orig);
1067 break;
1068 case Intrinsic::is_fpclass:
1069 Result = expandIsFPClass(Orig);
1070 break;
1071 case Intrinsic::log:
1072 Result = expandLogIntrinsic(Orig);
1073 break;
1074 case Intrinsic::log10:
1075 Result = expandLog10Intrinsic(Orig);
1076 break;
1077 case Intrinsic::pow:
1078 case Intrinsic::powi:
1079 Result = expandPowIntrinsic(Orig, IntrinsicId);
1080 break;
1081 case Intrinsic::dx_all:
1082 case Intrinsic::dx_any:
1083 Result = expandAnyOrAllIntrinsic(Orig, IntrinsicId);
1084 break;
1085 case Intrinsic::dx_cross:
1086 Result = expandCrossIntrinsic(Orig);
1087 break;
1088 case Intrinsic::dx_uclamp:
1089 case Intrinsic::dx_sclamp:
1090 case Intrinsic::dx_nclamp:
1091 Result = expandClampIntrinsic(Orig, IntrinsicId);
1092 break;
1093 case Intrinsic::dx_degrees:
1094 Result = expandDegreesIntrinsic(Orig);
1095 break;
1096 case Intrinsic::dx_isinf:
1097 Result = expand16BitIsInf(Orig);
1098 break;
1099 case Intrinsic::dx_isnan:
1100 Result = expand16BitIsNaN(Orig);
1101 break;
1102 case Intrinsic::dx_lerp:
1103 Result = expandLerpIntrinsic(Orig);
1104 break;
1105 case Intrinsic::dx_normalize:
1106 Result = expandNormalizeIntrinsic(Orig);
1107 break;
1108 case Intrinsic::dx_fdot:
1109 Result = expandFloatDotIntrinsic(Orig);
1110 break;
1111 case Intrinsic::dx_sdot:
1112 case Intrinsic::dx_udot:
1113 Result = expandIntegerDotIntrinsic(Orig, IntrinsicId);
1114 break;
1115 case Intrinsic::dx_sign:
1116 Result = expandSignIntrinsic(Orig);
1117 break;
1118 case Intrinsic::dx_step:
1119 Result = expandStepIntrinsic(Orig);
1120 break;
1121 case Intrinsic::dx_radians:
1122 Result = expandRadiansIntrinsic(Orig);
1123 break;
1124 case Intrinsic::dx_resource_load_rawbuffer:
1125 if (expandBufferLoadIntrinsic(Orig, /*IsRaw*/ true))
1126 return true;
1127 break;
1128 case Intrinsic::dx_resource_store_rawbuffer:
1129 if (expandBufferStoreIntrinsic(Orig, /*IsRaw*/ true))
1130 return true;
1131 break;
1132 case Intrinsic::dx_resource_load_typedbuffer:
1133 if (expandBufferLoadIntrinsic(Orig, /*IsRaw*/ false))
1134 return true;
1135 break;
1136 case Intrinsic::dx_resource_store_typedbuffer:
1137 if (expandBufferStoreIntrinsic(Orig, /*IsRaw*/ false))
1138 return true;
1139 break;
1140 case Intrinsic::usub_sat:
1141 Result = expandUsubSat(Orig);
1142 break;
1143 case Intrinsic::vector_reduce_add:
1144 case Intrinsic::vector_reduce_fadd:
1145 Result = expandVecReduceAdd(Orig, IntrinsicId);
1146 break;
1147 }
1148 if (Result) {
1149 Orig->replaceAllUsesWith(Result);
1150 Orig->eraseFromParent();
1151 return true;
1152 }
1153 return false;
1154}
1155
1157 for (auto &F : make_early_inc_range(M.functions())) {
1158 if (!isIntrinsicExpansion(F))
1159 continue;
1160 bool IntrinsicExpanded = false;
1161 for (User *U : make_early_inc_range(F.users())) {
1162 auto *IntrinsicCall = dyn_cast<CallInst>(U);
1163 if (!IntrinsicCall)
1164 continue;
1165 IntrinsicExpanded = expandIntrinsic(F, IntrinsicCall);
1166 }
1167 if (F.user_empty() && IntrinsicExpanded)
1168 F.eraseFromParent();
1169 }
1170 return true;
1171}
1172
1179
1183
1185
1187 "DXIL Intrinsic Expansion", false, false)
1189 "DXIL Intrinsic Expansion", false, false)
1190
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")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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)
static Value * expandFunnelShiftIntrinsic(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:54
#define I(x, y, z)
Definition MD5.cpp:57
#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:1427
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
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:802
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:2794
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:413
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:197
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
Definition Type.cpp:295
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:300
Value * getOperand(unsigned i) const
Definition User.h:233
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:553
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
constexpr float ln10f
Definition MathExtras.h:50
constexpr float log2ef
Definition MathExtras.h:51
constexpr double pi
constexpr float ln2f
Definition MathExtras.h:49
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:632
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
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:559
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