27#define DEBUG_TYPE "dxil-data-scalarization" 
   38    Type *NewElementType =
 
 
   84  typedef std::pair<AllocaInst *, SmallVector<Value *, 4>> AllocaAndGEPs;
 
   88  VectorToArrayMap VectorAllocaMap;
 
 
   99  bool MadeChange = 
false;
 
  105  VectorAllocaMap.clear();
 
 
  110DataScalarizerVisitor::lookupReplacementGlobal(
Value *CurrOperand) {
 
  112    auto It = GlobalMap.find(OldGlobal);
 
  113    if (It != GlobalMap.end()) {
 
  138      Builder.CreateAlloca(NewType, 
nullptr, AI.
getName() + 
".scalarize");
 
 
  148  if (CE && CE->getOpcode() == Instruction::GetElementPtr) {
 
  159  if (
GlobalVariable *NewGlobal = lookupReplacementGlobal(PtrOperand))
 
 
  166  Value *PtrOperand = 
SI.getPointerOperand();
 
  168  if (CE && CE->getOpcode() == Instruction::GetElementPtr) {
 
  172    StoreInst *NewStore = Builder.CreateStore(
SI.getValueOperand(), OldGEP);
 
  174    SI.replaceAllUsesWith(NewStore);
 
  175    SI.eraseFromParent();
 
  179  if (
GlobalVariable *NewGlobal = lookupReplacementGlobal(PtrOperand))
 
  180    SI.setOperand(
SI.getPointerOperandIndex(), NewGlobal);
 
 
  185DataScalarizerVisitor::AllocaAndGEPs
 
  186DataScalarizerVisitor::createArrayFromVector(
IRBuilder<> &Builder, 
Value *Vec,
 
  187                                             const Twine &Name = 
"") {
 
  190    return VectorAllocaMap[Vec];
 
  192  auto InsertPoint = Builder.GetInsertPoint();
 
  195  Builder.SetInsertPointPastAllocas(Builder.GetInsertBlock()->getParent());
 
  198      Builder.CreateAlloca(ArrTy, 
nullptr, Name + 
".alloca");
 
  205    Builder.SetInsertPoint(Instr->getNextNode());
 
  207  for (
unsigned I = 0; 
I < ArrNumElems; ++
I) {
 
  208    Value *EE = Builder.CreateExtractElement(Vec, 
I, Name + 
".extract");
 
  209    GEPs[
I] = Builder.CreateInBoundsGEP(
 
  210        ArrTy, ArrAlloca, {Builder.getInt32(0), Builder.getInt32(
I)},
 
  215  VectorAllocaMap.insert({Vec, {ArrAlloca, GEPs}});
 
  217  return {ArrAlloca, GEPs};
 
  222static std::pair<Value *, Value *>
 
  224                     const Twine &Name = 
"") {
 
  226  Value *
GEP = Builder.CreateInBoundsGEP(
 
  227      ArrTy, ArrAlloca, {Builder.getInt32(0), Index}, Name + 
".index");
 
  230  return std::make_pair(
GEP, Load);
 
 
  233bool DataScalarizerVisitor::replaceDynamicInsertElementInst(
 
  241  AllocaAndGEPs ArrAllocaAndGEPs =
 
  242      createArrayFromVector(Builder, Vec, IEI.
getName());
 
  243  AllocaInst *ArrAlloca = ArrAllocaAndGEPs.first;
 
  275  return replaceDynamicInsertElementInst(IEI);
 
 
  278bool DataScalarizerVisitor::replaceDynamicExtractElementInst(
 
  282  AllocaAndGEPs ArrAllocaAndGEPs =
 
  284  AllocaInst *ArrAlloca = ArrAllocaAndGEPs.first;
 
  288  Value *Load = GEPAndLoad.second;
 
  300  return replaceDynamicExtractElementInst(EEI);
 
 
  307  bool NeedsTransform = 
false;
 
  313      PtrOperand = GEPCE->getPointerOperand();
 
  314      NewGEPType = GEPCE->getSourceElementType();
 
  319  if (
GlobalVariable *NewGlobal = lookupReplacementGlobal(PtrOperand)) {
 
  320    NewGEPType = NewGlobal->getValueType();
 
  321    PtrOperand = NewGlobal;
 
  322    NeedsTransform = 
true;
 
  324    Type *AllocatedType = Alloca->getAllocatedType();
 
  327      NewGEPType = AllocatedType;
 
  328      NeedsTransform = 
true;
 
  341  Value *NewGEP = Builder.CreateGEP(NewGEPType, PtrOperand, Indices,
 
  347    OldGEPI->eraseFromParent();
 
 
  369      for (
unsigned I = 0; 
I < ConstVecInit->getNumOperands(); ++
I)
 
  370        ArrayElements.
push_back(ConstVecInit->getOperand(
I));
 
  373      for (
unsigned I = 0; 
I < ConstDataVecInit->getNumElements(); ++
I)
 
  374        ArrayElements.
push_back(ConstDataVecInit->getElementAsConstant(
I));
 
  376      assert(
false && 
"Expected a ConstantVector or ConstantDataVector for " 
  377                      "vector initializer!");
 
  386    assert(ArrayInit && 
"Expected a ConstantArray for array initializer!");
 
  389    for (
unsigned I = 0; 
I < ArrayTy->getNumElements(); ++
I) {
 
  392          ArrayInit->getOperand(
I), ArrayTy->getElementType(),
 
 
  405  bool MadeChange = 
false;
 
  410    Type *OrigType = 
G.getValueType();
 
  413    if (OrigType != NewType) {
 
  417          M, NewType, 
G.isConstant(), 
G.getLinkage(),
 
  418          nullptr, 
G.getName() + 
".scalarized", &
G,
 
  419          G.getThreadLocalMode(), 
G.getAddressSpace(),
 
  420          G.isExternallyInitialized());
 
  424      if (
G.getAlignment() > 0) {
 
  428      if (
G.hasInitializer()) {
 
  436      Impl.GlobalMap[&
G] = NewGlobal;
 
  441    if (
F.isDeclaration())
 
  443    MadeChange |= Impl.visit(
F);
 
  447  for (
auto &[Old, New] : Impl.GlobalMap) {
 
  448    Old->eraseFromParent();
 
 
  470                      "DXIL Data Scalarization", 
false, 
false)
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
static bool findAndReplaceVectors(Module &M)
 
static bool isVectorOrArrayOfVectors(Type *T)
 
static Type * equivalentArrayTypeFromVector(Type *T)
 
static std::pair< Value *, Value * > dynamicallyLoadArray(IRBuilder<> &Builder, AllocaInst *ArrAlloca, Value *Index, const Twine &Name="")
Returns a pair of Value* with the first being a GEP into ArrAlloca using indices {0,...
 
static const int MaxVecSize
 
static Constant * transformInitializer(Constant *Init, Type *OrigType, Type *NewType, LLVMContext &Ctx)
 
Module.h This file contains the declarations for the Module class.
 
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)
 
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
 
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
 
DXILDataScalarizationLegacy()
 
bool visitCallInst(CallInst &ICI)
 
bool visitInstruction(Instruction &I)
 
bool visitBinaryOperator(BinaryOperator &BO)
 
bool visitInsertElementInst(InsertElementInst &IEI)
 
bool visitGetElementPtrInst(GetElementPtrInst &GEPI)
 
bool visitStoreInst(StoreInst &SI)
 
bool visitFreezeInst(FreezeInst &FI)
 
bool visitBitCastInst(BitCastInst &BCI)
 
bool visitCastInst(CastInst &CI)
 
bool visitFCmpInst(FCmpInst &FCI)
 
bool visitLoadInst(LoadInst &LI)
 
bool visitSelectInst(SelectInst &SI)
 
bool visitUnaryOperator(UnaryOperator &UO)
 
bool visitICmpInst(ICmpInst &ICI)
 
bool visitShuffleVectorInst(ShuffleVectorInst &SVI)
 
bool visitAllocaInst(AllocaInst &AI)
 
bool visitPHINode(PHINode &PHI)
 
bool visitExtractElementInst(ExtractElementInst &EEI)
 
friend bool findAndReplaceVectors(llvm::Module &M)
 
an instruction to allocate memory on the stack
 
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
 
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
 
void setAlignment(Align Align)
 
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
 
LLVM Basic Block Representation.
 
This class represents a no-op cast from one type to another.
 
This class represents a function call, abstracting a target machine's calling convention.
 
This is the base class for all instructions that perform data casts.
 
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
 
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
 
A vector constant whose element type is a simple 1/2/4/8-byte integer or float/double,...
 
A constant value that is initialized with an expression using other constant values.
 
Constant Vector Declarations.
 
This is an important base class in LLVM.
 
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
 
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
 
This instruction compares its operands according to the predicate given to the constructor.
 
This class represents a freeze function that returns random concrete value if an operand is either a ...
 
LLVM_ABI Type * getSourceElementType() const
 
LLVM_ABI Type * getResultElementType() const
 
Value * getPointerOperand()
 
GEPNoWrapFlags getNoWrapFlags() const
 
iterator_range< op_iterator > indices()
 
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
 
void setUnnamedAddr(UnnamedAddr Val)
 
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
 
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
 
This instruction compares its operands according to the predicate given to the constructor.
 
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
 
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
 
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
 
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
 
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
 
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
 
This instruction inserts a single (scalar) element into a VectorType value.
 
Base class for instruction visitors.
 
void visit(Iterator Start, Iterator End)
 
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
 
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
 
This is an important class for using LLVM in a threaded context.
 
An instruction for reading from memory.
 
void setAlignment(Align Align)
 
Value * getPointerOperand()
 
static unsigned getPointerOperandIndex()
 
Align getAlign() const
Return the alignment of the access that is being performed.
 
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.
 
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
 
A set of analyses that are preserved following a run of a transformation pass.
 
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
 
This class represents the LLVM 'select' instruction.
 
This instruction constructs a fixed permutation of two input vectors.
 
void push_back(const T &Elt)
 
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
 
An instruction for storing to memory.
 
void setAlignment(Align Align)
 
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.
 
Type * getArrayElementType() const
 
LLVM_ABI uint64_t getArrayNumElements() const
 
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
 
void setOperand(unsigned i, Value *Val)
 
Value * getOperand(unsigned i) const
 
LLVM Value Representation.
 
Type * getType() const
All values are typed, get the type of this value.
 
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
 
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
 
self_iterator getIterator()
 
This is an optimization pass for GlobalISel generic memory operations.
 
FunctionAddr VTableAddr Value
 
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
 
ModulePass * createDXILDataScalarizationLegacyPass()
Pass to scalarize llvm global data into a DXIL legal form.
 
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...
 
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
 
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
 
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
 
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.