Skip to content

Commit b38e78c

Browse files
clementvaljeanPerierschweitzpgi
committed
[flang][NFC] Add module lowering tests
This patch adds test for the lowering of Fortran modules. This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D122317 Co-authored-by: Jean Perier <[email protected]> Co-authored-by: Eric Schweitz <[email protected]>
1 parent 5800fb4 commit b38e78c

File tree

6 files changed

+361
-1
lines changed

6 files changed

+361
-1
lines changed

flang/test/CMakeLists.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,17 @@ set(FLANG_TEST_PARAMS
4646
flang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
4747

4848
set(FLANG_TEST_DEPENDS
49-
flang-new llvm-config FileCheck count not module_files fir-opt tco bbc llvm-objdump
49+
flang-new
50+
llvm-config
51+
FileCheck
52+
count
53+
not
54+
module_files
55+
fir-opt
56+
tco
57+
bbc
58+
llvm-objdump
59+
split-file
5060
)
5161

5262
if (FLANG_INCLUDE_TESTS)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
! Test that module data access are lowered correctly in the different
2+
! procedure contexts.
3+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
4+
5+
module parent
6+
integer :: i
7+
contains
8+
! Test simple access to the module data
9+
! CHECK-LABEL: func @_QMparentPtest1
10+
subroutine test1()
11+
! CHECK: fir.address_of(@_QMparentEi) : !fir.ref<i32>
12+
print *, i
13+
end subroutine
14+
15+
! Test access to the module data inside an internal procedure where the
16+
! host is defined inside the module.
17+
subroutine test2()
18+
call test2internal()
19+
contains
20+
! CHECK-LABEL: func @_QMparentFtest2Ptest2internal()
21+
subroutine test2internal()
22+
! CHECK: fir.address_of(@_QMparentEi) : !fir.ref<i32>
23+
print *, i
24+
end subroutine
25+
end subroutine
26+
end module
27+
28+
! Test access to the module data inside an internal procedure where the
29+
! host is using the module.
30+
subroutine test3()
31+
use parent
32+
call test3internal()
33+
contains
34+
! CHECK-LABEL: func @_QFtest3Ptest3internal()
35+
subroutine test3internal()
36+
! CHECK: fir.address_of(@_QMparentEi) : !fir.ref<i32>
37+
print *, i
38+
end subroutine
39+
end subroutine
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
! Test that module variables with an initializer are only defined once,
2+
! except for compiler generated derived type descriptor that should be
3+
! always fully defined as linkonce_odr by the compilation units defining or
4+
! using them.
5+
! Test that this holds true in contexts with namelist members that are special
6+
! because the symbol on the use site are not symbols with semantics::UseDetails,
7+
! but directly the symbols from the module scope.
8+
9+
10+
! RUN: split-file %s %t
11+
! RUN: bbc -emit-fir %t/definition-a.f90 -o - | FileCheck %s --check-prefix=CHECK-A-DEF
12+
! RUN: bbc -emit-fir %t/definition-b.f90 -o - | FileCheck %s --check-prefix=CHECK-B-DEF
13+
! RUN: bbc -emit-fir %t/use.f90 -o - | FileCheck %s --check-prefix=CHECK-USE
14+
15+
16+
17+
!--- definition-a.f90
18+
19+
! Test definition of `atype` derived type descriptor as `linkonce_odr`
20+
module define_a
21+
type atype
22+
real :: x
23+
end type
24+
end module
25+
26+
! CHECK-A-DEF: fir.global linkonce_odr @_QMdefine_aE.dt.atype constant : !fir.type<{{.*}}> {
27+
! CHECK-A-DEF: fir.has_value
28+
! CHECK-A-DEF: }
29+
30+
!--- definition-b.f90
31+
32+
! Test define_b `i` is defined here.
33+
! Also test that the derived type descriptor of types defined here (`btype`) and used
34+
! here (`atype`) are fully defined here as linkonce_odr.
35+
module define_b
36+
use :: define_a
37+
type btype
38+
type(atype) :: atype
39+
end type
40+
integer :: i = 42
41+
namelist /some_namelist/ i
42+
end module
43+
44+
! CHECK-B-DEF: fir.global @_QMdefine_bEi : i32 {
45+
! CHECK-B-DEF: fir.has_value %{{.*}} : i32
46+
! CHECK-B-DEF: }
47+
48+
! CHECK-B-DEF: fir.global linkonce_odr @_QMdefine_bE.dt.btype constant : !fir.type<{{.*}}> {
49+
! CHECK-B-DEF: fir.has_value
50+
! CHECK-B-DEF: }
51+
52+
! CHECK-B-DEF: fir.global linkonce_odr @_QMdefine_aE.dt.atype constant : !fir.type<{{.*}}> {
53+
! CHECK-B-DEF: fir.has_value
54+
! CHECK-B-DEF: }
55+
56+
57+
58+
!--- use.f90
59+
60+
! Test define_b `i` is declared but not defined here and that derived types
61+
! descriptors are fully defined as linkonce_odr here.
62+
subroutine foo()
63+
use :: define_b
64+
type(btype) :: somet
65+
print *, somet
66+
write(*, some_namelist)
67+
end subroutine
68+
! CHECK-USE: fir.global @_QMdefine_bEi : i32{{$}}
69+
! CHECK-USE-NOT: fir.has_value %{{.*}} : i32
70+
71+
! CHECK-USE: fir.global linkonce_odr @_QMdefine_aE.dt.atype constant : !fir.type<{{.*}}> {
72+
! CHECK-USE: fir.has_value
73+
! CHECK-USE: }
74+
75+
! CHECK-USE: fir.global linkonce_odr @_QMdefine_bE.dt.btype constant : !fir.type<{{.*}}> {
76+
! CHECK-USE: fir.has_value
77+
! CHECK-USE: }
78+
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! Test lowering of module that defines data that is otherwise not used
4+
! in this file.
5+
6+
! Module m1 defines simple data
7+
module m1
8+
real :: x
9+
integer :: y(100)
10+
end module
11+
! CHECK: fir.global @_QMm1Ex : f32
12+
! CHECK: fir.global @_QMm1Ey : !fir.array<100xi32>
13+
14+
! Module modEq1 defines data that is equivalenced and not used in this
15+
! file.
16+
module modEq1
17+
! Equivalence, no initialization
18+
real :: x1(10), x2(10), x3(10)
19+
! Equivalence with initialization
20+
real :: y1 = 42.
21+
real :: y2(10)
22+
equivalence (x1(1), x2(5), x3(10)), (y1, y2(5))
23+
end module
24+
! CHECK-LABEL: fir.global @_QMmodeq1Ex1 : !fir.array<76xi8>
25+
! CHECK-LABEL: fir.global @_QMmodeq1Ey1 : !fir.array<10xi32> {
26+
! CHECK: %[[undef:.*]] = fir.undefined !fir.array<10xi32>
27+
! CHECK: %[[v1:.*]] = fir.insert_on_range %0, %c0{{.*}} from (0) to (3) : (!fir.array<10xi32>, i32) -> !fir.array<10xi32>
28+
! CHECK: %[[v2:.*]] = fir.insert_value %1, %c1109917696{{.*}}, [4 : index] : (!fir.array<10xi32>, i32) -> !fir.array<10xi32>
29+
! CHECK: %[[v3:.*]] = fir.insert_on_range %2, %c0{{.*}} from (5) to (9) : (!fir.array<10xi32>, i32) -> !fir.array<10xi32>
30+
! CHECK: fir.has_value %[[v3]] : !fir.array<10xi32>
31+
32+
! Module defines variable in common block without initializer
33+
module modCommonNoInit1
34+
! Module variable is in blank common
35+
real :: x_blank
36+
common // x_blank
37+
! Module variable is in named common, no init
38+
real :: x_named1
39+
common /named1/ x_named1
40+
end module
41+
! CHECK-LABEL: fir.global common @_QB(dense<0> : vector<4xi8>) : !fir.array<4xi8>
42+
! CHECK-LABEL: fir.global common @_QBnamed1(dense<0> : vector<4xi8>) : !fir.array<4xi8>
43+
44+
! Module defines variable in common block with initialization
45+
module modCommonInit1
46+
integer :: i_named2 = 42
47+
common /named2/ i_named2
48+
end module
49+
! CHECK-LABEL: fir.global @_QBnamed2 : tuple<i32> {
50+
! CHECK: %[[init:.*]] = fir.insert_value %{{.*}}, %c42{{.*}}, [0 : index] : (tuple<i32>, i32) -> tuple<i32>
51+
! CHECK: fir.has_value %[[init]] : tuple<i32>
52+
53+
! Test defining two module variables whose initializers depend on each others
54+
! addresses.
55+
module global_init_depending_on_each_other_address
56+
type a
57+
type(b), pointer :: pb
58+
end type
59+
type b
60+
type(a), pointer :: pa
61+
end type
62+
type(a), target :: xa
63+
type(b), target :: xb
64+
data xa, xb/a(xb), b(xa)/
65+
end module
66+
! CHECK-LABEL: fir.global @_QMglobal_init_depending_on_each_other_addressExb
67+
! CHECK: fir.address_of(@_QMglobal_init_depending_on_each_other_addressExa)
68+
! CHECK-LABEL: fir.global @_QMglobal_init_depending_on_each_other_addressExa
69+
! CHECK: fir.address_of(@_QMglobal_init_depending_on_each_other_addressExb)

flang/test/Lower/module_use.f90

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
! RUN: bbc -emit-fir %S/module_definition.f90
2+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
3+
4+
! Test use of module data not defined in this file.
5+
! The modules are defined in module_definition.f90
6+
! The first runs ensures the module file is generated.
7+
8+
! CHECK-LABEL: func @_QPm1use()
9+
real function m1use()
10+
use m1
11+
! CHECK-DAG: fir.address_of(@_QMm1Ex) : !fir.ref<f32>
12+
! CHECK-DAG: fir.address_of(@_QMm1Ey) : !fir.ref<!fir.array<100xi32>>
13+
m1use = x + y(1)
14+
end function
15+
16+
! TODO: test equivalences once front-end fix in module file is pushed.
17+
!! CHECK-LABEL func @_QPmodeq1use()
18+
!real function modEq1use()
19+
! use modEq1
20+
! ! CHECK-DAG fir.address_of(@_QMmodeq1Ex1) : !fir.ref<tuple<!fir.array<36xi8>, !fir.array<40xi8>>>
21+
! ! CHECK-DAG fir.address_of(@_QMmodeq1Ey1) : !fir.ref<tuple<!fir.array<16xi8>, !fir.array<24xi8>>>
22+
! modEq1use = x2(1) + y1
23+
!end function
24+
! CHECK-DAG fir.global @_QMmodeq1Ex1 : tuple<!fir.array<36xi8>, !fir.array<40xi8>>
25+
! CHECK-DAG fir.global @_QMmodeq1Ey1 : tuple<!fir.array<16xi8>, !fir.array<24xi8>>
26+
27+
! CHECK-LABEL: func @_QPmodcommon1use()
28+
real function modCommon1Use()
29+
use modCommonInit1
30+
use modCommonNoInit1
31+
! CHECK-DAG: fir.address_of(@_QBnamed2) : !fir.ref<!fir.array<4xi8>>
32+
! CHECK-DAG: fir.address_of(@_QB) : !fir.ref<!fir.array<4xi8>>
33+
! CHECK-DAG: fir.address_of(@_QBnamed1) : !fir.ref<!fir.array<4xi8>>
34+
modCommon1Use = x_blank + x_named1 + i_named2
35+
end function
36+
37+
38+
! CHECK-DAG: fir.global @_QMm1Ex : f32
39+
! CHECK-DAG: fir.global @_QMm1Ey : !fir.array<100xi32>
40+
! CHECK-DAG: fir.global common @_QBnamed2(dense<0> : vector<4xi8>) : !fir.array<4xi8>
41+
! CHECK-DAG: fir.global common @_QB(dense<0> : vector<4xi8>) : !fir.array<4xi8>
42+
! CHECK-DAG: fir.global common @_QBnamed1(dense<0> : vector<4xi8>) : !fir.array<4xi8>
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! Test use of module data that is defined in this file.
4+
! TODO: similar tests for the functions that are using the modules, but without the
5+
! module being defined in this file. This require a front-end fix to be pushed first
6+
! so
7+
8+
! Module m2 defines simple data
9+
module m2
10+
real :: x
11+
integer :: y(100)
12+
contains
13+
! CHECK-LABEL: func @_QMm2Pfoo()
14+
real function foo()
15+
! CHECK-DAG: fir.address_of(@_QMm2Ex) : !fir.ref<f32>
16+
! CHECK-DAG: fir.address_of(@_QMm2Ey) : !fir.ref<!fir.array<100xi32>>
17+
foo = x + y(1)
18+
end function
19+
end module
20+
! CHECK-LABEL: func @_QPm2use()
21+
real function m2use()
22+
use m2
23+
! CHECK-DAG: fir.address_of(@_QMm2Ex) : !fir.ref<f32>
24+
! CHECK-DAG: fir.address_of(@_QMm2Ey) : !fir.ref<!fir.array<100xi32>>
25+
m2use = x + y(1)
26+
end function
27+
! Test renaming
28+
! CHECK-LABEL: func @_QPm2use_rename()
29+
real function m2use_rename()
30+
use m2, only: renamedx => x
31+
! CHECK-DAG: fir.address_of(@_QMm2Ex) : !fir.ref<f32>
32+
m2use_rename = renamedx
33+
end function
34+
35+
! Module modEq2 defines data that is equivalenced
36+
module modEq2
37+
! Equivalence, no initialization
38+
real :: x1(10), x2(10), x3(10)
39+
! Equivalence with initialization
40+
real :: y1 = 42.
41+
real :: y2(10)
42+
equivalence (x1(1), x2(5), x3(10)), (y1, y2(5))
43+
contains
44+
! CHECK-LABEL: func @_QMmodeq2Pfoo()
45+
real function foo()
46+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ex1) : !fir.ref<!fir.array<76xi8>>
47+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ey1) : !fir.ref<!fir.array<10xi32>>
48+
foo = x2(1) + y1
49+
end function
50+
end module
51+
! CHECK-LABEL: func @_QPmodeq2use()
52+
real function modEq2use()
53+
use modEq2
54+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ex1) : !fir.ref<!fir.array<76xi8>>
55+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ey1) : !fir.ref<!fir.array<10xi32>>
56+
modEq2use = x2(1) + y1
57+
end function
58+
! Test rename of used equivalence members
59+
! CHECK-LABEL: func @_QPmodeq2use_rename()
60+
real function modEq2use_rename()
61+
use modEq2, only: renamedx => x2, renamedy => y1
62+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ex1) : !fir.ref<!fir.array<76xi8>>
63+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ey1) : !fir.ref<!fir.array<10xi32>>
64+
modEq2use = renamedx(1) + renamedy
65+
end function
66+
67+
68+
! Module defines variable in common block
69+
module modCommon2
70+
! Module variable is in blank common
71+
real :: x_blank
72+
common // x_blank
73+
! Module variable is in named common, no init
74+
real :: x_named1(10)
75+
common /named1/ x_named1
76+
! Module variable is in named common, with init
77+
integer :: i_named2 = 42
78+
common /named2/ i_named2
79+
contains
80+
! CHECK-LABEL: func @_QMmodcommon2Pfoo()
81+
real function foo()
82+
! CHECK-DAG: fir.address_of(@_QBnamed2) : !fir.ref<tuple<i32>>
83+
! CHECK-DAG: fir.address_of(@_QB) : !fir.ref<!fir.array<4xi8>>
84+
! CHECK-DAG: fir.address_of(@_QBnamed1) : !fir.ref<!fir.array<40xi8>>
85+
foo = x_blank + x_named1(5) + i_named2
86+
end function
87+
end module
88+
! CHECK-LABEL: func @_QPmodcommon2use()
89+
real function modCommon2use()
90+
use modCommon2
91+
! CHECK-DAG: fir.address_of(@_QBnamed2) : !fir.ref<tuple<i32>>
92+
! CHECK-DAG: fir.address_of(@_QB) : !fir.ref<!fir.array<4xi8>>
93+
! CHECK-DAG: fir.address_of(@_QBnamed1) : !fir.ref<!fir.array<40xi8>>
94+
modCommon2use = x_blank + x_named1(5) + i_named2
95+
end function
96+
! CHECK-LABEL: func @_QPmodcommon2use_rename()
97+
real function modCommon2use_rename()
98+
use modCommon2, only : renamed0 => x_blank, renamed1 => x_named1, renamed2 => i_named2
99+
! CHECK-DAG: fir.address_of(@_QBnamed2) : !fir.ref<tuple<i32>>
100+
! CHECK-DAG: fir.address_of(@_QB) : !fir.ref<!fir.array<4xi8>>
101+
! CHECK-DAG: fir.address_of(@_QBnamed1) : !fir.ref<!fir.array<40xi8>>
102+
modCommon2use_rename = renamed0 + renamed1(5) + renamed2
103+
end function
104+
105+
106+
! Test that there are no conflicts between equivalence use associated and the ones
107+
! from the scope
108+
real function test_no_equiv_conflicts()
109+
use modEq2
110+
! Same equivalences as in modEq2. Test that lowering does not mixes
111+
! up the equivalence based on the similar offset inside the scope.
112+
real :: x1l(10), x2l(10), x3l(10)
113+
real :: y1l = 42.
114+
real :: y2l(10)
115+
save :: x1l, x2l, x3l, y1l, y2l
116+
equivalence (x1l(1), x2l(5), x3l(10)), (y1l, y2l(5))
117+
! CHECK-DAG: fir.address_of(@_QFtest_no_equiv_conflictsEx1l) : !fir.ref<!fir.array<76xi8>>
118+
! CHECK-DAG: fir.address_of(@_QFtest_no_equiv_conflictsEy1l) : !fir.ref<!fir.array<10xi32>>
119+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ex1) : !fir.ref<!fir.array<76xi8>>
120+
! CHECK-DAG: fir.address_of(@_QMmodeq2Ey1) : !fir.ref<!fir.array<10xi32>>
121+
test_no_equiv_conflicts = x2(1) + y1 + x2l(1) + y1l
122+
end function

0 commit comments

Comments
 (0)