summaryrefslogtreecommitdiff
path: root/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
diff options
context:
space:
mode:
authorjeanPerier <jperier@nvidia.com>2025-05-20 10:45:29 +0200
committerGitHub <noreply@github.com>2025-05-20 10:45:29 +0200
commit80816e792382da286b29f937938ab54ae159f482 (patch)
tree53f405ef638b704fe72a3b16e89d9e23f9f0deea /mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
parent034eaeddc30cbaf273744580f15325514d5fb928 (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.cpp31
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;
}