1#
2# Copyright (C) Mellanox Technologies Ltd. 2001-2014.  ALL RIGHTS RESERVED.
3# Copyright (c) UT-Battelle, LLC. 2017. ALL RIGHTS RESERVED.
4# Copyright (C) ARM Ltd. 2016-2020.  ALL RIGHTS RESERVED.
5# See file LICENSE for terms.
6#
7
8
9#
10# Initialize CFLAGS
11#
12BASE_CFLAGS="-g -Wall -Werror"
13
14
15#
16# Check that C++ is functional.
17#
18# AC_PROG_CXX never fails but falls back on g++ as a default CXX compiler that
19# always present. If g++ isn't installed, the macro doesn't detect this and
20# compilation fails later on. CHECK_CXX_COMP compiles simple C++ code to
21# verify that compiler is present and functional.
22#
23AC_DEFUN([CHECK_CXX_COMP],
24         [AC_MSG_CHECKING(if $CXX works)
25          AC_LANG_PUSH([C++])
26          AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
27                            #ifndef __cplusplus
28                            #error "No C++ support, AC_PROG_CXX failed"
29                            #endif
30                            ]])],
31                            [AC_MSG_RESULT([yes])],
32                            [AC_MSG_ERROR([Cannot continue. Please install C++ compiler.])])
33          AC_LANG_POP([C++])
34         ])
35
36
37#
38# Debug mode
39#
40AC_ARG_ENABLE(debug,
41        AC_HELP_STRING([--enable-debug], [Enable debug mode build]),
42        [],
43        [enable_debug=no])
44AS_IF([test "x$enable_debug" = xyes],
45        [BASE_CFLAGS="-D_DEBUG $BASE_CFLAGS"
46         BASE_CXXFLAGS="-D_DEBUG" $BASE_CXXFLAGS],
47        [])
48
49
50#
51# Optimization level
52#
53AC_ARG_ENABLE(compiler-opt,
54        AC_HELP_STRING([--enable-compiler-opt], [Set optimization level [0-3]]),
55        [],
56        [enable_compiler_opt="none"])
57AS_IF([test "x$enable_compiler_opt" = "xyes"], [BASE_CFLAGS="-O3 $BASE_CFLAGS"],
58      [test "x$enable_compiler_opt" = "xnone"],
59          [AS_IF([test "x$enable_debug" = xyes],
60                 [BASE_CFLAGS="-O0 $BASE_CFLAGS"
61                  BASE_CXXFLAGS="-O0 $BASE_CXXFLAGS"],
62                 [BASE_CFLAGS="-O3 $BASE_CFLAGS"
63                  BASE_CXXFLAGS="-O0 $BASE_CXXFLAGS"])],
64      [test "x$enable_compiler_opt" = "xno"], [],
65      [BASE_CFLAGS="-O$enable_compiler_opt $BASE_CFLAGS"])
66
67
68#
69# CHECK_CROSS_COMP (program, true-action, false-action)
70#
71# The macro checks if it can run the program; it executes
72# true action if the program can be executed, otherwise
73# false action is executed.
74# For cross-platform compilation we only check
75# if we can compile and link the program.
76AC_DEFUN([CHECK_CROSS_COMP], [
77         AC_RUN_IFELSE([$1], [$2], [$3],
78                       [AC_LINK_IFELSE([$1], [$2], [$3])])
79])
80
81
82#
83# Check for one specific attribute by compiling with C
84# Usage: CHECK_SPECIFIC_ATTRIBUTE([name], [doc], [program])
85#
86AC_DEFUN([CHECK_SPECIFIC_ATTRIBUTE], [
87    AC_CACHE_VAL(ucx_cv_attribute_[$1], [
88        SAVE_CFLAGS="$CFLAGS"
89        CFLAGS="$BASE_CFLAGS $CFLAGS"
90        #
91        # Try to compile using the C compiler
92        #
93        AC_TRY_COMPILE([$3],[],
94                       [ucx_cv_attribute_[$1]=1],
95                       [ucx_cv_attribute_[$1]=0])
96	CFLAGS="$SAVE_CFLAGS"
97    ])
98	AC_MSG_CHECKING([for __attribute__([$1])])
99	AC_MSG_RESULT([$ucx_cv_attribute_[$1]])
100	AC_DEFINE_UNQUOTED([HAVE_ATTRIBUTE_[$2]], [$ucx_cv_attribute_[$1]], [Check attribute [$1]])
101])
102
103
104#
105#  Enable/disable turning on machine-specific optimizations
106#
107AC_ARG_ENABLE(optimizations,
108              AC_HELP_STRING([--enable-optimizations],
109                             [Enable non-portable machine-specific CPU optimizations, default: NO]),
110              [],
111              [enable_optimizations=no])
112
113
114#
115# Check if compiler supports a given CPU optimization flag, and if yes - add it
116# to BASE_CFLAGS substitution, and OPT_CFLAGS C define.
117#
118# Usage: COMPILER_CPU_OPTIMIZATION([name], [doc], [flag], [program])
119#
120AC_DEFUN([COMPILER_CPU_OPTIMIZATION],
121[
122    AC_ARG_WITH([$1],
123                [AC_HELP_STRING([--with-$1], [Use $2 compiler option.])],
124                [],
125                [with_$1=$enable_optimizations])
126
127    AS_IF([test "x$with_$1" != "xno"],
128          [SAVE_CFLAGS="$CFLAGS"
129           CFLAGS="$BASE_CFLAGS $CFLAGS $3"
130           AC_MSG_CHECKING([$3])
131           CHECK_CROSS_COMP([AC_LANG_SOURCE([$4])],
132                            [AC_MSG_RESULT([yes])
133                             # TODO: Add CPU UARCH detector and validator in UCX init.
134                             # As for now we will avoid passing this information to
135                             # library.
136                             BASE_CFLAGS="$BASE_CFLAGS $3"
137                             AS_IF([test "x$1" != "xmcpu" -a "x$1" != "xmarch"],
138                                   [OPT_CFLAGS="$OPT_CFLAGS|$1"])],
139                            [AC_MSG_RESULT([no])])
140           CFLAGS="$SAVE_CFLAGS"])
141])
142
143
144#
145# Check platform uarch and apply micro-architecture specific optimizations
146#
147AC_DEFUN([DETECT_UARCH],
148[
149    cpuimpl=`grep 'CPU implementer' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1`
150    cpuarch=`grep 'CPU architecture' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1`
151    cpuvar=`grep 'CPU variant' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1`
152    cpupart=`grep 'CPU part' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1`
153
154    ax_cpu=""
155    ax_arch=""
156
157    AC_MSG_NOTICE(Detected CPU implementation: ${cpuimpl})
158    AC_MSG_NOTICE(Detected CPU architecture: ${cpuarch})
159    AC_MSG_NOTICE(Detected CPU variant: ${cpuvar})
160    AC_MSG_NOTICE(Detected CPU part: ${cpupart})
161
162    case $cpuimpl in
163      0x42) case $cpupart in
164        0x516 | 0x0516)
165          AC_DEFINE([HAVE_AARCH64_THUNDERX2], 1, [Cavium ThunderX2])
166          ax_cpu="thunderx2t99"
167          ax_arch="armv8.1-a+lse" ;;
168        0xaf | 0x0af)
169          AC_DEFINE([HAVE_AARCH64_THUNDERX2], 1, [Cavium ThunderX2])
170          ax_cpu="thunderx2t99"
171          ax_arch="armv8.1-a+lse" ;;
172        esac
173        ;;
174      0x43) case $cpupart in
175        0x516 | 0x0516)
176          AC_DEFINE([HAVE_AARCH64_THUNDERX2], 1, [Cavium ThunderX2])
177          ax_cpu="thunderx2t99"
178          ax_arch="armv8.1-a+lse" ;;
179        0xaf | 0x0af)
180          AC_DEFINE([HAVE_AARCH64_THUNDERX2], 1, [Cavium ThunderX2])
181          ax_cpu="thunderx2t99"
182          ax_arch="armv8.1-a+lse" ;;
183        0xa1 | 0x0a1)
184          AC_DEFINE([HAVE_AARCH64_THUNDERX1], 1, [Cavium ThunderX1])
185          ax_cpu="thunderxt88" ;;
186        esac
187        ;;
188      0x48) case $cpupart in
189        0xd01 | 0x0d01)
190          AC_DEFINE([HAVE_AARCH64_HI1620], 1, [Huawei Kunpeng 920])
191          ax_cpu="tsv110"
192          ax_arch="armv8.2-a" ;;
193        esac
194        ;;
195      *)
196        ;;
197    esac
198    AM_CONDITIONAL([HAVE_AARCH64_THUNDERX2], [test x$ax_cpu = xthunderx2t99])
199    AM_CONDITIONAL([HAVE_AARCH64_THUNDERX1], [test x$ax_cpu = xthunderxt88])
200    AM_CONDITIONAL([HAVE_AARCH64_HI1620], [test x$ax_cpu = xtsv110])
201])
202
203
204#
205# CHECK_COMPILER_FLAG
206# Usage: CHECK_COMPILER_FLAG([name], [flag], [program], [if-true], [if-false])
207#
208# The macro checks if program may be compiled using specified flag
209#
210AC_DEFUN([CHECK_COMPILER_FLAG],
211[
212         AC_MSG_CHECKING([compiler flag $1])
213         SAVE_CFLAGS="$CFLAGS"
214         SAVE_CXXFLAGS="$CFLAGS"
215         CFLAGS="$BASE_CFLAGS $CFLAGS $2"
216         CXXFLAGS="$BASE_CXXFLAGS $CXXFLAGS $2"
217         AC_COMPILE_IFELSE([$3],
218                           [AC_MSG_RESULT([yes])
219                            CFLAGS="$SAVE_CFLAGS"
220                            CXXFLAGS="$SAVE_CXXFLAGS"
221                            $4],
222                           [AC_MSG_RESULT([no])
223                            CFLAGS="$SAVE_CFLAGS"
224                            CXXFLAGS="$SAVE_CXXFLAGS"
225                            $5])
226])
227
228
229#
230# ADD_COMPILER_FLAG_IF_SUPPORTED
231# Usage: ADD_COMPILER_FLAG_IF_SUPPORTED([name], [flag], [program], [if-true], [if-false])
232#
233# The macro checks if program may be compiled using specified flag and adds
234# this flag if it is supported
235#
236AC_DEFUN([ADD_COMPILER_FLAG_IF_SUPPORTED],
237[
238         CHECK_COMPILER_FLAG([$1], [$2], [$3],
239                             [BASE_CFLAGS="$BASE_CFLAGS $2"
240                              $4],
241                             [$5])
242])
243
244
245#
246# ADD_COMPILER_FLAGS_IF_SUPPORTED
247# Usage: ADD_COMPILER_FLAGS_IF_SUPPORTED([[flag1], [flag2], [flag3]], [program])
248#
249# The macro checks multiple flags supported by compiler
250#
251AC_DEFUN([ADD_COMPILER_FLAGS_IF_SUPPORTED],
252[
253         m4_foreach([_flag], [$1],
254                    [ADD_COMPILER_FLAG_IF_SUPPORTED([_flag], [_flag], [$2], [], [])])
255])
256
257
258#
259# CHECK_DEPRECATED_DECL_FLAG (flag, variable)
260#
261# The macro checks if the given compiler flag enables usig deprecated declarations.
262# If yes, it appends the flags to "variable".
263#
264AC_DEFUN([CHECK_DEPRECATED_DECL_FLAG],
265[
266         AC_MSG_CHECKING([whether $1 overrides deprecated declarations])
267         SAVE_CFLAGS="$CFLAGS"
268         CFLAGS="$BASE_CFLAGS $CFLAGS $1"
269         AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
270                                  int __attribute__ ((__deprecated__)) f() { return 0; }
271                                  int main(int argc, char** argv) { return f(); }
272                            ]])],
273                           [AC_MSG_RESULT([yes])
274                            $2="${$2} $1"],
275                           [AC_MSG_RESULT([no])])
276         CFLAGS="$SAVE_CFLAGS"
277])
278
279
280#
281# Force ICC treat command line warnings as errors.
282# This evaluation should be called prior to all other compiler flags evals
283#
284CHECK_COMPILER_FLAG([-diag-error 10006], [-diag-error 10006],
285                    [AC_LANG_SOURCE([[int main(int argc, char** argv){return 0;}]])],
286                    [BASE_CFLAGS="$BASE_CFLAGS -diag-error 10006"
287                     BASE_CXXFLAGS="$BASE_CXXFLAGS -diag-error 10006"],
288                    [])
289
290
291CHECK_DEPRECATED_DECL_FLAG([-diag-disable 1478], CFLAGS_NO_DEPRECATED) # icc
292CHECK_DEPRECATED_DECL_FLAG([-Wno-deprecated-declarations], CFLAGS_NO_DEPRECATED) # gcc
293AC_SUBST([CFLAGS_NO_DEPRECATED], [$CFLAGS_NO_DEPRECATED])
294
295
296#
297# Disable format-string warning on ICC
298#
299ADD_COMPILER_FLAG_IF_SUPPORTED([-diag-disable 269],
300                               [-diag-disable 269],
301                               [AC_LANG_SOURCE([[#include <stdlib.h>
302                                                 #include <stdio.h>
303                                                 int main(int argc, char** argv) {
304                                                     char *p = NULL;
305                                                     scanf("%m[^.]", &p);
306                                                     free(p);
307                                                     return 0;
308                                                 }]])],
309                               [],
310                               [])
311
312
313#
314# Set default datatype alignment to 16 bytes.
315# Some compilers (LLVM based, clang) expects allocation of datatypes by 32 bytes
316# to optimize operations memset/memcpy/etc using vectorized processor instructions
317# which requires aligment of memory buffer by 32 or higer bytes. Default malloc method
318# guarantee alignment for 16 bytes only. Force using compiler 16-bytes alignment
319# by default if option is supported.
320#
321UCX_ALLOC_ALIGN=16
322ADD_COMPILER_FLAG_IF_SUPPORTED([-fmax-type-align=$UCX_ALLOC_ALIGN],
323                               [-fmax-type-align=$UCX_ALLOC_ALIGN],
324                               [AC_LANG_SOURCE([[int main(int argc, char** argv){return 0;}]])],
325                               [AC_DEFINE_UNQUOTED([UCX_ALLOC_ALIGN], $UCX_ALLOC_ALIGN, [Set aligment assumption for compiler])],
326                               [])
327
328
329#
330# SSE/AVX
331#
332COMPILER_CPU_OPTIMIZATION([avx], [AVX], [-mavx],
333                          [#include <immintrin.h>
334                           int main(int argc, char** argv) {
335                               return _mm256_testz_si256(_mm256_set1_epi32(1), _mm256_set1_epi32(3));
336                           }
337                          ])
338AS_IF([test "x$with_avx" != xyes],
339      [COMPILER_CPU_OPTIMIZATION([sse41], [SSE 4.1], [-msse4.1],
340                                 [#include <smmintrin.h>
341                                  int main(int argc, char** argv) {
342                                      return _mm_testz_si128(_mm_set1_epi32(1), _mm_set1_epi32(3));
343                                  }
344                                 ])
345       COMPILER_CPU_OPTIMIZATION([sse42], [SSE 4.2], [-msse4.2],
346                                 [#include <popcntintrin.h>
347                                  int main(int argc, char** argv) { return _mm_popcnt_u32(0x101) - 2;
348                                  }])
349      ])
350
351
352DETECT_UARCH()
353
354
355#
356# CPU tuning
357#
358AS_IF([test "x$ax_cpu" != "x"],
359      [COMPILER_CPU_OPTIMIZATION([mcpu], [CPU Model], [-mcpu=$ax_cpu],
360                                 [int main(int argc, char** argv) { return 0;}])
361      ])
362
363
364#
365# Architecture tuning
366#
367AS_IF([test "x$ax_arch" != "x"],
368      [COMPILER_CPU_OPTIMIZATION([march], [architecture tuning], [-march=$ax_arch],
369                                 [int main(int argc, char** argv) { return 0;}])
370      ])
371
372
373#
374# Check for compiler attribute which disables optimizations per-function.
375#
376CHECK_SPECIFIC_ATTRIBUTE([optimize], [NOOPTIMIZE],
377                         [int foo (int arg) __attribute__ ((optimize("O0")));])
378
379
380#
381# Compile code with frame pointer. Optimizations usually omit the frame pointer,
382# but if we are profiling the code with callgraph we need it.
383# This option may affect perofrmance so it is off by default.
384#
385AC_ARG_ENABLE([frame-pointer],
386    AS_HELP_STRING([--enable-frame-pointer],
387                   [Compile with frame pointer, useful for profiling, default: NO]),
388    [],
389    [enable_frame_pointer=no])
390AS_IF([test "x$enable_frame_pointer" = xyes],
391      [ADD_COMPILER_FLAG_IF_SUPPORTED([-fno-omit-frame-pointer],
392                                      [-fno-omit-frame-pointer],
393                                      [AC_LANG_SOURCE([[int main(int argc, char** argv){return 0;}]])],
394                                      [AS_MESSAGE([compiling with frame pointer])],
395                                      [AS_MESSAGE([compiling with frame pointer is not supported])])],
396      [:])
397
398ADD_COMPILER_FLAG_IF_SUPPORTED([-funwind-tables],
399                               [-funwind-tables],
400                               [AC_LANG_SOURCE([[int main(int argc, char** argv){return 0;}]])],
401                               [AS_MESSAGE([compiling with unwind tables])],
402                               [AS_MESSAGE([compiling without unwind tables])])
403
404
405#
406# Check for C++ support
407#
408CHECK_CXX_COMP()
409
410
411#
412# Check for C++11 support
413#
414AC_MSG_CHECKING([c++11 support])
415AC_LANG_PUSH([C++])
416SAVE_CXXFLAGS="$CXXFLAGS"
417CXX11FLAGS="-std=c++11"
418CXXFLAGS="$CXXFLAGS $CXX11FLAGS"
419AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <iostream>
420					#include <string>
421					int main(int argc, char** argv) {
422						std::to_string(1);
423						return 0;
424					} ]])],
425                  [AC_MSG_RESULT([yes])
426                   AC_SUBST([CXX11FLAGS])
427                   cxx11_happy=yes],
428                  [AC_MSG_RESULT([no])
429                   cxx11_happy=no])
430CXXFLAGS="$SAVE_CXXFLAGS"
431AC_LANG_POP
432AM_CONDITIONAL([HAVE_CXX11], [test "x$cxx11_happy" != xno])
433
434
435#
436# Check for GNU++11 support
437#
438AC_MSG_CHECKING([gnu++11 support])
439AC_LANG_PUSH([C++])
440
441SAVE_CXXFLAGS="$CXXFLAGS"
442CXX11FLAGS="-std=gnu++11"
443CXXFLAGS="$CXXFLAGS $CXX11FLAGS"
444AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <iostream>
445					#include <string>
446					int main(int argc, char** argv) {
447						int a;
448						typeof(a) b = 0;
449						std::to_string(1);
450						return 0;
451					} ]])],
452                  [AC_MSG_RESULT([yes])
453                   AC_SUBST([CXX11FLAGS])
454                   gnuxx11_happy=yes],
455                  [AC_MSG_RESULT([no])
456                   gnuxx11_happy=no])
457CXXFLAGS="$SAVE_CXXFLAGS"
458AM_CONDITIONAL([HAVE_GNUXX11], [test "x$gnuxx11_happy" != xno])
459
460AC_CHECK_DECL(_GLIBCXX_NOTHROW, have_glibcxx_nothrow=yes,
461              have_glibcxx_nothrow=no, [[#include <exception>]])
462AM_CONDITIONAL([HAVE_GLIBCXX_NOTHROW], [test "x$have_glibcxx_nothrow" = xyes])
463
464AC_LANG_POP
465
466
467#
468# PGI specific switches
469#
470# --diag_suppress 181  - Suppress incorrect printf format for PGI18 compiler. TODO: remove it after compiler fix
471# --diag_suppress 1215 - Suppress deprecated API warning for PGI18 compiler
472# --diag_suppress 1901 - Use of a const variable in a constant expression is nonstandard in C
473ADD_COMPILER_FLAGS_IF_SUPPORTED([[--display_error_number],
474                                 [--diag_suppress 181],
475                                 [--diag_suppress 1215],
476                                 [--diag_suppress 1901]],
477                                [AC_LANG_SOURCE([[int main(int argc, char **argv){return 0;}]])])
478
479
480#
481# Check if "-pedantic" flag is supported
482#
483CHECK_COMPILER_FLAG([-pedantic], [-pedantic],
484                    [AC_LANG_SOURCE([[int main(int argc, char** argv){return 0;}]])],
485                    [CFLAGS_PEDANTIC="$CFLAGS_PEDANTIC -pedantic"],
486                    [])
487
488
489#
490# Add strict compilation flags
491#
492ADD_COMPILER_FLAGS_IF_SUPPORTED([[-Wno-missing-field-initializers],
493                                 [-Wno-unused-parameter],
494                                 [-Wno-unused-label],
495                                 [-Wno-long-long],
496                                 [-Wno-endif-labels],
497                                 [-Wno-sign-compare],
498                                 [-Wno-multichar],
499                                 [-Wno-deprecated-declarations],
500                                 [-Winvalid-pch]],
501                                [AC_LANG_SOURCE([[int main(int argc, char **argv){return 0;}]])])
502
503
504#
505# Set C++ optimization/debug flags to be the same as for C
506#
507BASE_CXXFLAGS="$BASE_CFLAGS"
508
509
510#
511# Add strict flags supported by C compiler only
512# NOTE: This must be done after setting BASE_CXXFLAGS
513#
514ADD_COMPILER_FLAGS_IF_SUPPORTED([[-Wno-pointer-sign],
515                                 [-Werror-implicit-function-declaration],
516                                 [-Wno-format-zero-length],
517                                 [-Wnested-externs],
518                                 [-Wshadow]],
519                                [AC_LANG_SOURCE([[int main(int argc, char **argv){return 0;}]])])
520
521
522AC_SUBST([BASE_CFLAGS])
523AC_SUBST([BASE_CXXFLAGS])
524AC_SUBST([CFLAGS_PEDANTIC])
525
526
527#
528# Set common C preprocessor flags
529#
530BASE_CPPFLAGS="-DCPU_FLAGS=\"$OPT_CFLAGS\""
531BASE_CPPFLAGS="$BASE_CPPFLAGS -I\${abs_top_srcdir}/src"
532BASE_CPPFLAGS="$BASE_CPPFLAGS -I\${abs_top_builddir}"
533BASE_CPPFLAGS="$BASE_CPPFLAGS -I\${abs_top_builddir}/src"
534AC_SUBST([BASE_CPPFLAGS], [$BASE_CPPFLAGS])
535