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/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"
30
31#define DEBUG_TYPE "dxil-intrinsic-expansion"
32
33using namespace llvm;
34
36
37public:
38 bool runOnModule(Module &M) override;
40
41 static char ID; // Pass identification.
42};
43
45 switch (F.getIntrinsicID()) {
46 case Intrinsic::abs:
47 case Intrinsic::atan2:
48 case Intrinsic::exp:
49 case Intrinsic::log:
50 case Intrinsic::log10:
51 case Intrinsic::pow:
52 case Intrinsic::dx_all:
53 case Intrinsic::dx_any:
54 case Intrinsic::dx_cross:
55 case Intrinsic::dx_uclamp:
56 case Intrinsic::dx_sclamp:
57 case Intrinsic::dx_nclamp:
58 case Intrinsic::dx_degrees:
59 case Intrinsic::dx_lerp:
60 case Intrinsic::dx_normalize:
61 case Intrinsic::dx_fdot:
62 case Intrinsic::dx_sdot:
63 case Intrinsic::dx_udot:
64 case Intrinsic::dx_sign:
65 case Intrinsic::dx_step:
66 case Intrinsic::dx_radians:
67 case Intrinsic::vector_reduce_add:
68 case Intrinsic::vector_reduce_fadd:
69 return true;
70 }
71 return false;
72}
73static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
74 assert(IntrinsicId == Intrinsic::vector_reduce_add ||
75 IntrinsicId == Intrinsic::vector_reduce_fadd);
76
77 IRBuilder<> Builder(Orig);
78 bool IsFAdd = (IntrinsicId == Intrinsic::vector_reduce_fadd);
79
80 Value *X = Orig->getOperand(IsFAdd ? 1 : 0);
81 Type *Ty = X->getType();
82 auto *XVec = dyn_cast<FixedVectorType>(Ty);
83 unsigned XVecSize = XVec->getNumElements();
84 Value *Sum = Builder.CreateExtractElement(X, static_cast<uint64_t>(0));
85
86 // Handle the initial start value for floating-point addition.
87 if (IsFAdd) {
88 Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
89 if (StartValue && !StartValue->isZeroValue())
90 Sum = Builder.CreateFAdd(Sum, StartValue);
91 }
92
93 // Accumulate the remaining vector elements.
94 for (unsigned I = 1; I < XVecSize; I++) {
95 Value *Elt = Builder.CreateExtractElement(X, I);
96 if (IsFAdd)
97 Sum = Builder.CreateFAdd(Sum, Elt);
98 else
99 Sum = Builder.CreateAdd(Sum, Elt);
100 }
101
102 return Sum;
103}
104
105static Value *expandAbs(CallInst *Orig) {
106 Value *X = Orig->getOperand(0);
107 IRBuilder<> Builder(Orig);
108 Type *Ty = X->getType();
109 Type *EltTy = Ty->getScalarType();
110 Constant *Zero = Ty->isVectorTy()
113 cast<FixedVectorType>(Ty)->getNumElements()),
114 ConstantInt::get(EltTy, 0))
115 : ConstantInt::get(EltTy, 0);
116 auto *V = Builder.CreateSub(Zero, X);
117 return Builder.CreateIntrinsic(Ty, Intrinsic::smax, {X, V}, nullptr,
118 "dx.max");
119}
120
122
123 VectorType *VT = cast<VectorType>(Orig->getType());
124 if (cast<FixedVectorType>(VT)->getNumElements() != 3)
125 report_fatal_error(Twine("return vector must have exactly 3 elements"),
126 /* gen_crash_diag=*/false);
127
128 Value *op0 = Orig->getOperand(0);
129 Value *op1 = Orig->getOperand(1);
130 IRBuilder<> Builder(Orig);
131
132 Value *op0_x = Builder.CreateExtractElement(op0, (uint64_t)0, "x0");
133 Value *op0_y = Builder.CreateExtractElement(op0, 1, "x1");
134 Value *op0_z = Builder.CreateExtractElement(op0, 2, "x2");
135
136 Value *op1_x = Builder.CreateExtractElement(op1, (uint64_t)0, "y0");
137 Value *op1_y = Builder.CreateExtractElement(op1, 1, "y1");
138 Value *op1_z = Builder.CreateExtractElement(op1, 2, "y2");
139
140 auto MulSub = [&](Value *x0, Value *y0, Value *x1, Value *y1) -> Value * {
141 Value *xy = Builder.CreateFMul(x0, y1);
142 Value *yx = Builder.CreateFMul(y0, x1);
143 return Builder.CreateFSub(xy, yx, Orig->getName());
144 };
145
146 Value *yz_zy = MulSub(op0_y, op0_z, op1_y, op1_z);
147 Value *zx_xz = MulSub(op0_z, op0_x, op1_z, op1_x);
148 Value *xy_yx = MulSub(op0_x, op0_y, op1_x, op1_y);
149
150 Value *cross = UndefValue::get(VT);
151 cross = Builder.CreateInsertElement(cross, yz_zy, (uint64_t)0);
152 cross = Builder.CreateInsertElement(cross, zx_xz, 1);
153 cross = Builder.CreateInsertElement(cross, xy_yx, 2);
154 return cross;
155}
156
157// Create appropriate DXIL float dot intrinsic for the given A and B operands
158// The appropriate opcode will be determined by the size of the operands
159// The dot product is placed in the position indicated by Orig
161 Type *ATy = A->getType();
162 [[maybe_unused]] Type *BTy = B->getType();
163 assert(ATy->isVectorTy() && BTy->isVectorTy());
164
165 IRBuilder<> Builder(Orig);
166
167 auto *AVec = dyn_cast<FixedVectorType>(ATy);
168
170
171 Intrinsic::ID DotIntrinsic = Intrinsic::dx_dot4;
172 switch (AVec->getNumElements()) {
173 case 2:
174 DotIntrinsic = Intrinsic::dx_dot2;
175 break;
176 case 3:
177 DotIntrinsic = Intrinsic::dx_dot3;
178 break;
179 case 4:
180 DotIntrinsic = Intrinsic::dx_dot4;
181 break;
182 default:
184 Twine("Invalid dot product input vector: length is outside 2-4"),
185 /* gen_crash_diag=*/false);
186 return nullptr;
187 }
188 return Builder.CreateIntrinsic(ATy->getScalarType(), DotIntrinsic,
189 ArrayRef<Value *>{A, B}, nullptr, "dot");
190}
191
192// Create the appropriate DXIL float dot intrinsic for the operands of Orig
193// The appropriate opcode will be determined by the size of the operands
194// The dot product is placed in the position indicated by Orig
196 return expandFloatDotIntrinsic(Orig, Orig->getOperand(0),
197 Orig->getOperand(1));
198}
199
200// Expand integer dot product to multiply and add ops
202 Intrinsic::ID DotIntrinsic) {
203 assert(DotIntrinsic == Intrinsic::dx_sdot ||
204 DotIntrinsic == Intrinsic::dx_udot);
205 Value *A = Orig->getOperand(0);
206 Value *B = Orig->getOperand(1);
207 Type *ATy = A->getType();
208 [[maybe_unused]] Type *BTy = B->getType();
209 assert(ATy->isVectorTy() && BTy->isVectorTy());
210
211 IRBuilder<> Builder(Orig);
212
213 auto *AVec = dyn_cast<FixedVectorType>(ATy);
214
216
217 Value *Result;
218 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
219 ? Intrinsic::dx_imad
220 : Intrinsic::dx_umad;
221 Value *Elt0 = Builder.CreateExtractElement(A, (uint64_t)0);
222 Value *Elt1 = Builder.CreateExtractElement(B, (uint64_t)0);
223 Result = Builder.CreateMul(Elt0, Elt1);
224 for (unsigned I = 1; I < AVec->getNumElements(); I++) {
225 Elt0 = Builder.CreateExtractElement(A, I);
226 Elt1 = Builder.CreateExtractElement(B, I);
227 Result = Builder.CreateIntrinsic(Result->getType(), MadIntrinsic,
228 ArrayRef<Value *>{Elt0, Elt1, Result},
229 nullptr, "dx.mad");
230 }
231 return Result;
232}
233
235 Value *X = Orig->getOperand(0);
236 IRBuilder<> Builder(Orig);
237 Type *Ty = X->getType();
238 Type *EltTy = Ty->getScalarType();
239 Constant *Log2eConst =
242 cast<FixedVectorType>(Ty)->getNumElements()),
243 ConstantFP::get(EltTy, numbers::log2ef))
244 : ConstantFP::get(EltTy, numbers::log2ef);
245 Value *NewX = Builder.CreateFMul(Log2eConst, X);
246 auto *Exp2Call =
247 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2");
248 Exp2Call->setTailCall(Orig->isTailCall());
249 Exp2Call->setAttributes(Orig->getAttributes());
250 return Exp2Call;
251}
252
254 Intrinsic::ID intrinsicId) {
255 Value *X = Orig->getOperand(0);
256 IRBuilder<> Builder(Orig);
257 Type *Ty = X->getType();
258 Type *EltTy = Ty->getScalarType();
259
260 auto ApplyOp = [&Builder](Intrinsic::ID IntrinsicId, Value *Result,
261 Value *Elt) {
262 if (IntrinsicId == Intrinsic::dx_any)
263 return Builder.CreateOr(Result, Elt);
264 assert(IntrinsicId == Intrinsic::dx_all);
265 return Builder.CreateAnd(Result, Elt);
266 };
267
268 Value *Result = nullptr;
269 if (!Ty->isVectorTy()) {
270 Result = EltTy->isFloatingPointTy()
271 ? Builder.CreateFCmpUNE(X, ConstantFP::get(EltTy, 0))
272 : Builder.CreateICmpNE(X, ConstantInt::get(EltTy, 0));
273 } else {
274 auto *XVec = dyn_cast<FixedVectorType>(Ty);
275 Value *Cond =
276 EltTy->isFloatingPointTy()
277 ? Builder.CreateFCmpUNE(
279 ElementCount::getFixed(XVec->getNumElements()),
280 ConstantFP::get(EltTy, 0)))
281 : Builder.CreateICmpNE(
283 ElementCount::getFixed(XVec->getNumElements()),
284 ConstantInt::get(EltTy, 0)));
285 Result = Builder.CreateExtractElement(Cond, (uint64_t)0);
286 for (unsigned I = 1; I < XVec->getNumElements(); I++) {
287 Value *Elt = Builder.CreateExtractElement(Cond, I);
288 Result = ApplyOp(intrinsicId, Result, Elt);
289 }
290 }
291 return Result;
292}
293
295 Value *X = Orig->getOperand(0);
296 Value *Y = Orig->getOperand(1);
297 Value *S = Orig->getOperand(2);
298 IRBuilder<> Builder(Orig);
299 auto *V = Builder.CreateFSub(Y, X);
300 V = Builder.CreateFMul(S, V);
301 return Builder.CreateFAdd(X, V, "dx.lerp");
302}
303
305 float LogConstVal = numbers::ln2f) {
306 Value *X = Orig->getOperand(0);
307 IRBuilder<> Builder(Orig);
308 Type *Ty = X->getType();
309 Type *EltTy = Ty->getScalarType();
310 Constant *Ln2Const =
313 cast<FixedVectorType>(Ty)->getNumElements()),
314 ConstantFP::get(EltTy, LogConstVal))
315 : ConstantFP::get(EltTy, LogConstVal);
316 auto *Log2Call =
317 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
318 Log2Call->setTailCall(Orig->isTailCall());
319 Log2Call->setAttributes(Orig->getAttributes());
320 return Builder.CreateFMul(Ln2Const, Log2Call);
321}
324}
325
326// Use dot product of vector operand with itself to calculate the length.
327// Divide the vector by that length to normalize it.
329 Value *X = Orig->getOperand(0);
330 Type *Ty = Orig->getType();
331 Type *EltTy = Ty->getScalarType();
332 IRBuilder<> Builder(Orig);
333
334 auto *XVec = dyn_cast<FixedVectorType>(Ty);
335 if (!XVec) {
336 if (auto *constantFP = dyn_cast<ConstantFP>(X)) {
337 const APFloat &fpVal = constantFP->getValueAPF();
338 if (fpVal.isZero())
339 report_fatal_error(Twine("Invalid input scalar: length is zero"),
340 /* gen_crash_diag=*/false);
341 }
342 return Builder.CreateFDiv(X, X);
343 }
344
345 Value *DotProduct = expandFloatDotIntrinsic(Orig, X, X);
346
347 // verify that the length is non-zero
348 // (if the dot product is non-zero, then the length is non-zero)
349 if (auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) {
350 const APFloat &fpVal = constantFP->getValueAPF();
351 if (fpVal.isZero())
352 report_fatal_error(Twine("Invalid input vector: length is zero"),
353 /* gen_crash_diag=*/false);
354 }
355
356 Value *Multiplicand = Builder.CreateIntrinsic(EltTy, Intrinsic::dx_rsqrt,
357 ArrayRef<Value *>{DotProduct},
358 nullptr, "dx.rsqrt");
359
360 Value *MultiplicandVec =
361 Builder.CreateVectorSplat(XVec->getNumElements(), Multiplicand);
362 return Builder.CreateFMul(X, MultiplicandVec);
363}
364
366 Value *Y = Orig->getOperand(0);
367 Value *X = Orig->getOperand(1);
368 Type *Ty = X->getType();
369 IRBuilder<> Builder(Orig);
370 Builder.setFastMathFlags(Orig->getFastMathFlags());
371
372 Value *Tan = Builder.CreateFDiv(Y, X);
373
374 CallInst *Atan =
375 Builder.CreateIntrinsic(Ty, Intrinsic::atan, {Tan}, nullptr, "Elt.Atan");
376 Atan->setTailCall(Orig->isTailCall());
377 Atan->setAttributes(Orig->getAttributes());
378
379 // Modify atan result based on https://en.wikipedia.org/wiki/Atan2.
380 Constant *Pi = ConstantFP::get(Ty, llvm::numbers::pi);
381 Constant *HalfPi = ConstantFP::get(Ty, llvm::numbers::pi / 2);
382 Constant *NegHalfPi = ConstantFP::get(Ty, -llvm::numbers::pi / 2);
383 Constant *Zero = ConstantFP::get(Ty, 0);
384 Value *AtanAddPi = Builder.CreateFAdd(Atan, Pi);
385 Value *AtanSubPi = Builder.CreateFSub(Atan, Pi);
386
387 // x > 0 -> atan.
388 Value *Result = Atan;
389 Value *XLt0 = Builder.CreateFCmpOLT(X, Zero);
390 Value *XEq0 = Builder.CreateFCmpOEQ(X, Zero);
391 Value *YGe0 = Builder.CreateFCmpOGE(Y, Zero);
392 Value *YLt0 = Builder.CreateFCmpOLT(Y, Zero);
393
394 // x < 0, y >= 0 -> atan + pi.
395 Value *XLt0AndYGe0 = Builder.CreateAnd(XLt0, YGe0);
396 Result = Builder.CreateSelect(XLt0AndYGe0, AtanAddPi, Result);
397
398 // x < 0, y < 0 -> atan - pi.
399 Value *XLt0AndYLt0 = Builder.CreateAnd(XLt0, YLt0);
400 Result = Builder.CreateSelect(XLt0AndYLt0, AtanSubPi, Result);
401
402 // x == 0, y < 0 -> -pi/2
403 Value *XEq0AndYLt0 = Builder.CreateAnd(XEq0, YLt0);
404 Result = Builder.CreateSelect(XEq0AndYLt0, NegHalfPi, Result);
405
406 // x == 0, y > 0 -> pi/2
407 Value *XEq0AndYGe0 = Builder.CreateAnd(XEq0, YGe0);
408 Result = Builder.CreateSelect(XEq0AndYGe0, HalfPi, Result);
409
410 return Result;
411}
412
414
415 Value *X = Orig->getOperand(0);
416 Value *Y = Orig->getOperand(1);
417 Type *Ty = X->getType();
418 IRBuilder<> Builder(Orig);
419
420 auto *Log2Call =
421 Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2");
422 auto *Mul = Builder.CreateFMul(Log2Call, Y);
423 auto *Exp2Call =
424 Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2");
425 Exp2Call->setTailCall(Orig->isTailCall());
426 Exp2Call->setAttributes(Orig->getAttributes());
427 return Exp2Call;
428}
429
431
432 Value *X = Orig->getOperand(0);
433 Value *Y = Orig->getOperand(1);
434 Type *Ty = X->getType();
435 IRBuilder<> Builder(Orig);
436
437 Constant *One = ConstantFP::get(Ty->getScalarType(), 1.0);
438 Constant *Zero = ConstantFP::get(Ty->getScalarType(), 0.0);
439 Value *Cond = Builder.CreateFCmpOLT(Y, X);
440
441 if (Ty != Ty->getScalarType()) {
442 auto *XVec = dyn_cast<FixedVectorType>(Ty);
444 ElementCount::getFixed(XVec->getNumElements()), One);
446 ElementCount::getFixed(XVec->getNumElements()), Zero);
447 }
448
449 return Builder.CreateSelect(Cond, Zero, One);
450}
451
453 Value *X = Orig->getOperand(0);
454 Type *Ty = X->getType();
455 IRBuilder<> Builder(Orig);
456 Value *PiOver180 = ConstantFP::get(Ty, llvm::numbers::pi / 180.0);
457 return Builder.CreateFMul(X, PiOver180);
458}
459
461 if (ClampIntrinsic == Intrinsic::dx_uclamp)
462 return Intrinsic::umax;
463 if (ClampIntrinsic == Intrinsic::dx_sclamp)
464 return Intrinsic::smax;
465 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
466 return Intrinsic::maxnum;
467}
468
470 if (ClampIntrinsic == Intrinsic::dx_uclamp)
471 return Intrinsic::umin;
472 if (ClampIntrinsic == Intrinsic::dx_sclamp)
473 return Intrinsic::smin;
474 assert(ClampIntrinsic == Intrinsic::dx_nclamp);
475 return Intrinsic::minnum;
476}
477
479 Intrinsic::ID ClampIntrinsic) {
480 Value *X = Orig->getOperand(0);
481 Value *Min = Orig->getOperand(1);
482 Value *Max = Orig->getOperand(2);
483 Type *Ty = X->getType();
484 IRBuilder<> Builder(Orig);
485 auto *MaxCall = Builder.CreateIntrinsic(Ty, getMaxForClamp(ClampIntrinsic),
486 {X, Min}, nullptr, "dx.max");
487 return Builder.CreateIntrinsic(Ty, getMinForClamp(ClampIntrinsic),
488 {MaxCall, Max}, nullptr, "dx.min");
489}
490
492 Value *X = Orig->getOperand(0);
493 Type *Ty = X->getType();
494 IRBuilder<> Builder(Orig);
495 Value *DegreesRatio = ConstantFP::get(Ty, 180.0 * llvm::numbers::inv_pi);
496 return Builder.CreateFMul(X, DegreesRatio);
497}
498
500 Value *X = Orig->getOperand(0);
501 Type *Ty = X->getType();
502 Type *ScalarTy = Ty->getScalarType();
503 Type *RetTy = Orig->getType();
505
506 IRBuilder<> Builder(Orig);
507
508 Value *GT;
509 Value *LT;
510 if (ScalarTy->isFloatingPointTy()) {
511 GT = Builder.CreateFCmpOLT(Zero, X);
512 LT = Builder.CreateFCmpOLT(X, Zero);
513 } else {
514 assert(ScalarTy->isIntegerTy());
515 GT = Builder.CreateICmpSLT(Zero, X);
516 LT = Builder.CreateICmpSLT(X, Zero);
517 }
518
519 Value *ZextGT = Builder.CreateZExt(GT, RetTy);
520 Value *ZextLT = Builder.CreateZExt(LT, RetTy);
521
522 return Builder.CreateSub(ZextGT, ZextLT);
523}
524
525static bool expandIntrinsic(Function &F, CallInst *Orig) {
526 Value *Result = nullptr;
527 Intrinsic::ID IntrinsicId = F.getIntrinsicID();
528 switch (IntrinsicId) {
529 case Intrinsic::abs:
530 Result = expandAbs(Orig);
531 break;
532 case Intrinsic::atan2:
533 Result = expandAtan2Intrinsic(Orig);
534 break;
535 case Intrinsic::exp:
536 Result = expandExpIntrinsic(Orig);
537 break;
538 case Intrinsic::log:
539 Result = expandLogIntrinsic(Orig);
540 break;
541 case Intrinsic::log10:
542 Result = expandLog10Intrinsic(Orig);
543 break;
544 case Intrinsic::pow:
545 Result = expandPowIntrinsic(Orig);
546 break;
547 case Intrinsic::dx_all:
548 case Intrinsic::dx_any:
549 Result = expandAnyOrAllIntrinsic(Orig, IntrinsicId);
550 break;
551 case Intrinsic::dx_cross:
552 Result = expandCrossIntrinsic(Orig);
553 break;
554 case Intrinsic::dx_uclamp:
555 case Intrinsic::dx_sclamp:
556 case Intrinsic::dx_nclamp:
557 Result = expandClampIntrinsic(Orig, IntrinsicId);
558 break;
559 case Intrinsic::dx_degrees:
560 Result = expandDegreesIntrinsic(Orig);
561 break;
562 case Intrinsic::dx_lerp:
563 Result = expandLerpIntrinsic(Orig);
564 break;
565 case Intrinsic::dx_normalize:
566 Result = expandNormalizeIntrinsic(Orig);
567 break;
568 case Intrinsic::dx_fdot:
569 Result = expandFloatDotIntrinsic(Orig);
570 break;
571 case Intrinsic::dx_sdot:
572 case Intrinsic::dx_udot:
573 Result = expandIntegerDotIntrinsic(Orig, IntrinsicId);
574 break;
575 case Intrinsic::dx_sign:
576 Result = expandSignIntrinsic(Orig);
577 break;
578 case Intrinsic::dx_step:
579 Result = expandStepIntrinsic(Orig);
580 break;
581 case Intrinsic::dx_radians:
582 Result = expandRadiansIntrinsic(Orig);
583 break;
584 case Intrinsic::vector_reduce_add:
585 case Intrinsic::vector_reduce_fadd:
586 Result = expandVecReduceAdd(Orig, IntrinsicId);
587 break;
588 }
589 if (Result) {
590 Orig->replaceAllUsesWith(Result);
591 Orig->eraseFromParent();
592 return true;
593 }
594 return false;
595}
596
598 for (auto &F : make_early_inc_range(M.functions())) {
600 continue;
601 bool IntrinsicExpanded = false;
602 for (User *U : make_early_inc_range(F.users())) {
603 auto *IntrinsicCall = dyn_cast<CallInst>(U);
604 if (!IntrinsicCall)
605 continue;
606 IntrinsicExpanded = expandIntrinsic(F, IntrinsicCall);
607 }
608 if (F.user_empty() && IntrinsicExpanded)
609 F.eraseFromParent();
610 }
611 return true;
612}
613
616 if (expansionIntrinsics(M))
618 return PreservedAnalyses::all();
619}
620
622 return expansionIntrinsics(M);
623}
624
626
628 "DXIL Intrinsic Expansion", false, false)
630 "DXIL Intrinsic Expansion", false, false)
631
633 return new DXILIntrinsicExpansionLegacy();
634}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static Value * expandNormalizeIntrinsic(CallInst *Orig)
DXIL Intrinsic Expansion
static bool expandIntrinsic(Function &F, CallInst *Orig)
static Value * expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic)
static bool expansionIntrinsics(Module &M)
static Value * expandLerpIntrinsic(CallInst *Orig)
static Value * expandCrossIntrinsic(CallInst *Orig)
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 Value * expandPowIntrinsic(CallInst *Orig)
static Value * expandLogIntrinsic(CallInst *Orig, float LogConstVal=numbers::ln2f)
static Value * expandDegreesIntrinsic(CallInst *Orig)
static Value * expandExpIntrinsic(CallInst *Orig)
static Value * expandSignIntrinsic(CallInst *Orig)
static Intrinsic::ID getMaxForClamp(Intrinsic::ID ClampIntrinsic)
static Value * expandAnyOrAllIntrinsic(CallInst *Orig, Intrinsic::ID intrinsicId)
static Value * expandAbs(CallInst *Orig)
static Value * expandFloatDotIntrinsic(CallInst *Orig, Value *A, Value *B)
static Value * expandRadiansIntrinsic(CallInst *Orig)
static bool isIntrinsicExpansion(Function &F)
return RetTy
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#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
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#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 runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
bool isZero() const
Definition: APFloat.h:1441
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
void setAttributes(AttributeList A)
Set the attributes for this call.
Definition: InstrTypes.h:1420
AttributeList getAttributes() const
Return the attributes for this call.
Definition: InstrTypes.h:1417
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:1472
This is an important base class in LLVM.
Definition: Constant.h:42
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:373
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:311
Value * CreateFSub(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1594
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2510
Value * CreateFDiv(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1632
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2498
Value * CreateFAdd(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1575
Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Definition: IRBuilder.cpp:1153
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition: IRBuilder.cpp:1043
Value * CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2374
void setFastMathFlags(FastMathFlags NewFMF)
Set the fast-math flags to be used with generated fp-math operators.
Definition: IRBuilder.h:330
Value * CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2324
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2273
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:890
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1386
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition: IRBuilder.h:2032
Value * CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2309
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1517
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1369
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1539
Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2301
Value * CreateFMul(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1613
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1403
Value * CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2319
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2704
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:94
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: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:270
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:237
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition: Type.h:355
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1859
Value * getOperand(unsigned i) const
Definition: User.h:228
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
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
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.
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:657
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.