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_sdot:
46 case Intrinsic::dx_udot:
56 Type *Ty =
X->getType();
61 cast<FixedVectorType>(Ty)->getNumElements()),
62 ConstantInt::get(EltTy, 0))
63 : ConstantInt::get(EltTy, 0);
73 assert(DotIntrinsic == Intrinsic::dx_sdot ||
74 DotIntrinsic == Intrinsic::dx_udot);
75 Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot
80 [[maybe_unused]]
Type *ATy =
A->getType();
81 [[maybe_unused]]
Type *BTy =
B->getType();
87 auto *AVec = dyn_cast<FixedVectorType>(
A->getType());
91 for (
unsigned I = 1;
I < AVec->getNumElements();
I++) {
107 Type *Ty =
X->getType();
112 cast<FixedVectorType>(Ty)->getNumElements()),
117 Builder.
CreateIntrinsic(Ty, Intrinsic::exp2, {NewX},
nullptr,
"dx.exp2");
129 Type *Ty =
X->getType();
138 auto *XVec = dyn_cast<FixedVectorType>(Ty);
144 ConstantFP::get(EltTy, 0)))
148 ConstantInt::get(EltTy, 0)));
150 for (
unsigned I = 1;
I < XVec->getNumElements();
I++) {
152 Result = Builder.
CreateOr(Result, Elt);
168 auto *Result = Builder.
CreateFAdd(
X, V,
"dx.lerp");
179 Type *Ty =
X->getType();
184 cast<FixedVectorType>(Ty)->getNumElements()),
185 ConstantFP::get(EltTy, LogConstVal))
186 : ConstantFP::get(EltTy, LogConstVal);
191 auto *Result = Builder.
CreateFMul(Ln2Const, Log2Call);
204 Type *Ty =
X->getType();
222 if (ClampIntrinsic == Intrinsic::dx_uclamp)
223 return Intrinsic::umax;
224 assert(ClampIntrinsic == Intrinsic::dx_clamp);
228 return Intrinsic::smax;
230 return Intrinsic::maxnum;
235 if (ClampIntrinsic == Intrinsic::dx_uclamp)
236 return Intrinsic::umin;
237 assert(ClampIntrinsic == Intrinsic::dx_clamp);
241 return Intrinsic::smin;
243 return Intrinsic::minnum;
250 Type *Ty =
X->getType();
257 {MaxCall, Max},
nullptr,
"dx.min");
265 switch (
F.getIntrinsicID()) {
272 case Intrinsic::log10:
276 case Intrinsic::dx_any:
278 case Intrinsic::dx_uclamp:
279 case Intrinsic::dx_clamp:
281 case Intrinsic::dx_lerp:
283 case Intrinsic::dx_sdot:
284 case Intrinsic::dx_udot:
294 bool IntrinsicExpanded =
false;
296 auto *IntrinsicCall = dyn_cast<CallInst>(U);
301 if (
F.user_empty() && IntrinsicExpanded)
321 "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 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 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())
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 * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateFAdd(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
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...
const BasicBlock * getParent() const
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.
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.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
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...
ModulePass * createDXILIntrinsicExpansionLegacyPass()
Pass to expand intrinsic operations that lack DXIL opCodes.