[llvm] [SPIRV] Add legalization pass for zero-size arrays (PR #172367)

Steven Perron via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 16 10:36:44 PST 2025


================
@@ -0,0 +1,334 @@
+//===- SPIRVLegalizeZeroSizeArrays.cpp - Legalize zero-size arrays -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// SPIR-V does not support zero-size arrays unless it is within a shader. This
+// pass legalizes zero-size arrays ([0 x T]) in unsupported cases.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVLegalizeZeroSizeArrays.h"
+#include "SPIRV.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/TargetParser/Triple.h"
+
+#define DEBUG_TYPE "spirv-legalize-zero-size-arrays"
+
+using namespace llvm;
+
+namespace {
+
+bool hasZeroSizeArray(const Type *Ty) {
+  if (const ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
+    if (ArrTy->getNumElements() == 0)
+      return true;
+    return hasZeroSizeArray(ArrTy->getElementType());
+  }
+
+  if (const StructType *StructTy = dyn_cast<StructType>(Ty)) {
+    for (Type *ElemTy : StructTy->elements()) {
+      if (hasZeroSizeArray(ElemTy))
+        return true;
+    }
+  }
+
+  return false;
+}
+
+class SPIRVLegalizeZeroSizeArraysImpl
+    : public InstVisitor<SPIRVLegalizeZeroSizeArraysImpl> {
+  friend class InstVisitor<SPIRVLegalizeZeroSizeArraysImpl>;
+
+public:
+  bool runOnModule(Module &M);
+
+  // TODO: Handle GEP, PHI
+  void visitAllocaInst(AllocaInst &AI);
+  void visitLoadInst(LoadInst &LI);
+  void visitStoreInst(StoreInst &SI);
+  void visitSelectInst(SelectInst &Sel);
+  void visitExtractValueInst(ExtractValueInst &EVI);
+  void visitInsertValueInst(InsertValueInst &IVI);
+
+private:
+  Type *legalizeType(Type *Ty);
+  Constant *legalizeConstant(Constant *C);
+
+  DenseMap<Type *, Type *> TypeMap;
+  DenseMap<GlobalVariable *, GlobalVariable *> GlobalMap;
+  SmallVector<Instruction *, 16> ToErase;
+  bool Modified = false;
+};
+
+class SPIRVLegalizeZeroSizeArraysLegacy : public ModulePass {
+public:
+  static char ID;
+  SPIRVLegalizeZeroSizeArraysLegacy() : ModulePass(ID) {}
+  StringRef getPassName() const override {
+    return "SPIRV Legalize Zero-Size Arrays";
+  }
+  bool runOnModule(Module &M) override {
+    SPIRVLegalizeZeroSizeArraysImpl Impl;
+    return Impl.runOnModule(M);
+  }
+};
+
+Type *SPIRVLegalizeZeroSizeArraysImpl::legalizeType(Type *Ty) {
+  auto It = TypeMap.find(Ty);
+  if (It != TypeMap.end())
+    return It->second;
+
+  Type *LegalizedTy = Ty;
+
+  if (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
+    if (ArrTy->getNumElements() == 0) {
+      LegalizedTy = PointerType::getUnqual(Ty->getContext());
----------------
s-perron wrote:

This is not a obvious change. Add a comment to explain what is going on.

https://github.com/llvm/llvm-project/pull/172367


More information about the llvm-commits mailing list