22#include "llvm/IR/IntrinsicsDirectX.h"
30#define DEBUG_TYPE "dxil-intrinsic-expansion"
35 switch (
F.getIntrinsicID()) {
39 case Intrinsic::log10:
41 case Intrinsic::dx_any:
42 case Intrinsic::dx_clamp:
43 case Intrinsic::dx_uclamp:
44 case Intrinsic::dx_lerp:
45 case Intrinsic::dx_length:
46 case Intrinsic::dx_normalize:
47 case Intrinsic::dx_sdot:
48 case Intrinsic::dx_udot:
58 Type *Ty =
X->getType();
64 ConstantInt::get(EltTy, 0))
65 : ConstantInt::get(EltTy, 0);
75 assert(DotIntrinsic == Intrinsic::dx_sdot ||
76 DotIntrinsic == Intrinsic::dx_udot);
77 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
82 [[maybe_unused]]
Type *ATy =
A->getType();
83 [[maybe_unused]]
Type *BTy =
B->getType();
89 auto *AVec = dyn_cast<FixedVectorType>(
A->getType());
93 for (
unsigned I = 1;
I < AVec->getNumElements();
I++) {
109 Type *Ty =
X->getType();
119 Builder.
CreateIntrinsic(Ty, Intrinsic::exp2, {NewX},
nullptr,
"dx.exp2");
131 Type *Ty =
X->getType();
140 auto *XVec = dyn_cast<FixedVectorType>(Ty);
146 ConstantFP::get(EltTy, 0)))
150 ConstantInt::get(EltTy, 0)));
152 for (
unsigned I = 1;
I < XVec->getNumElements();
I++) {
154 Result = Builder.
CreateOr(Result, Elt);
166 Type *Ty =
X->getType();
173 auto *XVec = dyn_cast<FixedVectorType>(Ty);
174 unsigned XVecSize = XVec->getNumElements();
180 for (
unsigned I = 1;
I < XVecSize;
I++) {
201 auto *Result = Builder.
CreateFAdd(
X, V,
"dx.lerp");
212 Type *Ty =
X->getType();
218 ConstantFP::get(EltTy, LogConstVal))
219 : ConstantFP::get(EltTy, LogConstVal);
224 auto *Result = Builder.
CreateFMul(Ln2Const, Log2Call);
240 auto *XVec = dyn_cast<FixedVectorType>(Ty);
242 if (
auto *constantFP = dyn_cast<ConstantFP>(
X)) {
243 const APFloat &fpVal = constantFP->getValueAPF();
256 unsigned XVecSize = XVec->getNumElements();
257 Value *DotProduct =
nullptr;
283 if (
auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) {
284 const APFloat &fpVal = constantFP->getValueAPF();
292 nullptr,
"dx.rsqrt");
306 Type *Ty =
X->getType();
324 if (ClampIntrinsic == Intrinsic::dx_uclamp)
325 return Intrinsic::umax;
326 assert(ClampIntrinsic == Intrinsic::dx_clamp);
330 return Intrinsic::smax;
332 return Intrinsic::maxnum;
337 if (ClampIntrinsic == Intrinsic::dx_uclamp)
338 return Intrinsic::umin;
339 assert(ClampIntrinsic == Intrinsic::dx_clamp);
343 return Intrinsic::smin;
345 return Intrinsic::minnum;
352 Type *Ty =
X->getType();
359 {MaxCall, Max},
nullptr,
"dx.min");
367 switch (
F.getIntrinsicID()) {
374 case Intrinsic::log10:
378 case Intrinsic::dx_any:
380 case Intrinsic::dx_uclamp:
381 case Intrinsic::dx_clamp:
383 case Intrinsic::dx_lerp:
385 case Intrinsic::dx_length:
387 case Intrinsic::dx_normalize:
389 case Intrinsic::dx_sdot:
390 case Intrinsic::dx_udot:
400 bool IntrinsicExpanded =
false;
402 auto *IntrinsicCall = dyn_cast<CallInst>(U);
407 if (
F.user_empty() && IntrinsicExpanded)
427 "DXIL Intrinsic Expansion",
false,
false)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool expandIntrinsic(Function &F, CallInst *Orig)
static bool expandLog10Intrinsic(CallInst *Orig)
static bool expansionIntrinsics(Module &M)
static bool expandAbs(CallInst *Orig)
static bool expandExpIntrinsic(CallInst *Orig)
static bool expandLengthIntrinsic(CallInst *Orig)
static bool expandPowIntrinsic(CallInst *Orig)
static bool expandAnyIntrinsic(CallInst *Orig)
static bool expandIntegerDot(CallInst *Orig, Intrinsic::ID DotIntrinsic)
static bool expandLogIntrinsic(CallInst *Orig, float LogConstVal=numbers::ln2f)
static Intrinsic::ID getMaxForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic)
static Intrinsic::ID getMinForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic)
static bool expandNormalizeIntrinsic(CallInst *Orig)
static bool isIntrinsicExpansion(Function &F)
static bool expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic)
static bool expandLerpIntrinsic(CallInst *Orig)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getNumElements(Type *Ty)
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
AttributeList getAttributes() const
Return the parameter attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCall(bool IsTc=true)
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Value * CreateFSub(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateFDiv(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateFAdd(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateFMul(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
const ParentTy * getParent() const
This is an optimization pass for GlobalISel generic memory operations.
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...
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
ModulePass * createDXILIntrinsicExpansionLegacyPass()
Pass to expand intrinsic operations that lack DXIL opCodes.