diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index 9ea70d5057c9..d46e997c7d8f 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -2800,7 +2800,8 @@ def fir_GlobalOp : fir_Op<"global", [IsolatedFromAbove, Symbol]> { OptionalAttr:$constant, OptionalAttr:$target, OptionalAttr:$linkName, - OptionalAttr:$data_attr + OptionalAttr:$data_attr, + OptionalAttr:$alignment ); let regions = (region AtMostRegion<1>:$region); diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index c15d6b682bdb..80a80fd1d92e 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -1295,6 +1295,9 @@ declareCommonBlock(Fortran::lower::AbstractConverter &converter, getCommonMembersWithInitAliases(common); mlir::Location loc = converter.genLocation(common.name()); mlir::StringAttr linkage = builder.createCommonLinkage(); + const auto *details = + common.detailsIf(); + assert(details && "Expect CommonBlockDetails on the common symbol"); if (!commonBlockHasInit(cmnBlkMems)) { // A COMMON block sans initializers is initialized to zero. // mlir::Vector types must have a strictly positive size, so at least @@ -1307,7 +1310,8 @@ declareCommonBlock(Fortran::lower::AbstractConverter &converter, auto vecTy = mlir::VectorType::get(sz, i8Ty); mlir::Attribute zero = builder.getIntegerAttr(i8Ty, 0); auto init = mlir::DenseElementsAttr::get(vecTy, llvm::ArrayRef(zero)); - builder.createGlobal(loc, commonTy, commonName, linkage, init); + global = builder.createGlobal(loc, commonTy, commonName, linkage, init); + global.setAlignment(details->alignment()); // No need to add any initial value later. return std::nullopt; } @@ -1320,6 +1324,7 @@ declareCommonBlock(Fortran::lower::AbstractConverter &converter, getTypeOfCommonWithInit(converter, cmnBlkMems, commonSize); // Create the global object, the initial value will be added later. global = builder.createGlobal(loc, commonTy, commonName); + global.setAlignment(details->alignment()); return std::make_tuple(global, std::move(cmnBlkMems), loc); } diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 5d3adc3dfbf4..9f21c6b0cf09 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -2742,6 +2742,9 @@ struct GlobalOpConversion : public fir::FIROpConversion { loc, tyAttr, isConst, linkage, global.getSymName(), initAttr, 0, 0, false, false, comdat, attrs, dbgExpr); + if (global.getAlignment() && *global.getAlignment() > 0) + g.setAlignment(*global.getAlignment()); + auto module = global->getParentOfType(); // Add comdat if necessary if (fir::getTargetTriple(module).supportsCOMDAT() && diff --git a/flang/test/Lower/OpenMP/declare-target-data.f90 b/flang/test/Lower/OpenMP/declare-target-data.f90 index 4568810d8d07..d86f74d18b6d 100644 --- a/flang/test/Lower/OpenMP/declare-target-data.f90 +++ b/flang/test/Lower/OpenMP/declare-target-data.f90 @@ -62,25 +62,25 @@ contains end module test_0 PROGRAM commons - !CHECK-DAG: fir.global @numbers_ {omp.declare_target = #omp.declaretarget} : tuple { + !CHECK-DAG: fir.global @numbers_ {alignment = 4 : i64, omp.declare_target = #omp.declaretarget} : tuple { REAL :: one = 1 REAL :: two = 2 COMMON /numbers/ one, two !$omp declare target(/numbers/) - !CHECK-DAG: fir.global @numbers_link_ {omp.declare_target = #omp.declaretarget} : tuple { + !CHECK-DAG: fir.global @numbers_link_ {alignment = 4 : i64, omp.declare_target = #omp.declaretarget} : tuple { REAL :: one_link = 1 REAL :: two_link = 2 COMMON /numbers_link/ one_link, two_link !$omp declare target link(/numbers_link/) - !CHECK-DAG: fir.global @numbers_to_ {omp.declare_target = #omp.declaretarget} : tuple { + !CHECK-DAG: fir.global @numbers_to_ {alignment = 4 : i64, omp.declare_target = #omp.declaretarget} : tuple { REAL :: one_to = 1 REAL :: two_to = 2 COMMON /numbers_to/ one_to, two_to !$omp declare target to(/numbers_to/) - !CHECK-DAG: fir.global @numbers_enter_ {omp.declare_target = #omp.declaretarget} : tuple { + !CHECK-DAG: fir.global @numbers_enter_ {alignment = 4 : i64, omp.declare_target = #omp.declaretarget} : tuple { REAL :: one_enter = 1 REAL :: two_enter = 2 COMMON /numbers_enter/ one_enter, two_enter diff --git a/flang/test/Lower/OpenMP/lastprivate-commonblock.f90 b/flang/test/Lower/OpenMP/lastprivate-commonblock.f90 index 78adf09c6fe3..f823bf6c56ae 100644 --- a/flang/test/Lower/OpenMP/lastprivate-commonblock.f90 +++ b/flang/test/Lower/OpenMP/lastprivate-commonblock.f90 @@ -1,6 +1,6 @@ ! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -!CHECK: fir.global common @[[CB_C:.*]](dense<0> : vector<8xi8>) : !fir.array<8xi8> +!CHECK: fir.global common @[[CB_C:.*]](dense<0> : vector<8xi8>) {alignment = 4 : i64} : !fir.array<8xi8> !CHECK-LABEL: func.func @_QPlastprivate_common !CHECK: %[[CB_C_REF:.*]] = fir.address_of(@[[CB_C]]) : !fir.ref> !CHECK: %[[CB_C_REF_CVT:.*]] = fir.convert %[[CB_C_REF]] : (!fir.ref>) -> !fir.ref> diff --git a/flang/test/Lower/OpenMP/threadprivate-commonblock-use.f90 b/flang/test/Lower/OpenMP/threadprivate-commonblock-use.f90 index 71f1c7608a2c..f02a7486caf5 100644 --- a/flang/test/Lower/OpenMP/threadprivate-commonblock-use.f90 +++ b/flang/test/Lower/OpenMP/threadprivate-commonblock-use.f90 @@ -4,7 +4,7 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: fir.global common @cmn_(dense<0> : vector<4xi8>) : !fir.array<4xi8> +!CHECK: fir.global common @cmn_(dense<0> : vector<4xi8>) {alignment = 4 : i64} : !fir.array<4xi8> module m0 common /cmn/ k1 !$omp threadprivate(/cmn/) diff --git a/flang/test/Lower/OpenMP/threadprivate-commonblock.f90 b/flang/test/Lower/OpenMP/threadprivate-commonblock.f90 index ddbe5bd52465..eb6abe4d2cac 100644 --- a/flang/test/Lower/OpenMP/threadprivate-commonblock.f90 +++ b/flang/test/Lower/OpenMP/threadprivate-commonblock.f90 @@ -12,7 +12,7 @@ module test !$omp threadprivate(/blk/) -!CHECK: fir.global common @blk_(dense<0> : vector<103xi8>) : !fir.array<103xi8> +!CHECK: fir.global common @blk_(dense<0> : vector<103xi8>) {alignment = 8 : i64} : !fir.array<103xi8> contains subroutine sub() diff --git a/flang/test/Lower/OpenMP/threadprivate-use-association.f90 b/flang/test/Lower/OpenMP/threadprivate-use-association.f90 index d0d461547db2..9dcb2ab3ff9f 100644 --- a/flang/test/Lower/OpenMP/threadprivate-use-association.f90 +++ b/flang/test/Lower/OpenMP/threadprivate-use-association.f90 @@ -3,7 +3,7 @@ !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK-DAG: fir.global common @blk_(dense<0> : vector<24xi8>) : !fir.array<24xi8> +!CHECK-DAG: fir.global common @blk_(dense<0> : vector<24xi8>) {alignment = 4 : i64} : !fir.array<24xi8> !CHECK-DAG: fir.global @_QMtestEy : f32 { module test diff --git a/flang/test/Lower/common-block-2.f90 b/flang/test/Lower/common-block-2.f90 index 4b12860a48ff..635a1597b103 100644 --- a/flang/test/Lower/common-block-2.f90 +++ b/flang/test/Lower/common-block-2.f90 @@ -5,12 +5,12 @@ ! - A blank common that is initialized ! - A common block that is initialized outside of a BLOCK DATA. -! CHECK-LABEL: fir.global @__BLNK__ : tuple> { +! CHECK-LABEL: fir.global @__BLNK__ {alignment = 4 : i64} : tuple> { ! CHECK: %[[undef:.*]] = fir.zero_bits tuple> ! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple>, i32) -> tuple> ! CHECK: fir.has_value %[[init]] : tuple> -! CHECK-LABEL: fir.global @a_ : tuple> { +! CHECK-LABEL: fir.global @a_ {alignment = 4 : i64} : tuple> { ! CHECK: %[[undef:.*]] = fir.zero_bits tuple> ! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple>, i32) -> tuple> ! CHECK: fir.has_value %[[init]] : tuple> diff --git a/flang/test/Lower/common-block.f90 b/flang/test/Lower/common-block.f90 index 3934b71b7569..94e61b8bcc33 100644 --- a/flang/test/Lower/common-block.f90 +++ b/flang/test/Lower/common-block.f90 @@ -2,6 +2,7 @@ ! RUN: %flang -emit-llvm -S -mmlir -disable-external-name-interop %s -o - | FileCheck %s ! CHECK: @__BLNK__ = common global [8 x i8] zeroinitializer +! CHECK: @co1_ = common global [16 x i8] zeroinitializer, align 16 ! CHECK: @rien_ = common global [1 x i8] zeroinitializer ! CHECK: @with_empty_equiv_ = common global [8 x i8] zeroinitializer ! CHECK: @x_ = global { float, float } { float 1.0{{.*}}, float 2.0{{.*}} } @@ -72,3 +73,9 @@ subroutine s6 common /with_empty_equiv/ x, r1, y equivalence(r1, r2) end subroutine s6 + +subroutine s7() + real(16) r16 + common /co1/ r16 +end subroutine + diff --git a/flang/test/Lower/module_definition.f90 b/flang/test/Lower/module_definition.f90 index fd3b89db7d20..0a05364ca473 100644 --- a/flang/test/Lower/module_definition.f90 +++ b/flang/test/Lower/module_definition.f90 @@ -12,15 +12,15 @@ module modCommonNoInit1 real :: x_named1 common /named1/ x_named1 end module -! CHECK-LABEL: fir.global common @__BLNK__(dense<0> : vector<4xi8>) : !fir.array<4xi8> -! CHECK-LABEL: fir.global common @named1_(dense<0> : vector<4xi8>) : !fir.array<4xi8> +! CHECK-LABEL: fir.global common @__BLNK__(dense<0> : vector<4xi8>) {alignment = 4 : i64} : !fir.array<4xi8> +! CHECK-LABEL: fir.global common @named1_(dense<0> : vector<4xi8>) {alignment = 4 : i64} : !fir.array<4xi8> ! Module defines variable in common block with initialization module modCommonInit1 integer :: i_named2 = 42 common /named2/ i_named2 end module -! CHECK-LABEL: fir.global @named2_ : tuple { +! CHECK-LABEL: fir.global @named2_ {alignment = 4 : i64} : tuple { ! CHECK: %[[init:.*]] = fir.insert_value %{{.*}}, %c42{{.*}}, [0 : index] : (tuple, i32) -> tuple ! CHECK: fir.has_value %[[init]] : tuple diff --git a/flang/test/Lower/module_use.f90 b/flang/test/Lower/module_use.f90 index 21458bb48843..ad43865470b6 100644 --- a/flang/test/Lower/module_use.f90 +++ b/flang/test/Lower/module_use.f90 @@ -5,9 +5,9 @@ ! The modules are defined in module_definition.f90 ! The first runs ensures the module file is generated. -! CHECK: fir.global common @__BLNK__(dense<0> : vector<4xi8>) : !fir.array<4xi8> -! CHECK-NEXT: fir.global common @named1_(dense<0> : vector<4xi8>) : !fir.array<4xi8> -! CHECK-NEXT: fir.global common @named2_(dense<0> : vector<4xi8>) : !fir.array<4xi8> +! CHECK: fir.global common @__BLNK__(dense<0> : vector<4xi8>) {alignment = 4 : i64} : !fir.array<4xi8> +! CHECK-NEXT: fir.global common @named1_(dense<0> : vector<4xi8>) {alignment = 4 : i64} : !fir.array<4xi8> +! CHECK-NEXT: fir.global common @named2_(dense<0> : vector<4xi8>) {alignment = 4 : i64} : !fir.array<4xi8> ! CHECK-LABEL: func @_QPm1use() real function m1use() diff --git a/flang/test/Lower/pointer-initial-target-2.f90 b/flang/test/Lower/pointer-initial-target-2.f90 index 1129ddd03560..99c7ede50504 100644 --- a/flang/test/Lower/pointer-initial-target-2.f90 +++ b/flang/test/Lower/pointer-initial-target-2.f90 @@ -11,7 +11,7 @@ block data real, save, target :: b common /a/ p data p /b/ -! CHECK-LABEL: fir.global @a_ : tuple>> +! CHECK-LABEL: fir.global @a_ {alignment = 8 : i64} : tuple>> ! CHECK: %[[undef:.*]] = fir.zero_bits tuple>> ! CHECK: %[[b:.*]] = fir.address_of(@_QEb) : !fir.ref ! CHECK: %[[box:.*]] = fir.embox %[[b]] : (!fir.ref) -> !fir.box @@ -29,9 +29,9 @@ block data tied real, pointer :: p2 => x1 common /c1/ x1, p1 common /c2/ x2, p2 -! CHECK-LABEL: fir.global @c1_ : tuple, !fir.box>> +! CHECK-LABEL: fir.global @c1_ {alignment = 8 : i64} : tuple, !fir.box>> ! CHECK: fir.address_of(@c2_) : !fir.ref, !fir.box>>> -! CHECK-LABEL: fir.global @c2_ : tuple, !fir.box>> +! CHECK-LABEL: fir.global @c2_ {alignment = 8 : i64} : tuple, !fir.box>> ! CHECK: fir.address_of(@c1_) : !fir.ref, !fir.box>>> end block data @@ -40,7 +40,7 @@ block data bdsnake integer, target :: b = 42 integer, pointer :: p => b common /snake/ p, b -! CHECK-LABEL: fir.global @snake_ : tuple>, i32> +! CHECK-LABEL: fir.global @snake_ {alignment = 8 : i64} : tuple>, i32> ! CHECK: %[[tuple0:.*]] = fir.zero_bits tuple>, i32> ! CHECK: %[[snakeAddr:.*]] = fir.address_of(@snake_) : !fir.ref>, i32>> ! CHECK: %[[byteView:.*]] = fir.convert %[[snakeAddr:.*]] : (!fir.ref>, i32>>) -> !fir.ref>