24#define DEBUG_TYPE "spirv-legalize-zero-size-arrays"
30bool hasZeroSizeArray(
const Type *Ty) {
32 if (ArrTy->getNumElements() == 0)
34 return hasZeroSizeArray(ArrTy->getElementType());
38 for (
Type *ElemTy : StructTy->elements()) {
39 if (hasZeroSizeArray(ElemTy))
47bool shouldLegalizeInstType(
const Type *Ty) {
51 return ArrTy->getNumElements() == 0 ||
52 shouldLegalizeInstType(ArrTy->getElementType());
57class SPIRVLegalizeZeroSizeArraysImpl
58 :
public InstVisitor<SPIRVLegalizeZeroSizeArraysImpl> {
59 friend class InstVisitor<SPIRVLegalizeZeroSizeArraysImpl>;
64 bool runOnModule(
Module &M);
85class SPIRVLegalizeZeroSizeArraysLegacy :
public ModulePass {
91 return "SPIRV Legalize Zero-Size Arrays";
93 bool runOnModule(
Module &M)
override {
94 SPIRVLegalizeZeroSizeArraysImpl Impl(TM);
95 return Impl.runOnModule(M);
110Type *SPIRVLegalizeZeroSizeArraysImpl::legalizeType(
Type *Ty) {
111 auto It = TypeMap.find(Ty);
112 if (It != TypeMap.end())
115 Type *LegalizedTy = Ty;
125 for (
Type *ElemTy : StructTy->elements()) {
126 Type *LegalizedElemTy = legalizeType(ElemTy);
128 Changed |= LegalizedElemTy != ElemTy;
134 (StructTy->getName() +
".legalized").str(),
135 StructTy->isPacked())
137 StructTy->isPacked());
141 TypeMap[Ty] = LegalizedTy;
146 if (!
C || !hasZeroSizeArray(
C->getType()))
155 Type *NewTy = legalizeType(
C->getType());
162 for (
Use &U : CA->operands())
169 for (
Use &U : CS->operands())
177 if (CE->getOpcode() == Instruction::GetElementPtr)
181 for (
Use &U : CE->operands()) {
183 Ops.push_back(LegalizedOp);
187 return CE->getWithOperands(
Ops);
193void SPIRVLegalizeZeroSizeArraysImpl::visitAllocaInst(
AllocaInst &AI) {
202 AllocaInst *NewAI = Builder.CreateAlloca(Builder.getInt8Ty());
211void SPIRVLegalizeZeroSizeArraysImpl::visitLoadInst(
LoadInst &LI) {
212 if (!hasZeroSizeArray(LI.
getType()))
217 if (shouldLegalizeInstType(ArrTy)) {
224void SPIRVLegalizeZeroSizeArraysImpl::visitStoreInst(
StoreInst &
SI) {
225 Type *StoreTy =
SI.getValueOperand()->getType();
229 if (shouldLegalizeInstType(ArrTy)) {
235void SPIRVLegalizeZeroSizeArraysImpl::visitSelectInst(
SelectInst &Sel) {
236 if (!hasZeroSizeArray(Sel.
getType()))
241 if (shouldLegalizeInstType(ArrTy)) {
248void SPIRVLegalizeZeroSizeArraysImpl::visitExtractValueInst(
255 if (shouldLegalizeInstType(ArrTy)) {
262void SPIRVLegalizeZeroSizeArraysImpl::visitInsertValueInst(
270 if (shouldLegalizeInstType(ArrTy)) {
277bool SPIRVLegalizeZeroSizeArraysImpl::runOnModule(
Module &M) {
294 if (!hasZeroSizeArray(GV.getValueType()))
297 Type *NewTy = legalizeType(GV.getValueType());
299 GV.hasInitializer() && !GV.hasAppendingLinkage()
300 ? legalizeConstant(GV.getInitializer())
308 GV.hasAppendingLinkage()
315 M, NewTy, GV.isConstant(), NewLT, LegalizedInitializer,
316 "", &GV, GV.getThreadLocalMode(), GV.getAddressSpace(),
317 GV.isExternallyInitialized());
322 GlobalMap[&GV] = NewGV;
332 GV->eraseFromParent();
340 I->eraseFromParent();
349 SPIRVLegalizeZeroSizeArraysImpl Impl(TM);
350 if (Impl.runOnModule(M))
355char SPIRVLegalizeZeroSizeArraysLegacy::ID = 0;
358 "spirv-legalize-zero-size-arrays",
359 "Legalize SPIR-V zero-size arrays",
false,
false)
363 return new SPIRVLegalizeZeroSizeArraysLegacy(TM);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file defines the DenseMap class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
This file defines the SmallVector class.
an instruction to allocate memory on the stack
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
void setAlignment(Align Align)
ConstantArray - Constant Array Declarations.
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
A constant value that is initialized with an expression using other constant values.
static LLVM_ABI Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI void copyMetadata(const GlobalObject *Src, unsigned Offset)
Copy metadata from Src, adjusting offsets by Offset.
LLVM_ABI void setComdat(Comdat *C)
PointerType * getType() const
Global values are always pointers.
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ ExternalWeakLinkage
ExternalWeak linkage description.
LLVM_ABI void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This instruction inserts a struct field of array element value into an aggregate value.
Value * getInsertedValueOperand()
Value * getAggregateOperand()
Base class for instruction visitors.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
An instruction for reading from memory.
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.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
const SPIRVSubtarget * getSubtargetImpl() const
This class represents the LLVM 'select' instruction.
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.
Represent a constant reference to a string, i.e.
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
The instances of the Type class are immutable: once they are created, they are never changed.
A Use represents the edge between a Value definition and its users.
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 void takeName(Value *V)
Transfer the name from V to this value.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
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...
ModulePass * createSPIRVLegalizeZeroSizeArraysPass(const SPIRVTargetMachine &TM)
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.