26#define DEBUG_TYPE "spirv-legalize-zero-size-arrays"
32bool hasZeroSizeArray(
const Type *Ty) {
34 if (ArrTy->getNumElements() == 0)
36 return hasZeroSizeArray(ArrTy->getElementType());
40 for (
Type *ElemTy : StructTy->elements()) {
41 if (hasZeroSizeArray(ElemTy))
49bool shouldLegalizeInstType(
const Type *Ty) {
53 return ArrTy->getNumElements() == 0 ||
54 shouldLegalizeInstType(ArrTy->getElementType());
59class SPIRVLegalizeZeroSizeArraysImpl
60 :
public InstVisitor<SPIRVLegalizeZeroSizeArraysImpl> {
61 friend class InstVisitor<SPIRVLegalizeZeroSizeArraysImpl>;
66 bool runOnModule(
Module &M);
87class SPIRVLegalizeZeroSizeArraysLegacy :
public ModulePass {
93 return "SPIRV Legalize Zero-Size Arrays";
95 bool runOnModule(
Module &M)
override {
96 SPIRVLegalizeZeroSizeArraysImpl Impl(TM);
97 return Impl.runOnModule(M);
112Type *SPIRVLegalizeZeroSizeArraysImpl::legalizeType(
Type *Ty) {
113 auto It = TypeMap.find(Ty);
114 if (It != TypeMap.end())
117 Type *LegalizedTy = Ty;
127 for (
Type *ElemTy : StructTy->elements()) {
128 Type *LegalizedElemTy = legalizeType(ElemTy);
130 Changed |= LegalizedElemTy != ElemTy;
136 (StructTy->getName() +
".legalized").str(),
137 StructTy->isPacked())
139 StructTy->isPacked());
143 TypeMap[Ty] = LegalizedTy;
148 if (!
C || !hasZeroSizeArray(
C->getType()))
157 Type *NewTy = legalizeType(
C->getType());
164 for (
Use &U : CA->operands())
171 for (
Use &U : CS->operands())
179 if (CE->getOpcode() == Instruction::GetElementPtr)
183 for (
Use &U : CE->operands()) {
185 Ops.push_back(LegalizedOp);
189 return CE->getWithOperands(
Ops);
195void SPIRVLegalizeZeroSizeArraysImpl::visitAllocaInst(
AllocaInst &AI) {
204 AllocaInst *NewAI = Builder.CreateAlloca(Builder.getInt8Ty());
213void SPIRVLegalizeZeroSizeArraysImpl::visitLoadInst(
LoadInst &LI) {
214 if (!hasZeroSizeArray(LI.
getType()))
219 if (shouldLegalizeInstType(ArrTy)) {
226void SPIRVLegalizeZeroSizeArraysImpl::visitStoreInst(
StoreInst &
SI) {
227 Type *StoreTy =
SI.getValueOperand()->getType();
231 if (shouldLegalizeInstType(ArrTy)) {
237void SPIRVLegalizeZeroSizeArraysImpl::visitSelectInst(
SelectInst &Sel) {
238 if (!hasZeroSizeArray(Sel.
getType()))
243 if (shouldLegalizeInstType(ArrTy)) {
250void SPIRVLegalizeZeroSizeArraysImpl::visitExtractValueInst(
257 if (shouldLegalizeInstType(ArrTy)) {
264void SPIRVLegalizeZeroSizeArraysImpl::visitInsertValueInst(
272 if (shouldLegalizeInstType(ArrTy)) {
279bool SPIRVLegalizeZeroSizeArraysImpl::runOnModule(
Module &M) {
296 if (!hasZeroSizeArray(GV.getValueType()))
299 Type *NewTy = legalizeType(GV.getValueType());
300 Constant *LegalizedInitializer = legalizeConstant(GV.getInitializer());
305 M, NewTy, GV.isConstant(), GV.getLinkage(), LegalizedInitializer,
306 "", &GV, GV.getThreadLocalMode(), GV.getAddressSpace(),
307 GV.isExternallyInitialized());
312 GlobalMap[&GV] = NewGV;
322 GV->eraseFromParent();
330 I->eraseFromParent();
339 SPIRVLegalizeZeroSizeArraysImpl Impl(TM);
340 if (Impl.runOnModule(M))
345char SPIRVLegalizeZeroSizeArraysLegacy::ID = 0;
348 "spirv-legalize-zero-size-arrays",
349 "Legalize SPIR-V zero-size arrays",
false,
false)
353 return new SPIRVLegalizeZeroSizeArraysLegacy(TM);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file defines the DenseMap class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> 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.
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(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
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 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.
StringRef - 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
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.