diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -415,11 +415,13 @@ } /// A helper method to decide if a constant must not be set as a global variable -/// initializer. +/// initializer. For an external linkage variable, the variable with an +/// initializer is considered externally visible and defined in this module, the +/// variable without an initializer is externally available and is defined +/// elsewhere. static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage, llvm::Constant *cst) { - return (linkage == llvm::GlobalVariable::ExternalLinkage && - isa(cst)) || + return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) || linkage == llvm::GlobalVariable::ExternalWeakLinkage; } @@ -436,7 +438,7 @@ LogicalResult ModuleTranslation::convertGlobals() { for (auto op : getModuleBody(mlirModule).getOps()) { llvm::Type *type = convertType(op.getType()); - llvm::Constant *cst = llvm::UndefValue::get(type); + llvm::Constant *cst = nullptr; if (op.getValueOrNull()) { // String attributes are treated separately because they cannot appear as // in-function constants and are thus not supported by getLLVMConstant. @@ -452,10 +454,18 @@ auto linkage = convertLinkageToLLVM(op.linkage()); auto addrSpace = op.addr_space(); + + // LLVM IR requires constant with linkage other than external or weak + // external to have initializers. If MLIR does not provide an initializer, + // default to undef. + bool dropInitializer = shouldDropGlobalInitializer(linkage, cst); + if (!dropInitializer && !cst) + cst = llvm::UndefValue::get(type); + else if (dropInitializer && cst) + cst = nullptr; + auto *var = new llvm::GlobalVariable( - *llvmModule, type, op.constant(), linkage, - shouldDropGlobalInitializer(linkage, cst) ? nullptr : cst, - op.sym_name(), + *llvmModule, type, op.constant(), linkage, cst, op.sym_name(), /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, addrSpace); if (op.unnamed_addr().hasValue()) diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -36,6 +36,12 @@ // CHECK: @int_global_undef = internal global i64 undef llvm.mlir.global internal @int_global_undef() : i64 +// CHECK: @explicit_undef = global i32 undef +llvm.mlir.global external @explicit_undef() : i32 { + %0 = llvm.mlir.undef : i32 + llvm.return %0 : i32 +} + // CHECK: @int_gep = internal constant i32* getelementptr (i32, i32* @i32_global, i32 2) llvm.mlir.global internal constant @int_gep() : !llvm.ptr { %addr = llvm.mlir.addressof @i32_global : !llvm.ptr