14#include "llvm/IR/IntrinsicsDirectX.h"
17#define DEBUG_TYPE "dxil-mem-intrinsics"
26 assert(LengthCI &&
"Expected length to be a ConstantInt");
29 Builder.GetInsertBlock()->getModule()->getDataLayout();
34 assert(Alloca &&
"Expected memset on an Alloca");
36 "Expected for memset size to match DataLayout size");
40 assert(ArrTy &&
"Expected Alloca for an Array Type");
42 Type *ElemTy = ArrTy->getElementType();
45 [[maybe_unused]]
uint64_t ElemSize =
DL.getTypeStoreSize(ElemTy);
47 assert(ElemSize > 0 &&
"Size must be set");
48 assert(OrigLength == ElemSize *
Size &&
"Size in bytes must match");
50 Value *TypedVal = Val;
53 TypedVal = Builder.CreateIntCast(Val, ElemTy,
false);
56 Value *Zero = Builder.getInt32(0);
58 Value *Ptr = Builder.CreateGEP(ArrTy, Dst, {Zero,
Offset},
"gep");
59 Builder.CreateStore(TypedVal, Ptr);
67 return GV->getValueType();
69 return AI->getAllocatedType();
72 if (
II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
75 assert(Ty &&
"getpointer used on untyped resource");
81 Type *Ty =
GEP->getResultElementType();
82 if (!Ty->isIntegerTy(8))
89 return AT->getElementType();
93 APInt ConstantOffset(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
94 [[maybe_unused]]
bool IsConst =
95 GEP->accumulateConstantOffset(
DL, ConstantOffset);
96 assert(IsConst &&
"Non-constant GEP into struct?");
103 return ST->getTypeAtIndex(Idx);
114 size_t NextOffset = 0) {
117 NextOffset =
flattenTypes(AT->getElementType(),
DL, FlatTys, NextOffset);
121 for (
Type *Ty : ST->elements())
126 FlatTys.emplace_back(ContainerTy, NextOffset);
127 return NextOffset +
DL.getTypeStoreSize(ContainerTy);
135 assert(LengthCI &&
"Expected Length to be a ConstantInt");
143 const DataLayout &
DL = Builder.GetInsertBlock()->getModule()->getDataLayout();
146 [[maybe_unused]]
size_t MaxLength =
148 assert(MaxLength >= ByteLength &&
"Dst not large enough for memcpy");
155 assert(SrcLength >= ByteLength &&
"Src not large enough for memcpy");
156 for (
const auto &[
LHS,
RHS] :
zip(FlattenedTypes, SrcTypes)) {
157 auto &[DstTy, DstOffset] =
LHS;
158 auto &[SrcTy, SrcOffset] =
RHS;
159 assert(DstTy == SrcTy &&
"Mismatched types for memcpy");
160 assert(DstOffset == SrcOffset &&
"Incompatible layouts for memcpy");
161 if (DstOffset >= ByteLength)
166 for (
const auto &[Ty,
Offset] : FlattenedTypes) {
172 Value *SrcPtr = Builder.CreateInBoundsGEP(Int8Ty, Src, ByteOffset);
173 Value *SrcVal = Builder.CreateLoad(Ty, SrcPtr);
174 Value *DstPtr = Builder.CreateInBoundsGEP(Int8Ty, Dst, ByteOffset);
175 Builder.CreateStore(SrcVal, DstPtr);
186 bool HadMemIntrinsicUses =
false;
190 case Intrinsic::memcpy:
191 case Intrinsic::memcpy_inline:
192 case Intrinsic::memmove:
193 case Intrinsic::memset:
194 case Intrinsic::memset_inline:
200 HadMemIntrinsicUses =
true;
210 assert(
F.user_empty() &&
"Mem intrinsic not eliminated?");
213 return HadMemIntrinsicUses;
232 "DXIL Memory Intrinsic Elimination",
false,
false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static size_t flattenTypes(Type *ContainerTy, const DataLayout &DL, SmallVectorImpl< std::pair< Type *, size_t > > &FlatTys, size_t NextOffset=0)
static bool eliminateMemIntrinsics(Module &M)
void expandMemSet(MemSetInst *MemSet)
void expandMemCpy(MemCpyInst *MemCpy)
static Type * getPointeeType(Value *Ptr, const DataLayout &DL)
void expandMemMove(MemMoveInst *MemMove)
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
DXILMemIntrinsicsLegacy()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
an instruction to allocate memory on the stack
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
A parsed version of the target data layout string in and methods for querying it.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This class wraps the llvm.memcpy intrinsic.
Value * getLength() const
Value * getDest() const
This is just like getRawDest, but it strips off any cast instructions (including addrspacecast) that ...
This class wraps the llvm.memmove intrinsic.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
Value * getSource() const
This is just like getRawSource, but it strips off any cast instructions that feed 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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
LLVM_ABI unsigned getElementContainingOffset(uint64_t FixedOffset) const
Given a valid byte offset into the structure, returns the structure index that contains it.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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...
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
ModulePass * createDXILMemIntrinsicsLegacyPass()
Pass to transform all llvm memory intrinsics to explicit loads and stores.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.