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) {
201 if (shouldLegalizeInstType(ArrTy)) {
217void SPIRVLegalizeZeroSizeArraysImpl::visitLoadInst(
LoadInst &LI) {
218 if (!hasZeroSizeArray(LI.
getType()))
223 if (shouldLegalizeInstType(ArrTy)) {
230void SPIRVLegalizeZeroSizeArraysImpl::visitStoreInst(
StoreInst &
SI) {
231 Type *StoreTy =
SI.getValueOperand()->getType();
235 if (shouldLegalizeInstType(ArrTy)) {
241void SPIRVLegalizeZeroSizeArraysImpl::visitSelectInst(
SelectInst &Sel) {
242 if (!hasZeroSizeArray(Sel.
getType()))
247 if (shouldLegalizeInstType(ArrTy)) {
254void SPIRVLegalizeZeroSizeArraysImpl::visitExtractValueInst(
261 if (shouldLegalizeInstType(ArrTy)) {
268void SPIRVLegalizeZeroSizeArraysImpl::visitInsertValueInst(
276 if (shouldLegalizeInstType(ArrTy)) {
283bool SPIRVLegalizeZeroSizeArraysImpl::runOnModule(
Module &M) {
297 if (!hasZeroSizeArray(GV.getValueType()))
301 if (GV.getName() ==
"llvm.embedded.module")
304 Type *NewTy = legalizeType(GV.getValueType());
305 Constant *LegalizedInitializer = legalizeConstant(GV.getInitializer());
310 M, NewTy, GV.isConstant(), GV.getLinkage(), LegalizedInitializer,
311 "", &GV, GV.getThreadLocalMode(), GV.getAddressSpace(),
312 GV.isExternallyInitialized());
317 GlobalMap[&GV] = NewGV;
327 GV->eraseFromParent();
335 I->eraseFromParent();
344 SPIRVLegalizeZeroSizeArraysImpl Impl(TM);
345 if (Impl.runOnModule(M))
350char SPIRVLegalizeZeroSizeArraysLegacy::ID = 0;
353 "spirv-legalize-zero-size-arrays",
354 "Legalize SPIR-V zero-size arrays",
false,
false)
358 return new SPIRVLegalizeZeroSizeArraysLegacy(TM);
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.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
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.
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.
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.
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 StringRef getName() const
Return a constant reference to the value's name.
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.