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);
72 assert(DotIntrinsic == Intrinsic::dx_sdot ||
73 DotIntrinsic == Intrinsic::dx_udot);
74 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
79 [[maybe_unused]]
Type *ATy =
A->getType();
80 [[maybe_unused]]
Type *BTy =
B->getType();
86 auto *AVec = dyn_cast<FixedVectorType>(
A->getType());
90 for (
unsigned I = 1;
I < AVec->getNumElements();
I++) {
104 Type *Ty =
X->getType();
114 Builder.
CreateIntrinsic(Ty, Intrinsic::exp2, {NewX},
nullptr,
"dx.exp2");
124 Type *Ty =
X->getType();
127 Value *Result =
nullptr;
133 auto *XVec = dyn_cast<FixedVectorType>(Ty);
139 ConstantFP::get(EltTy, 0)))
143 ConstantInt::get(EltTy, 0)));
145 for (
unsigned I = 1;
I < XVec->getNumElements();
I++) {
147 Result = Builder.
CreateOr(Result, Elt);
157 Type *Ty =
X->getType();
164 auto *XVec = dyn_cast<FixedVectorType>(Ty);
165 unsigned XVecSize = XVec->getNumElements();
171 for (
unsigned I = 1;
I < XVecSize;
I++) {
177 nullptr,
"elt.sqrt");
196 Type *Ty =
X->getType();
202 ConstantFP::get(EltTy, LogConstVal))
203 : ConstantFP::get(EltTy, LogConstVal);
208 return Builder.
CreateFMul(Ln2Const, Log2Call);
221 auto *XVec = dyn_cast<FixedVectorType>(Ty);
223 if (
auto *constantFP = dyn_cast<ConstantFP>(
X)) {
224 const APFloat &fpVal = constantFP->getValueAPF();
232 unsigned XVecSize = XVec->getNumElements();
233 Value *DotProduct =
nullptr;
259 if (
auto *constantFP = dyn_cast<ConstantFP>(DotProduct)) {
260 const APFloat &fpVal = constantFP->getValueAPF();
268 nullptr,
"dx.rsqrt");
278 Type *Ty =
X->getType();
294 if (ClampIntrinsic == Intrinsic::dx_uclamp)
295 return Intrinsic::umax;
296 assert(ClampIntrinsic == Intrinsic::dx_clamp);
300 return Intrinsic::smax;
302 return Intrinsic::maxnum;
307 if (ClampIntrinsic == Intrinsic::dx_uclamp)
308 return Intrinsic::umin;
309 assert(ClampIntrinsic == Intrinsic::dx_clamp);
313 return Intrinsic::smin;
315 return Intrinsic::minnum;
323 Type *Ty =
X->getType();
329 {MaxCall, Max},
nullptr,
"dx.min");
333 Value *Result =
nullptr;
334 switch (
F.getIntrinsicID()) {
344 case Intrinsic::log10:
350 case Intrinsic::dx_any:
353 case Intrinsic::dx_uclamp:
354 case Intrinsic::dx_clamp:
357 case Intrinsic::dx_lerp:
360 case Intrinsic::dx_length:
363 case Intrinsic::dx_normalize:
366 case Intrinsic::dx_sdot:
367 case Intrinsic::dx_udot:
384 bool IntrinsicExpanded =
false;
386 auto *IntrinsicCall = dyn_cast<CallInst>(U);
391 if (
F.user_empty() && IntrinsicExpanded)
411 "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 Value * expandNormalizeIntrinsic(CallInst *Orig)
static bool expandIntrinsic(Function &F, CallInst *Orig)
static Value * expandLengthIntrinsic(CallInst *Orig)
static Value * expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic)
static bool expansionIntrinsics(Module &M)
static Value * expandLerpIntrinsic(CallInst *Orig)
static Value * expandAnyIntrinsic(CallInst *Orig)
static Value * expandLog10Intrinsic(CallInst *Orig)
static Value * expandPowIntrinsic(CallInst *Orig)
static Value * expandLogIntrinsic(CallInst *Orig, float LogConstVal=numbers::ln2f)
static Value * expandExpIntrinsic(CallInst *Orig)
static Value * expandIntegerDot(CallInst *Orig, Intrinsic::ID DotIntrinsic)
static Intrinsic::ID getMaxForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic)
static Intrinsic::ID getMinForClamp(Type *ElemTy, Intrinsic::ID ClampIntrinsic)
static Value * expandAbs(CallInst *Orig)
static bool isIntrinsicExpansion(Function &F)
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.