diff options
| author | jeanPerier <jperier@nvidia.com> | 2025-05-20 10:45:29 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-20 10:45:29 +0200 |
| commit | 80816e792382da286b29f937938ab54ae159f482 (patch) | |
| tree | 53f405ef638b704fe72a3b16e89d9e23f9f0deea /mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | |
| parent | 034eaeddc30cbaf273744580f15325514d5fb928 (diff) | |
[mlir][LLVM] handle ArrayAttr for constant array of structs (#139724)
While LLVM IR dialect has a way to represent arbitrary LLVM constant
array of structs via an insert chain, it is in practice very expensive
for the compilation time as soon as the array is bigger than a couple
hundred elements. This is because generating and later folding such
insert chain is really not cheap.
This patch allows representing array of struct constants via ArrayAttr in
the LLVM dialect.
Diffstat (limited to 'mlir/lib/Target/LLVMIR/ModuleTranslation.cpp')
| -rw-r--r-- | mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 95b8ee0331c5..9b5c93171abf 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -553,8 +553,10 @@ static llvm::Constant *convertDenseResourceElementsAttr( llvm::Constant *mlir::LLVM::detail::getLLVMConstant( llvm::Type *llvmType, Attribute attr, Location loc, const ModuleTranslation &moduleTranslation) { - if (!attr) + if (!attr || isa<UndefAttr>(attr)) return llvm::UndefValue::get(llvmType); + if (isa<ZeroAttr>(attr)) + return llvm::Constant::getNullValue(llvmType); if (auto *structType = dyn_cast<::llvm::StructType>(llvmType)) { auto arrayAttr = dyn_cast<ArrayAttr>(attr); if (!arrayAttr) { @@ -713,6 +715,33 @@ llvm::Constant *mlir::LLVM::detail::getLLVMConstant( ArrayRef<char>{stringAttr.getValue().data(), stringAttr.getValue().size()}); } + + // Handle arrays of structs that cannot be represented as DenseElementsAttr + // in MLIR. + if (auto arrayAttr = dyn_cast<ArrayAttr>(attr)) { + if (auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) { + llvm::Type *elementType = arrayTy->getElementType(); + Attribute previousElementAttr; + llvm::Constant *elementCst = nullptr; + SmallVector<llvm::Constant *> constants; + constants.reserve(arrayTy->getNumElements()); + for (Attribute elementAttr : arrayAttr) { + // Arrays with a single value or with repeating values are quite common. + // Short-circuit the translation when the element value is the same as + // the previous one. + if (!previousElementAttr || previousElementAttr != elementAttr) { + previousElementAttr = elementAttr; + elementCst = + getLLVMConstant(elementType, elementAttr, loc, moduleTranslation); + if (!elementCst) + return nullptr; + } + constants.push_back(elementCst); + } + return llvm::ConstantArray::get(arrayTy, constants); + } + } + emitError(loc, "unsupported constant value"); return nullptr; } |
