[Tarantool-patches] [PATCH] cmake: add LTO support for building luajit

Timur Safin tsafin at tarantool.org
Thu Jun 25 12:45:14 MSK 2020


: From: Tarantool-patches <tarantool-patches-bounces at dev.tarantool.org> On
: Subject: Re: [Tarantool-patches] [PATCH] cmake: add LTO support for
: building luajit
: 
: I vote to use the same build tools and flags that CMake uses to build
: files under its control, because otherwise we would write the same logic
: again. It may be not as accurate as one that CMake provides (see example
: below). It may become outdated in a future. And, last but not least,
: duplicated code is painful to maintain.
: 

I've looked into cmake IPO implementation for different compilers, and essentially they set these 5 variables if asked for IPO:

CMAKE_${lang}_COMPILE_OPTIONS_IPO
CMAKE_${lang}_LINK_OPTIONS_IPO
CMAKE_${lang}_ARCHIVE_CREATE_IPO
CMAKE_${lang}_ARCHIVE_APPEND_IPO
CMAKE_${lang}_ARCHIVE_FINISH_IPO

For C, CXX and ASM as ${lang}

So indeed, propagating those relevant variables down to luajit make variables 
seems adequate approach and flexible enough to all supported by cmake compilers

: I think it would be good to expose related build tool names and flags
: from cmake/lto.cmake and use them in cmake/luajit.cmake. I implemented
: the former part (I would even left STATUS messages as is, they provide
: useful information):
: 
:  | diff --git a/cmake/lto.cmake b/cmake/lto.cmake
:  | index 95ade75f4..79b908e26 100644
:  | --- a/cmake/lto.cmake
:  | +++ b/cmake/lto.cmake
:  | @@ -90,8 +90,40 @@ if (NOT TARGET_OS_DARWIN)
:  |      endif()
:  |  endif()
:  |
:  | -# gh-3742: investigate LTO warnings.
:  | -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wno-lto-type-
: mismatch")
:  | +# {{{ Expose build tools and flags
:  | +#
:  | +# It is convenient for building non-cmake targets with the same
:  | +# flags as we use for sources under CMake control.
:  | +#
:  | +# It leans on uncodumented variables that are set in the following
:  | +# CMake modules: Compiler/GNU.cmake and Compiler/Clang.cmake.
:  | +
:  | +# CFLAGS_LTO (list)
:  | +set(CFLAGS_LTO ${CMAKE_C_COMPILE_OPTIONS_IPO})
:  | +message(STATUS "CFLAGS_LTO: ${CFLAGS_LTO}")
:  |
:  | +# LDFLAGS_LTO (list)
:  | +set(LDFLAGS_LTO ${CMAKE_C_LINK_OPTIONS_IPO})
:  | +# FIXME: gh-3742: investigate LTO warnings.
:  | +list(APPEND LDFLAGS_LTO -Wno-lto-type-mismatch)
:  | +message(STATUS "LDFLAGS_LTO: ${LDFLAGS_LTO}")
:  | +
:  | +# AR_LTO (string)
:  | +#
:  | +# Note: Platform/Linux-Intel.cmake and Platform/Windows-MSVC.cmake
:  | +# set CMAKE_C_CREATE_STATIC_LIBRARY_IPO, but not
:  | +# CMAKE_C_ARCHIVE_CREATE_IPO. So this snippet is only for GCC and
:  | +# clang.
:  | +set(_ar_command ${CMAKE_C_ARCHIVE_CREATE_IPO})
:  | +separate_arguments(_ar_command)
:  | +list(GET _ar_command 0 AR_LTO)
:  | +unset(_ar_command)
:  | +message(STATUS "AR_LTO: ${AR_LTO}")
:  | +
:  | +# }}}
:  | +
:  | +# Set build tools and flags for files that are built using CMake.
:  | +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wno-lto-type-
: mismatch")
:  |  set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
:  | +
:  |  message(STATUS "Enabling LTO: TRUE")
: 
: Olga, Igor, what do you think about this way?

Looks like this is already applied to the branch, and works the 
as expected.

Here is the theory how to make sure that .o files contain necessary
information for inter-procedure optimizations:

1. For clang it's simple - .o is not ELF file, but rather LLVM IR (bc) file

```
tsafin at M1BOOK6319:~/tarantool/build_lto$ file ./third_party/luajit/src/lj_opt_sink.o
./third_party/luajit/src/lj_opt_sink.o: LLVM IR bitcode
```

we are ok then

2. For gcc it's more complicated - .o file is still ELF file but should
contain GIMPLE IR code in the special sections .gnu.lto.*

```
tsafin at M1BOOK6319:~/tarantool/build_lto$ file  ./third_party/luajit/src/lj_trace.o
./third_party/luajit/src/lj_trace.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

tsafin at M1BOOK6319:~/tarantool/build_lto$ readelf -a ./third_party/luajit/src/lj_trace.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          82944 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         48
  Section header string table index: 47

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000000  0000000000000000  AX       0     0     1
  [ 2] .data             PROGBITS         0000000000000000  00000040
       0000000000000000  0000000000000000  WA       0     0     1
  [ 3] .bss              NOBITS           0000000000000000  00000040
       0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .gnu.lto_.profile PROGBITS         0000000000000000  00000040
       000000000000000e  0000000000000000   E       0     0     1
  [ 5] .gnu.lto_.icf.bee PROGBITS         0000000000000000  0000004e
       00000000000000ca  0000000000000000   E       0     0     1
  [ 6] .gnu.lto_.jmpfunc PROGBITS         0000000000000000  00000118
       00000000000004fb  0000000000000000   E       0     0     1
  [ 7] .gnu.lto_.inline. PROGBITS         0000000000000000  00000613
       0000000000000524  0000000000000000   E       0     0     1
  [ 8] .gnu.lto_.purecon PROGBITS         0000000000000000  00000b37
       000000000000004b  0000000000000000   E       0     0     1
  [ 9] .gnu.lto_penalty_ PROGBITS         0000000000000000  00000b82
       0000000000000684  0000000000000000   E       0     0     1
  [10] .gnu.lto_trace_fi PROGBITS         0000000000000000  00001206
       0000000000000595  0000000000000000   E       0     0     1
  [11] .gnu.lto_trace_sa PROGBITS         0000000000000000  0000179b
       0000000000000611  0000000000000000   E       0     0     1
  [12] .gnu.lto_trace_st PROGBITS         0000000000000000  00001dac
       0000000000000d49  0000000000000000   E       0     0     1
  [13] .gnu.lto_trace_ex PROGBITS         0000000000000000  00002af5
       0000000000000255  0000000000000000   E       0     0     1
  [14] .gnu.lto_trace_un PROGBITS         0000000000000000  00002d4a
       00000000000004f9  0000000000000000   E       0     0     1
  [15] .gnu.lto_trace_fl PROGBITS         0000000000000000  00003243
       000000000000050c  0000000000000000   E       0     0     1
  [16] .gnu.lto_trace_ex PROGBITS         0000000000000000  0000374f
       00000000000004cc  0000000000000000   E       0     0     1
  [17] .gnu.lto_lj_trace PROGBITS         0000000000000000  00003c1b
       000000000000031f  0000000000000000   E       0     0     1
  [18] .gnu.lto_lj_trace PROGBITS         0000000000000000  00003f3a
       0000000000000291  0000000000000000   E       0     0     1
  [19] .gnu.lto_lj_trace PROGBITS         0000000000000000  000041cb
       000000000000024a  0000000000000000   E       0     0     1
  [20] .gnu.lto_lj_trace PROGBITS         0000000000000000  00004415
       000000000000047e  0000000000000000   E       0     0     1
  [21] .gnu.lto_lj_trace PROGBITS         0000000000000000  00004893
       0000000000000429  0000000000000000   E       0     0     1
  [22] .gnu.lto_lj_trace PROGBITS         0000000000000000  00004cbc
       00000000000004a7  0000000000000000   E       0     0     1
  [23] .gnu.lto_lj_trace PROGBITS         0000000000000000  00005163
       00000000000001f3  0000000000000000   E       0     0     1
  [24] .gnu.lto_lj_trace PROGBITS         0000000000000000  00005356
       00000000000002a9  0000000000000000   E       0     0     1
  [25] .gnu.lto_lj_trace PROGBITS         0000000000000000  000055ff
       0000000000000840  0000000000000000   E       0     0     1
  [26] .gnu.lto_trace_st PROGBITS         0000000000000000  00005e3f
       0000000000000be5  0000000000000000   E       0     0     1
  [27] .gnu.lto_trace_st PROGBITS         0000000000000000  00006a24
       000000000000030c  0000000000000000   E       0     0     1
  [28] .gnu.lto_trace_ab PROGBITS         0000000000000000  00006d30
       0000000000001335  0000000000000000   E       0     0     1
  [29] .gnu.lto_trace_st PROGBITS         0000000000000000  00008065
       0000000000000f5b  0000000000000000   E       0     0     1
  [30] .gnu.lto_lj_trace PROGBITS         0000000000000000  00008fc0
       0000000000000387  0000000000000000   E       0     0     1
  [31] .gnu.lto_lj_trace PROGBITS         0000000000000000  00009347
       000000000000055c  0000000000000000   E       0     0     1
  [32] .gnu.lto_lj_trace PROGBITS         0000000000000000  000098a3
       00000000000003ed  0000000000000000   E       0     0     1
  [33] .gnu.lto_trace_ho PROGBITS         0000000000000000  00009c90
       000000000000051c  0000000000000000   E       0     0     1
  [34] .gnu.lto_lj_trace PROGBITS         0000000000000000  0000a1ac
       00000000000001ef  0000000000000000   E       0     0     1
  [35] .gnu.lto_lj_trace PROGBITS         0000000000000000  0000a39b
       000000000000041c  0000000000000000   E       0     0     1
  [36] .gnu.lto_lj_trace PROGBITS         0000000000000000  0000a7b7
       0000000000000251  0000000000000000   E       0     0     1
  [37] .gnu.lto_lj_trace PROGBITS         0000000000000000  0000aa08
       0000000000000f22  0000000000000000   E       0     0     1
  [38] .gnu.lto_.symbol_ PROGBITS         0000000000000000  0000b92a
       00000000000003cb  0000000000000000   E       0     0     1
  [39] .gnu.lto_.refs.be PROGBITS         0000000000000000  0000bcf5
       000000000000001b  0000000000000000   E       0     0     1
  [40] .gnu.lto_.decls.b PROGBITS         0000000000000000  0000bd10
       000000000000769a  0000000000000000   E       0     0     1
  [41] .gnu.lto_.symtab. PROGBITS         0000000000000000  000133aa
       0000000000000465  0000000000000000   E       0     0     1
  [42] .gnu.lto_.opts    PROGBITS         0000000000000000  0001380f
       00000000000000d1  0000000000000000   E       0     0     1

...
```


So it looks LGTM at the moment (once been rebased)

Timur



More information about the Tarantool-patches mailing list