25#define DEBUG_TYPE "spirv-legalize-zero-size-arrays"
31bool hasZeroSizeArray(
const Type *Ty) {
33 if (ArrTy->getNumElements() == 0)
35 return hasZeroSizeArray(ArrTy->getElementType());
39 for (
Type *ElemTy : StructTy->elements()) {
40 if (hasZeroSizeArray(ElemTy))
48bool shouldLegalizeInstType(
const Type *Ty) {
52 return ArrTy->getNumElements() == 0 ||
53 shouldLegalizeInstType(ArrTy->getElementType());
58class SPIRVLegalizeZeroSizeArraysImpl
59 :
public InstVisitor<SPIRVLegalizeZeroSizeArraysImpl> {
60 friend class InstVisitor<SPIRVLegalizeZeroSizeArraysImpl>;
65 bool runOnModule(
Module &M);
86class SPIRVLegalizeZeroSizeArraysLegacy :
public ModulePass {
92 return "SPIRV Legalize Zero-Size Arrays";
94 bool runOnModule(
Module &M)
override {
95 SPIRVLegalizeZeroSizeArraysImpl Impl(TM);
96 return Impl.runOnModule(M);
111Type *SPIRVLegalizeZeroSizeArraysImpl::legalizeType(
Type *Ty) {
112 auto It = TypeMap.find(Ty);
113 if (It != TypeMap.end())
116 Type *LegalizedTy = Ty;
126 for (
Type *ElemTy : StructTy->elements()) {
127 Type *LegalizedElemTy = legalizeType(ElemTy);
129 Changed |= LegalizedElemTy != ElemTy;
135 (StructTy->getName() +
".legalized").str(),
136 StructTy->isPacked())
138 StructTy->isPacked());
142 TypeMap[Ty] = LegalizedTy;
147 if (!
C || !hasZeroSizeArray(
C->getType()))
156 Type *NewTy = legalizeType(
C->getType());
163 for (
Use &U : CA->operands())
170 for (
Use &U : CS->operands())
178 if (CE->getOpcode() == Instruction::GetElementPtr)
182 for (
Use &U : CE->operands()) {
184 Ops.push_back(LegalizedOp);
188 return CE->getWithOperands(
Ops);
194void SPIRVLegalizeZeroSizeArraysImpl::visitAllocaInst(
AllocaInst &AI) {
203 AllocaInst *NewAI = Builder.CreateAlloca(Builder.getInt8Ty());
212void SPIRVLegalizeZeroSizeArraysImpl::visitLoadInst(
LoadInst &LI) {
213 if (!hasZeroSizeArray(LI.
getType()))
218 if (shouldLegalizeInstType(ArrTy)) {
225void SPIRVLegalizeZeroSizeArraysImpl::visitStoreInst(
StoreInst &
SI) {
226 Type *StoreTy =
SI.getValueOperand()->getType();
230 if (shouldLegalizeInstType(ArrTy)) {
236void SPIRVLegalizeZeroSizeArraysImpl::visitSelectInst(
SelectInst &Sel) {
237 if (!hasZeroSizeArray(Sel.
getType()))
242 if (shouldLegalizeInstType(ArrTy)) {
249void SPIRVLegalizeZeroSizeArraysImpl::visitExtractValueInst(
256 if (shouldLegalizeInstType(ArrTy)) {
263void SPIRVLegalizeZeroSizeArraysImpl::visitInsertValueInst(
271 if (shouldLegalizeInstType(ArrTy)) {
278bool SPIRVLegalizeZeroSizeArraysImpl::runOnModule(
Module &M) {
295 if (!hasZeroSizeArray(GV.getValueType()))
298 Type *NewTy = legalizeType(GV.getValueType());
300 GV.hasInitializer() && !GV.hasAppendingLinkage()
301 ? legalizeConstant(GV.getInitializer())
309 GV.hasAppendingLinkage()
316 M, NewTy, GV.isConstant(), NewLT, LegalizedInitializer,
317 "", &GV, GV.getThreadLocalMode(), GV.getAddressSpace(),
318 GV.isExternallyInitialized());
323 GlobalMap[&GV] = NewGV;
333 GV->eraseFromParent();
341 I->eraseFromParent();
350 SPIRVLegalizeZeroSizeArraysImpl Impl(TM);
351 if (Impl.runOnModule(M))
356char SPIRVLegalizeZeroSizeArraysLegacy::ID = 0;
359 "spirv-legalize-zero-size-arrays",
360 "Legalize SPIR-V zero-size arrays",
false,
false)
364 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.