File: ompi_fortran_get_alignment.m4

package info (click to toggle)
openmpi 5.0.8-3
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 201,692 kB
  • sloc: ansic: 613,078; makefile: 42,353; sh: 11,194; javascript: 9,244; f90: 7,052; java: 6,404; perl: 5,179; python: 1,859; lex: 740; fortran: 61; cpp: 20; tcl: 12
file content (220 lines) | stat: -rw-r--r-- 8,873 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
dnl -*- shell-script -*-
dnl
dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
dnl                         University Research and Technology
dnl                         Corporation.  All rights reserved.
dnl Copyright (c) 2004-2005 The University of Tennessee and The University
dnl                         of Tennessee Research Foundation.  All rights
dnl                         reserved.
dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
dnl                         University of Stuttgart.  All rights reserved.
dnl Copyright (c) 2004-2005 The Regents of the University of California.
dnl                         All rights reserved.
dnl Copyright (c) 2025      Research Organization for Information Science
dnl                         and Technology (RIST).  All rights reserved.
dnl Copyright (c) 2010-2012 Cisco Systems, Inc.  All rights reserved.
dnl $COPYRIGHT$
dnl
dnl Additional copyrights may follow
dnl
dnl $HEADER$
dnl

# This is a long, sordid tale.

# We have been unable to devise a F90 test that will result in a
# consistent alignment answer.  Specifically, our prior tests have
# been similar to the prior f77 test -- have a small chunk of f90 code
# compiled with the C code to actually compute the offsets.  The f90
# code was a struct-like entity (a "type") with multiple members -- on
# a character and the other of the target type.  The C code measured
# the distance between them.  But even if you use the keyword to
# ensure that the F90 compiler does not re-order this struct, you may
# still get a different alignment answer than the F77 test (!).  This
# is apparently because F90 allows compilers to align types
# differently according to use (in common blocks, as standalone
# variables, and as a member of a struct).  Hence, the alignment can
# be different depending on how to measure (and use) it.  This was
# confirmed by various members of the Fortran committee and several
# Fortran compiler vendors.

# We use to check the F77 alignment based on common block usage, but
# this is only one of the available types for F90.  Hence, we may
# actually get a different answer between f77 and f90 in the same
# compiler series (and some compilers do!  E.g., g95 gives different
# answers even when "g95" itself is used as both the f77 and f90
# compiler).

# So we gave up -- the only thing we can do (and has worked for years)
# is to check Fortran alignment in common blocks when compiled with .f
# files (not .f90).

# Indeed, just because data is coming from the mpif.h bindings doesn't
# mean it wasn't compiled with the f90 (or later) compiler.  So
# there's no way to tell -- just hope that common block alignment is
# good enough.  :-(

# OMPI_FORTRAN_GET_ALIGNMENT(type, shell variable to set)
# ----------------------------------------------------
AC_DEFUN([OMPI_FORTRAN_GET_ALIGNMENT],[
    OPAL_VAR_SCOPE_PUSH([fortran_get_alignment_happy ompi_conftest_h])
    # Use of m4_translit suggested by Eric Blake:
    # http://lists.gnu.org/archive/html/bug-autoconf/2010-10/msg00016.html
    AS_VAR_PUSHDEF([type_var],
       m4_translit([[ompi_cv_fortran_alignment_$1]], [*], [p]))

    AC_CACHE_CHECK([alignment of Fortran $1], type_var,
       [OMPI_FORTRAN_MAKE_C_FUNCTION([ompi_ac_align_fn], [align])
        # Fortran module.  Make sure it's .f, not .f90.
        cat > conftestf.f <<EOF
      program falign
      external align
      $1  w,x,y,z
      CHARACTER a,b,c
      common /foo/a,w,b,x,y,c,z
      call align(w,x,y,z)
      end
EOF

        # C module
        if test -f conftest.h; then
            ompi_conftest_h="#include \"conftest.h\""
        else
            ompi_conftest_h=""
        fi
        cat > conftest.c <<EOF
#include <stdio.h>
#include <stdlib.h>
$ompi_conftest_h

#ifdef __cplusplus
extern "C" {
#endif
void $ompi_ac_align_fn(char *w, char *x, char *y, char *z)
{   unsigned long aw, ax, ay, az;
    FILE *f=fopen("conftestval", "w");
    if (!f) exit(1);
    aw = (unsigned long) w;
    ax = (unsigned long) x;
    ay = (unsigned long) y;
    az = (unsigned long) z;
    if (! ((aw%16)||(ax%16)||(ay%16)||(az%16))) fprintf(f, "%d\n", 16);
    else if (! ((aw%12)||(ax%12)||(ay%12)||(az%12))) fprintf(f, "%d\n", 12);
    else if (! ((aw%8)||(ax%8)||(ay%8)||(az%8))) fprintf(f, "%d\n", 8);
    else if (! ((aw%4)||(ax%4)||(ay%4)||(az%4))) fprintf(f, "%d\n", 4);
    else if (! ((aw%2)||(ax%2)||(ay%2)||(az%2))) fprintf(f, "%d\n", 2);
    else fprintf(f, "%d\n", 1);
    fclose(f);
}
#ifdef __cplusplus
}
#endif
EOF

        OPAL_LOG_COMMAND([$CC $CFLAGS -I. -c conftest.c],
            [OPAL_LOG_COMMAND([$FC $FCFLAGS conftestf.f conftest.o -o conftest $LDFLAGS $LIBS],
                [fortran_get_alignment_happy="yes"],
                [fortran_get_alignment_happy="no"])],
            [fortran_get_alignment_happy="no"])

        if test "$fortran_get_alignment_happy" = "no" ; then
            AC_MSG_RESULT([Error!])
            AC_MSG_ERROR([Could not determine alignment of $1])
        fi

        AS_IF([test "$cross_compiling" = "yes"],
            [AC_MSG_RESULT([Error!])
             AC_MSG_ERROR([Can not determine alignment of $1 when cross-compiling])],
            [OPAL_LOG_COMMAND([./conftest],
                [AS_VAR_SET(type_var, [`cat conftestval`])],
                [AC_MSG_RESULT([Error!])
                 AC_MSG_ERROR([Could not determine alignment of $1])])])
        rm -rf conftest*])

    AS_VAR_COPY([$2], [type_var])
    AS_VAR_POPDEF([type_var])dnl
    OPAL_VAR_SCOPE_POP
])

# OMPI_FORTRAN_F08_GET_HANDLE_ALIGNMENT(type, variable to set)
# ------------------------------------------
AC_DEFUN([OMPI_FORTRAN_F08_GET_HANDLE_ALIGNMENT],[
    # Use of m4_translit suggested by Eric Blake:
    # http://lists.gnu.org/archive/html/bug-autoconf/2010-10/msg00016.html
    AS_VAR_PUSHDEF([type_var],
       m4_translit([[ompi_cv_fortran_alignment_$1]], [*], [p]))

    AC_CACHE_CHECK([alignment of Fortran $1], type_var,
        [AC_LANG_PUSH([Fortran])
         AC_LINK_IFELSE([AC_LANG_SOURCE([[module alignment_mod
type, BIND(C) :: test_mpi_handle
  integer :: MPI_VAL
end type test_mpi_handle
type(test_mpi_handle) :: t1
type(test_mpi_handle) :: t2
end module

program falignment
   use alignment_mod
   OPEN(UNIT=10, FILE="conftestval")
   if (LOC(t1) > LOC(t2)) then
      write (10,'(I5)') LOC(t1)-LOC(t2)
   else
      write (10,'(I5)') LOC(t2)-LOC(t1)
   endif
   CLOSE(10)

end program]])],
                          [AS_IF([test "$cross_compiling" = "yes"],
                                 [AC_MSG_ERROR([Can not determine alignment of $1 when cross-compiling])],
                                 [OPAL_LOG_COMMAND([./conftest],
                                                   [AS_VAR_SET(type_var, [`cat conftestval`])],
                                                   [AC_MSG_ERROR([Could not determine alignment of $1])])])],

                          [AC_MSG_WARN([Could not determine alignment of $1])
                           AC_MSG_WARN([See config.log for details])
                           AC_MSG_ERROR([Cannot continue])])
         rm -rf conftest* *.mod 2> /dev/null
         AC_LANG_POP([Fortran])])

    AS_VAR_COPY([$2], [type_var])
    AS_VAR_POPDEF([type_var])dnl
])dnl

# OMPI_FORTRAN_GET_COMMON_ALIGNMENT(variable to set)
# ------------------------------------------
AC_DEFUN([OMPI_FORTRAN_GET_COMMON_ALIGNMENT],[
    AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -gt $OMPI_FORTRAN_NO_BINDINGS],
          [AC_CACHE_CHECK([alignment of Fortran common], ompi_cv_fortran_common_alignment,
              [AC_LANG_PUSH([Fortran])
               AC_LINK_IFELSE([AC_LANG_SOURCE([[ program falignment
   CHARACTER A,B
   COMMON /AA/A
   COMMON /BB/B
   OPEN(UNIT=10, FILE="conftestval")
   if (LOC(A) > LOC(B)) then
      write (10,'(I5)') LOC(A)-LOC(B)
   else
      write (10,'(I5)') LOC(B)-LOC(A)
   endif
   CLOSE(10)

end program]])],
                          [AS_IF([test "$cross_compiling" = "yes"],
                                 [AC_MSG_ERROR([Can not determine common alignment when cross-compiling])],
                                 [OPAL_LOG_COMMAND([./conftest],
                                                   [AS_VAR_SET(ompi_cv_fortran_common_alignment, [`cat conftestval`])],
                                                   [AC_MSG_ERROR([Could not determine common alignment])])])],

                          [AC_MSG_WARN([Could not determine common alignment])
                           AC_MSG_WARN([See config.log for details])
                           AC_MSG_ERROR([Cannot continue])])
               rm -rf conftest* *.mod 2> /dev/null
               AC_LANG_POP([Fortran])])

           AS_VAR_COPY([$1], [ompi_cv_fortran_common_alignment])],
          [AC_MSG_CHECKING([Fortran common alignment])
           $1=0
           AC_MSG_RESULT([skipped])])

])dnl