Copyright
Copyright © José
Luis Lara Carrascal 2012-2023 
Sumario
Introducción
Instalación
Configurar el sistema para el uso de Clang
Optimizaciones de CPU para Clang
Niveles de optimización soportados por Clang
Optimizaciones adicionales para Clang
LLD - El enlazador dinámico de LLVM
Libc++ - La librería estándar de C++ de LLVM
Compilar programas con Clang
Comparativa de resultados de optimización entre Clang y GCC
El estándar de lenguaje de programación predefinido de C++, a partir de Clang 6
Enlaces
Introducción
Clang es un software creado para proveer al compilador LLVM de una interfaz para poder compilar código escrito en C, C++, Objective C y Objective C++. Compatible con GCC,
es más rápido y utiliza menos memoria que este
último, aunque no soporta de momento, todas las
características de GCC. En este manual trataremos su instalación y la de LLVM,
además de explicar la forma de configurar el sistema para su uso, y las diferencias respecto a GCC,
en lo que concierne a las optimizaciones de procesador. A partir de la
publicación de este manual, todos los manuales de la web que
sean compatibles con Clang,
incluirán la correspondiente información para su
uso, tomando como referencia la instalación tratada en este
manual. Desde el 2 de mayo de 2018, el manual se ha actualizado a una
instalación en un sistema de 64 bits multiarquitectura.
Instalación
Dependencias
Herramientas de
Compilación
Entre paréntesis la
versión con la que se ha compilado Clang
para la elaboración de este documento.
* GCC - (12.2.0) o Clang - (15.0.6)
* CMake - (3.25.1)
* Ninja - (1.11.1)
* Pkg-config - (0.29.2)
Librerías
de Desarrollo
* Binutils - (2.39)
* Elfutils - (0.187)
* Libffi - (3.4.4)
* Libxml2 - (2.10.3)
* Ncurses - (6.4)
* Zlib - (1.2.13)
Intérpretes de Lenguaje de Programación
* Perl - (5.36.0)
* Python - (3.11.1)
Pygments - (2.14.0)
PyYAML - (6.0)
Aplicaciones
* Sphinx - (6.1.3)
Descarga
llvm-15.0.7.tar.xz
Firma Digital 
llvm-15.0.7.tar.xz.asc
Verificar la firma digital del paquete
$ gpg --import manualinux.asc
$ gpg --verify llvm-15.0.7.tar.xz.asc llvm-15.0.7.tar.xz
|
Optimizaciones
$ export
{C,CXX}FLAGS='-O3 -march=znver3 -mtune=znver3'
|
Donde pone znver3
se indica el procesador respectivo de cada sistema
seleccionándolo de la siguiente tabla: |
Nota informativa sobre las optimizaciones para GCC
|
* La opción '-march=' establece el procesador mínimo con el que funcionará el programa compilado, la opción '-mtune=' el procesador específico para el que será optimizado.
* Los valores separados por comas, son equivalentes, es decir, que lo mismo da poner '-march=k8' que '-march=athlon64'.
* En versiones de GCC 3.2 e inferiores se utiliza la opción '-mcpu=' en lugar de '-mtune='.
|
Nota informativa sobre las optimizaciones para Clang
|
* La opción '-mtune=' está soportada a partir de la versión 3.4 de Clang.
* Los valores de color azul no son compatibles con Clang.
* Las filas con el fondo de color amarillo son valores exclusivos de Clang y, por lo tanto, no son aplicables con GCC.
|
Valores |
CPU |
Genéricos |
generic |
Produce un código
binario optimizado para la mayor parte de procesadores existentes.
Utilizar este valor si no sabemos el nombre del procesador que
tenemos en nuestro equipo. Este valor sólo es aplicable en
la opción '-mtune=', si utilizamos GCC. Esta opción está disponible a
partir de GCC 4.2. |
native |
Produce un código
binario optimizado para el procesador que tengamos en nuestro sistema,
siendo éste detectado utilizando la instrucción cpuid.
Procesadores antiguos pueden no ser detectados utilizando este valor.
Esta opción está disponible a
partir de GCC 4.2. |
x86-64 |
Procesador genérico con extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 1.9. |
x86-64-v2 |
Procesador
genérico con con soporte de instrucciones X86-64 (MMX, SSE,
SSE2, LAHFSAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3) y extensiones
64-bit. Esta opción está disponible a partir de GCC 11 y Clang 12. |
x86-64-v3 |
Procesador
genérico con con soporte de instrucciones X86-64 (MMX, SSE,
SSE2, LAHFSAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3, AVX, AVX2, F16C,
FMA, LZCNT, MOVBE, XSAVE, XSAVEC, FMA4) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11 y Clang 12. |
x86-64-v4 |
Procesador
genérico con con soporte de instrucciones X86-64 (MMX, SSE,
SSE2, LAHFSAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3, AVX, AVX2, F16C,
FMA, LZCNT, MOVBE, XSAVE, XSAVEC, AVX512*, FMA4) y extensiones 64-bit.
Esta opción está disponible a partir de GCC 11 y Clang 12. |
Intel |
alderlake |
Intel Alderlake con
soporte de instrucciones x86-64 (MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND,
FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC,
XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD,
AVX512VNNI, AVX512BF16, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD,
CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16,
AMX-TILE, AMX-INT8, AVX-VNNI) y extensiones 64-bit. Esta opción
está disponible a partir de GCC 11 y Clang 12. |
atom |
Intel Atom
con soporte de instrucciones MMX, SSE, SSE2, SSE3, SSSE3 y
extensiones 64-bit. Esta opción está disponible
desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición bonnell. |
bonnell |
Intel Bonnell con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3 y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
broadwell |
Intel Broadwell con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT,
AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2,
F16C, RDSEED, ADCX, PREFETCHW y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9 y Clang 3.6. |
cannonlake |
Intel Cannonlake Server con soporte de instrucciones MOVBE, MMX, SSE,
SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL,
FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW,
CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
AVX512CD, AVX512VBMI, AVX512IFMA, SHA, UMIP y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 3.9. |
cascadelake |
Intel Cascadelake con
soporte de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1,
SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI,
BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES,
AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI y
extensiones 64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 8. |
cooperlake |
Intel
Cooper Lake con
soporte de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI,
BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB,
AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI, AVX512BF16 y
extensiones 64-bit. Esta opción está disponible a
partir de GCC 10 y Clang 9. |
core2 |
Intel Core2
con soporte de instrucciones MMX, SSE, SSE2, SSE3, SSSE3 y
extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.3. |
core-avx2 |
Intel Core (Haswell). Esta opción está disponible desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición haswell. |
core-avx-i |
Intel Core (ivyBridge)
con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, AVX, AES, PCLMUL, FSGSBASE, RDRND, F16C y
extensiones 64-bit. Esta opción está disponible
desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición ivybridge. |
corei7 |
Intel Core i7 con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1 y SSE4.2 y extensiones 64-bit. Soporta también los procesadores Intel
Core i3 e i5. Esta opción está disponible desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición nehalem. |
corei7-avx |
Intel Core i7 con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, AVX, AES y PCLMUL y
extensiones 64-bit. Soporta también los
procesadores Intel Core i3 e i5. Esta opción está disponible desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición sandybridge. |
goldmont |
Intel Goldmont con soporte
de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2,
POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE y extensiones
64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 5. |
goldmont-plus |
Intel Goldmont Plus con
soporte de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1,
SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, PTWRITE,
RDPID, SGX, UMIP y extensiones 64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 7. |
haswell |
Intel Haswell con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT,
AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2,
F16C y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
i386 |
Intel i386.
|
i486 |
Intel i486. |
i586, pentium |
Intel Pentium sin soporte de instrucciones MMX. |
i686 |
Produce un código binario optimizado para la mayor parte de
procesadores compatibles con la serie 80686 de Intel. Todos los actuales lo son. |
icelake-client |
Intel Icelake Client con soporte de instrucciones MOVBE, MMX, SSE,
SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL,
FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW,
CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI,
AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ,
VAES y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 7. |
icelake-server |
Intel Icelake Server con soporte de instrucciones MOVBE, MMX, SSE,
SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL,
FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW,
CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI,
AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ,
VAES, PCONFIG, WBNOINVD y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 7. |
intel |
Intel Haswell y Silvermont. Este valor sólo es aplicable en
la opción '-mtune='. Esta opción está disponible a partir
de GCC 4.9. |
ivybridge |
Intel Ivy Bridge con soporte de instrucciones
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX,
AES, PCLMUL, FSGSBASE, RDRND, F16C y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
knl |
Intel Knights Landing con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2,
AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX,
PREFETCHW, AVX512F, AVX512PF, AVX512ER y extensiones 64-bit. Esta opción está disponible a partir
de GCC 5 y Clang 3.4. |
knm |
Intel Knights Mill con soporte de instrucciones MOVBE, MMX, SSE, SSE2,
SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, AVX512F,
AVX512PF, AVX512ER, AVX512CD, AVX5124VNNIW, AVX5124FMAPS,
AVX512VPOPCNTDQ y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 6. |
lakemont |
Intel Quark Lakemont MCU, basado en el procesador Intel Pentium. Esta opción está disponible a partir
de GCC 6 y Clang 3.9. |
nehalem |
Intel Nehalem con soporte de instrucciones MMX,
SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT y extensiones
64-bit. Esta opción está disponible a partir
de GCC 4.9. |
nocona |
Versión mejorada de Intel Pentium4 con soporte de instrucciones MMX, SSE, SSE2, SSE3 y extensiones 64-bit. |
penryn |
Intel
Penryn con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3 y SSE4.1. |
pentiumpro |
Intel PentiumPro. |
pentium2 |
Intel Pentium2 basado en PentiumPro con soporte de instrucciones MMX. |
pentium3, pentium3m |
Intel Pentium3 basado en PentiumPro con soporte de instrucciones MMX y SSE. |
pentium4, pentium4m |
Intel Pentium4 con soporte de instrucciones MMX, SSE y SSE2. |
pentium-m |
Versión de bajo
consumo de Intel Pentium3 con soporte de instrucciones MMX, SSE y SSE2.
Utilizado por los portátiles Centrino. |
pentium-mmx |
Intel PentiumMMX basado en Pentium con soporte de instrucciones MMX. |
prescott |
Versión mejorada de Intel Pentium4 con soporte de instrucciones MMX, SSE, SSE2 y SSE3. |
rocketlake |
Intel Rocket Lake con
soporte de instrucciones x86-64 (MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND,
FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC,
XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI,
AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ,
AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11. |
sandybridge |
Intel Sandy Bridge con soporte de instrucciones
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX,
AES, PCLMUL y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9 y Clang 3.6. |
sapphirerapids |
Intel Sapphire Rapids
con soporte de instrucciones x86-64 (MOVBE, MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT,
XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD,
AVX512VNNI, AVX512BF16, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD,
CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16,
AMX-TILE, AMX-INT8 and AVX-VNNI) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11 y Clang 12. |
silvermont |
Intel Silvermont con soporte de instrucciones
MOVBE, MMX, SSE, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1,
SSE4.2, POPCNT, AES, PCLMU, RDRND y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9 y Clang 3.6. |
skylake |
Intel Skylake con soporte de instrucciones MOVBE, MMX, SSE, SSE2,
SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT,
XSAVEC, XSAVES y extensiones 64-bit. Esta opción está disponible a partir
de GCC 6 y Clang 3.6. |
skylake-avx512 |
Intel Skylake Server
con soporte de instrucciones MOVBE, MMX, SSE, SSE2,
SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT,
XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD y
extensiones 64-bit. Esta opción está disponible a partir
de GCC 6 y Clang 3.9. |
tigerlake |
Intel
Tiger Lake con soporte de instrucciones OVBE, MMX, SSE, SSE2, SSE3,
SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND,
FMA, BMI,
BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES,
AVX512F,
AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA,
CLWB, UMIP,
RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI,
VPCLMULQDQ,
VAES, PCONFIG, WBNOINVD, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT y
extensiones 64-bit. Esta opción está disponible a partir
de GCC 10 y Clang 10. |
tremont |
Intel Tremont con soporte
de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2,
POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, PTWRITE, RDPID,
SGX, UMIP, GFNI-SSE, CLWB, ENCLV y extensiones 64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 7. |
westmere |
Intel Westmere con soporte de instrucciones
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES,
PCLMUL y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
yonah |
Procesadores
basados en la microarquitectura de Pentium M, con soporte de
instrucciones MMX, SSE, SSE2 y SSE3. |
AMD |
amdfam10, barcelona |
Procesadores basados en
AMD Family 10h core con soporte de instrucciones x86-64 (MMX, SSE,
SSE2, SSE3, SSE4A, 3DNow!, enhanced 3DNow!, ABM y extensiones
64-bit). Esta opción está disponible a partir de GCC 4.3. La definición barcelona está disponible a partir de Clang 3.6. |
athlon, athlon-tbird |
AMD Athlon con soporte de instrucciones MMX, 3DNow!, enhanced 3DNow! y SSE prefetch. |
athlon4, athlon-xp, athlon-mp |
Versiones mejoradas de AMD Athlon con soporte de instrucciones MMX, 3DNow!, enhanced 3DNow! y full SSE. |
bdver1 |
Procesadores basados en
AMD Family 15h core con soporte de instrucciones x86-64 (FMA4, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE,
SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM y extensiones
64-bit). Esta opción está disponible a partir
de GCC 4.7. |
bdver2 |
Procesadores basados en
AMD Family 15h core con soporte de instrucciones x86-64 (BMI, TBM, F16C, FMA, LWP, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE,
SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM y extensiones
64-bit). Esta opción está disponible a partir
de GCC 4.7. |
bdver3 |
Procesadores basados en
AMD Family 15h core con soporte de instrucciones x86-64 (FMA4, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE,
SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM y extensiones
64-bit). Esta opción está disponible a partir
de GCC 4.8 y Clang 3.4. |
bdver4 |
Procesadores basados en AMD Family 15h core con soporte de instrucciones x86-64
(BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP,
LWP, AES, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A,
SSSE3, SSE4.1, SSE4.2, ABM y extensiones 64-bit). Esta opción está
disponible a partir de GCC 4.9 y Clang 3.5. |
btver1 |
Procesadores basados en
AMD Family 14h core con soporte de instrucciones x86-64 (MMX, SSE,
SSE2, SSE3, SSE4A, CX16, ABM y extensiones 64-bit). Esta opción está disponible a partir
de GCC 4.6. |
btver2 |
Procesadores basados en
AMD Family 16h core con soporte de instrucciones x86-64 (MOVBE, F16C,
BMI, AVX, PCL_MUL, AES, SSE4.2, SSE4.1, CX16, ABM, SSE4A, SSSE3, SSE3,
SSE2, SSE, MMX y extensiones 64-bit). Esta opción
está disponible a partir
de GCC 4.8. |
geode |
AMD integrado con soporte de instrucciones MMX y 3DNow!. Esta opción está disponible a partir de GCC 4.3. |
k6 |
AMD K6 con soporte de instrucciones MMX. |
k6-2, k6-3 |
Versiones mejoradas de AMD K6 con soporte de instrucciones MMX y 3DNow!. |
k8, opteron, athlon64, athlon-fx |
Procesadores basados en
AMD K8 core con soporte de instrucciones x86-64 (MMX, SSE, SSE2,
3DNow!, enhanced 3DNow! y extensiones 64-bit). |
k8-sse3, opteron-sse3, athlon64-sse3 |
Versiones mejoradas de
AMD K8 core con soporte de instrucciones SSE3. Esta opción
está disponible a partir de GCC 4.3. |
znver1 |
Procesadores basados en
AMD Family 17h core con soporte de instrucciones x86-64 (BMI, BMI2,
F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES,
PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1,
SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT y extensiones
64-bit). Esta opción está disponible a partir de GCC 6 y Clang 4. |
znver2 |
Procesadores basados en
AMD Family 17h core con soporte de instrucciones x86-64 (BMI, BMI2,
,CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA,
CLZERO, AES, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3,
SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT y extensiones
64-bit). Esta opción está disponible a partir de GCC 9 y Clang 9. |
znver3 |
Procesadores basados en
AMD Family 19h core con soporte de instrucciones x86-64 (BMI, BMI2,
CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA,
CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3,
SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID,
WBNOINVD, PKU, VPCLMULQDQ, VAES) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11 y Clang 12. |
Optimizaciones adicionales
Optimizaciones adicionales |
GCC |
Graphite
|
$ export {C,CXX}FLAGS+=' -floop-interchange -ftree-loop-distribution -floop-strip-mine -floop-block' |
Clang |
New Pass Manager |
$ export {C,CXX}FLAGS+=' -fexperimental-new-pass-manager' |
Polly |
$ export {C,CXX}FLAGS+=' -O3 -mllvm -polly -mllvm -polly-vectorizer=stripmine' |
Parámetros adicionales para la versión de 32 bits
Establecer la variable de entorno adecuada para pkg-config en sistemas de 64 bits multiarquitectura |
$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/share/pkgconfig:$PKG_CONFIG_PATH |
Establecer la ruta de búsqueda de directorios de librerías en sistemas de 64 bits multiarquitectura |
$ export LDFLAGS+=' -L/usr/lib -L/usr/local/lib -L/opt/gcc12/lib' |
Establecer el RPATH correspondiente si utilizamos una versión de GCC que no es la principal del sistema |
$ export LDFLAGS+=" -Wl,-rpath,/opt/gcc12/lib -lstdc++" |
Sustituir /opt/gcc12/lib
por la ruta de instalación alternativa que cada usuario tenga en
su sistema.
|
Establecer
la variable de entorno de arquitectura de procesador requerida en
sistemas de 64 bits multiarquitectura basados en el CLFS |
$ export USE_ARCH=32 |
Establecer la variable de entorno de uso de compilador en modo de 32 bits, en sistemas de 64 bits multiarquitectura |
GCC |
$ export CC="gcc -m32" CXX="g++ -m32"
|
Clang |
$ export CC="clang -m32" CXX="clang++ -m32"
|
Parámetros adicionales para la versión de 64 bits
Establecer el RPATH correspondiente si utilizamos una versión de GCC que no es la principal del sistema |
$ export LDFLAGS+=" -Wl,-rpath,/opt/gcc12/lib64 -lstdc++" |
Sustituir /opt/gcc12/lib64
por la ruta de instalación alternativa que cada usuario tenga en
su sistema.
|
Parámetros adicionales globales
Parámetros adicionales de eliminación de avisos en el proceso de compilación |
$ export {C,CXX}FLAGS+=' -w' |
Parámetros adicionales complementarios de la optimización LTO/ThinLTO |
GCC |
$ export AR=gcc-ar RANLIB=gcc-ranlib NM=gcc-nm |
Clang |
$ export AR=llvm-ar RANLIB=llvm-ranlib NM=llvm-nm |
Establecer el uso de enlazador dinámico para Mold |
$ export LDFLAGS+=' -fuse-ld=mold' |
Establecer el uso de enlazador dinámico para LLD |
Clang |
$ export LDFLAGS+=' -fuse-ld=lld' |
Optimizaciones complementarias LTO/ThinLTO de LLD |
$ export LDFLAGS+=' -Wl,--lto-aa-pipeline=globals-aa -Wl,--lto-newpm-passes=memcpyopt' |
Optimizaciones complementarias LTO de LLD |
$ export LDFLAGS+=" -Wl,--lto-partitions=$(nproc)" |
Optimizaciones complementarias ThinLTO de LLD |
$ export LDFLAGS+=" -Wl,--thinlto-jobs=$(nproc)" |
Extracción 
$ tar Jxvf llvm-15.0.7.tar.xz
$ cd llvm-15.0.7
|
Configuración de la versión de 32 bits
La compilación de la versión de 32 bits de LLVM
sólo es necesaria si tenemos pensado compilar la versión
de 32 bits de Mesa con
soporte de LLVM. A diferencia de GCC, LLVM no compila las
librerías de 32 bits en el mismo proceso de compilación,
en un sistema de 64 bits multiarquitectura.
$ mkdir build32; cd build32
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/llvm15 \
-DLLVM_TARGETS_TO_BUILD=X86 -DBUILD_SHARED_LIBS=ON -DLLVM_ENABLE_RTTI=ON \
-DLLVM_ENABLE_FFI=ON -DOCAMLFIND=null -DLLVM_CCACHE_BUILD=ON -G Ninja ../llvm |
Explicación de los
comandos
mkdir build32; cd build32 : Crea un directorio de
compilación para no compilar directamente en el directorio de las fuentes, y entramos en el mismo.
-DCMAKE_BUILD_TYPE=Release : Compila la versión optimizada de LLVM.
-DCMAKE_INSTALL_PREFIX=/opt/llvm15
: Instala LLVM en /opt/llvm15.
-DLLVM_TARGETS_TO_BUILD=X86 : Compila sólo el soporte de la arquitectura de procesador x86,
omitiendo otras como ARM, PowerPC, etc. Esto reduce el tiempo de
compilación y el tamaño del directorio de
instalación del compilador.
-DBUILD_SHARED_LIBS=ON
: Compila las librerías compartidas en lugar de las
estáticas.
-DLLVM_ENABLE_RTTI=ON : Parámetro requerido para poder compilar Mesa con soporte de LLVM con el sistema de compilación, Meson.
-DLLVM_ENABLE_FFI=ON : Activa el soporte de Libffi, librería de características similares a GMP.
-DOCAMLFIND=null : Al no tener el paquete una opción específica para desactivar la adaptación de LLVM para el lenguaje de programación OCaml, le indicamos una ruta nula al ejecutable ocamlfind,
para poder desactivar el soporte de esta dependencia. Si no tenemos
instalado OCaml en nuestro sistema, esto no hay que añadirlo.
-DLLVM_CCACHE_BUILD=ON : Activa el uso de Ccache
para compilar el paquete.
-G Ninja : Utiliza Ninja en lugar de GNU Make para compilar el paquete (opcional).
Parámetros de configuración opcionales
-DCMAKE_AR=$(which $AR) -DCMAKE_RANLIB=$(which $RANLIB) -DCMAKE_NM=$(which $NM) : Sincroniza las variables de entorno establecidas en el manual, relativas a los binarios ejecutables intermedios, gcc-ar, gcc-ranlib y gcc-nm, con los parámetros de configuración utilizados por CMake, relativos a los programas ar, ranlib y nm, para poder aplicar correctamente la optimización LTO. Se utiliza el comando which para buscar los ejecutables porque desde
hace ya varias versiones, CMake no establece correctamente la ruta al
ejecutable en cuestión. Esto no es necesario hacerlo, si compilamos el paquete con Clang.
-DLLVM_ENABLE_LTO=ON|Thin : Activa el uso de la optimización LTO,
tanto con GCC como con Clang, siempre en combinación con el
parámetro anteriormente descrito. Si
vamos a utilizar
Clang, muy recomendable hacer uso de ThinLTO en lugar de LTO,
estableciendo Thin en lugar de ON,
en el valor de este parámetro, para reducir el tiempo de
compilación del paquete.
-DLLVM_ENABLE_LLD=ON
: Este parámetro sólo es necesario si utilizamos la
optimización ThinLTO con Clang, y no tenemos configurado un
directorio caché para LLD en nuestro sistema, cuyo uso hemos
establecido con la correspondiente variable de entorno de uso de
enlazador dinámico para LLD. El proceso de configuración
creará uno en la raíz del directorio de
compilación con el nombre lto.cache
y almacenará en el mismo los archivos objeto que se generen en
el proceso de enlazado, evitando utilizar la memoria física del
sistema, si tenemos montado el directorio /tmp con el sistema de archivos, Tmpfs.
Si se establece LLD como enlazador dinámico, antes del comando
de configuración del paquete, esta opción no será
funcional.
-DLLVM_PARALLEL_LINK_JOBS=$(nproc)
: Establece el número de procesos en paralelo de enlazado (por
defecto es 2), tomando como referencia la información del
número de núcleos de nuestro procesador, proporcionada
por el sistema. Este parámetro sólo es aplicable con Ninja.
Usuarios con 4 GB de memoria RAM, o menos, abstenerse de utilizar todos
los núcleos que tenga su procesador, si este tiene 4 o
más núcleos. Como ejemplo personal (mi CPU anterior, Phenom II x4 965): 4 instancias de LLD
ejecutándose con 4 tareas cada una (-Wl,--thinlto-jobs=4'),
llega a consumir máximos de 4 GB de memoria RAM.
Si compilamos el paquete con Clang, estableciendo las correspondientes
variables de entorno de LLD, es recomendable establecer este
parámetro a 1, para evitar una sobrecarga de procesos de
compilación.
-DCMAKE_STRIP=/usr/bin/strip : Sustituye llvm-strip por strip,
en el caso de que compilemos el paquete con Clang. El segundo es
bastante mejor que el primero, a la hora de reducir el tamaño de
los binarios compilados.
Compilación
Parámetros de compilación opcionales
-v : Muestra más información en el proceso de compilación.
-j$(nproc) :
Establece el número de procesos de compilación en
paralelo, en función del número de
núcleos e hilos que tenga nuestro procesador, tomando como
referencia la información mostrada por el sistema con el comando
correspondiente. Si nuestro procesador es mononúcleo de un solo
hilo, no añadir esta opción.
Instalación como root de la versión de 32 bits
$ su
# ninja install/strip
# mv /opt/llvm15/bin/llvm-config{,-32}
# exit
$ cd ..
|
Explicación de los
comandos
mv /opt/llvm15/bin/llvm-config{,-32}
: Renombramos el ejecutable encargado de mostrar la
información sobre la ubicación de las librerías de
LLVM en los procesos de compilación en los que sea necesario su
uso, siguiendo el método utilizado por el CLFS.
Configuración de la versión de 64 bits
$ mkdir build64; cd build64
$ cmake -DLLVM_ENABLE_PROYECTS="clang;lld;polly;compiler-rt;\
libcxx;libcxxabi;libunwind;openmp" -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/llvm15 -DLLVM_TARGETS_TO_BUILD="X86;BPF" \
-DGCC_INSTALL_PREFIX=/opt/gcc12 -DLLVM_BINUTILS_INCDIR=/usr/include \
-DLLVM_BUILD_DOCS=ON -DLLVM_ENABLE_SPHINX=ON -DSPHINX_WARNINGS_AS_ERRORS=OFF \
-DLLVM_BUILD_LLVM_DYLIB=ON -DOCAMLFIND=null -DLLVM_LIBDIR_SUFFIX=64 \
-DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_FFI=ON -DLLVM_CCACHE_BUILD=ON \
-DLLVM_INSTALL_UTILS=ON -DLIB{,CXX,CXXABI,UNWIND,}_INSTALL_LIBRARY_DIR=/opt/llvm15/lib64 \
-G Ninja ../llvm |
Explicación de los
comandos
mkdir build64; cd build64 : Creamos un directorio de
compilación para no compilar directamente en el directorio de las fuentes, y entramos en el mismo.
-DLLVM_ENABLE_PROJECTS="clang;lld;polly;compiler-rt;libcxx;libcxxabi;libunwind;openmp":
Activa la compilación de los proyectos separados por punto
y coma, incluidos junto a
LLVM en el paquete proporcionado en este manual. Esta opción es
nueva a partir de la versión 14, ya que se ha modificado la
estructura de compilación del mismo. Además de estos
proyectos, el paquete incluye los siguientes: bolt, clang-tools-extra,
flang, libc, libcl, lldb, mlir y pstl, que podemos añadir si
así lo deseamos, a este parámetro de configuración.
-DCMAKE_BUILD_TYPE=Release : Compila la versión optimizada de LLVM.
-DCMAKE_INSTALL_PREFIX=/opt/llvm15
: Instala el compilador en /opt/llvm15.
-DGCC_INSTALL_PREFIX=/opt/gcc12 : Le indicamos la ruta de instalación de GCC, en el caso de que utilicemos otra versión diferente a la principal del sistema. Esto es necesario para que Clang encuentre las cabeceras C++ de GCC cuando tenga que compilar código escrito en C++.
-DLLVM_TARGETS_TO_BUILD="X86;BPF" : Compila sólo el soporte de la arquitectura de procesador x86,
omitiendo otras como ARM, PowerPC, etc. Esto reduce el tiempo de
compilación y el tamaño del directorio de
instalación del compilador. El soporte de BPF es requerido para la compilación del paquete v4l-utils.
-DLLVM_BINUTILS_INCDIR=/usr/include : Le indicamos la ruta al archivo de cabecera plugin-api.h, proporcionado por el paquete Binutils cuando se instala con soporte de plugins. Esta versión especial es requerida para poder compilar el plugin LLVM Gold, que nos permite poder disponer de la optimización LTO, en las compilaciones que realicemos con Clang.
-DLLVM_BUILD_DOCS=ON : Activa la creación e instalación de la documentación en formato HTML y páginas de manual de LLVM y Clang.
-DLLVM_ENABLE_SPHINX=ON : Utiliza el programa Sphinx para crear la documentación en formato HTML y páginas de manual de LLVM y Clang.
-DSPHINX_WARNINGS_AS_ERRORS=OFF : Evita que los avisos sean tratados como errores, al generar la documentación en formato HTML y páginas de manual de LLVM y Clang.
-DLLVM_BUILD_LLVM_DYLIB=ON:
Compila una librería única compartida de LLVM, a partir
de las estáticas, para poder enlazar contra la misma, paquetes
como las librerías Mesa.
-DOCAMLFIND=null : Al no tener el paquete una opción específica para desactivar la adaptación de LLVM para el lenguaje de programación OCaml, le indicamos una ruta nula al ejecutable ocamlfind,
para poder desactivar el soporte de esta dependencia. Si no tenemos
instalado OCaml en nuestro sistema, esto no hay que añadirlo.
-DLLVM_LIBDIR_SUFFIX=64 : Establece el nombre del directorio de las librerías de LLVM en lib64,
para que no sean sobreescritas en el proceso de instalación,
las librerías de la versión de 32 bits, ubicadas en /opt/llvm15/lib.
-DLLVM_ENABLE_RTTI=ON : Parámetro requerido para poder compilar Mesa con soporte de LLVM con el sistema de compilación, Meson.
-DLLVM_ENABLE_FFI=ON : Activa el soporte de Libffi, librería de características similares a GMP.
-DLLVM_CCACHE_BUILD=ON : Activa el uso de Ccache
para compilar el paquete. No es necesario si tenemos configurado Ccache
en nuestro sistema con el uso de los enlaces simbólicos
correspondientes.
-DLLVM_INSTALL_UTILS=ON : Instala las utilidades binarias FileCheck, count, lli-child-target, llvm-PerfectShutffle, not y yaml-bench
que, en el caso de FileCheck es requerido en la compilación de
algún paquete de código fuente, cuyo nombre ahora no
recuerdo. Estas utilidades se compilan por defecto, pero para
instalarlas hay que añadir esta variable al comando de
configuración del paquete.
-DLIB{,CXX,CXXABI,UNWIND,}_INSTALL_LIBRARY_DIR=/opt/llvm15/lib64
: Evita a partir de LLVM 15, que las librerías libc++,
libc++abi y libunwind, se instalen en el directorio
/opt/llvm15/lib64/x86_64-unknown-linux-gnu, ubicándolas en el directorio predefinido de siempre.
-G Ninja : Utiliza Ninja en lugar de GNU Make para compilar el paquete (opcional).
Parámetros de configuración opcionales
-DBUILD_SHARED_LIBS=ON
: Compila las librerías compartidas en lugar de las
estáticas. Esto, junto a la eliminación de los
símbolos innecesarios con el comando ninja install/strip,
reduce la ocupación del espacio en disco del paquete en
más de un 70 %. Como contrapartida, la pérdida de
rendimiento del compilador ronda el 15/20 % según el paquete a
compilar (no se ha probado con paquetes de gran tamaño), de
ahí que esta opción se haya convertido en opcional en
este manual. Sirva de ejemplo, la tabla que pongo a
continuación, tomando como referencia la compilación de Pekwm, con las opciones O3+CPU+Polly.
Tabla
de diferencias de tamaño entre una instalación
estática, una mixta y una compartida de LLVM 10, más el
tiempo de compilación que tarda Clang 10, según el modo
de instalación del compilador
|
Modo de instalación |
Ocupación de espacio en disco |
Parámetros aplicados |
Tiempo de compilación |
Estática |
1,3 GB |
O3+CPU+Polly |
18" |
Mixta [1] |
731,4 MB |
O3+CPU+Polly |
19" |
Compartida |
340,9 MB
|
O3+CPU+Polly |
23" |
[1]
Este es el modo que utiliza el BLFS,
enlazando las herramientas
(incluido Clang) contra la librería compartida de LLVM,
utilizando el parámetro -DLLVM_LINK_LLVM_DYLIB=ON. Al que le
tendremos que añadir el parámetro
-DCLANG_LINK_CLANG_DYLIB=OFF,
para que libclang-cpp se integre de forma estática en el binario
ejecutable clang-10, porque de lo contrario, el rendimiento de Clang es
el mismo que en una instalación compartida. Aún
así, como se puede ver en la tabla, sigue siendo ligeramente
más
lento que la instalación predefinida (Un segundo, en
informática y en Fórmula 1, es un mundo), porque clang-10
queda
enlazado contra la librería compartida de LLVM, en lugar de
hacerlo de forma estática como en la instalación
predefinida. |
Si se utiliza esta opción no hay que utilizar -DLLVM_BUILD_LLVM_DYLIB.
-DCMAKE_AR=$(which $AR) -DCMAKE_RANLIB=$(which $RANLIB) -DCMAKE_NM=$(which $NM) : Sincroniza las variables de entorno establecidas en el manual, relativas a los binarios ejecutables intermedios, gcc-ar, gcc-ranlib y gcc-nm, con los parámetros de configuración utilizados por CMake, relativos a los programas ar, ranlib y nm, para poder aplicar correctamente la optimización LTO. Se utiliza el comando which para buscar los ejecutables porque desde
hace ya varias versiones, CMake no establece correctamente la ruta al
ejecutable en cuestión. Esto no es necesario hacerlo, si compilamos el paquete con Clang.
-DLLVM_ENABLE_LTO=ON|Thin : Activa el uso de la optimización LTO,
tanto con GCC como con Clang, siempre en combinación con el
parámetro
anteriormente descrito. La reducción de los archivos binarios es
irrelevante, penalizado por el aumento de tamaño de las
librerías estáticas, lo que hace que el total de espacio
requerido aumente en más de 140 MB, si utilizamos la
optimización ThinLTO con Clang. La ganancia de velocidad (10/15
% en las comparativas de este manual) y el menor tamaño de los
binarios que genera el compilador, independientemente de la
optimización que se utilice, sí es relevante. Si
vamos a utilizar
Clang, muy recomendable hacer uso de ThinLTO en lugar de LTO,
estableciendo Thin en lugar de ON,
en el valor de este parámetro, para reducir el tiempo de
compilación del paquete.
-DLLVM_ENABLE_LLD=ON
: Este parámetro sólo es necesario si utilizamos la optimización
ThinLTO con Clang, y no tenemos configurado un directorio caché para
LLD en nuestro sistema, cuyo uso hemos establecido con la
correspondiente variable de entorno de uso de enlazador dinámico para
LLD. El proceso de configuración creará uno en la raíz del directorio
de compilación con el nombre lto.cache
y almacenará en el mismo los archivos objeto que se generen en el
proceso de enlazado, evitando utilizar la memoria física del sistema,
si tenemos montado el directorio /tmp con el sistema de archivos, Tmpfs.
Si se establece LLD como enlazador dinámico, antes del comando
de configuración del paquete, esta opción no será
funcional.
-DLLVM_PARALLEL_LINK_JOBS=$(nproc)
: Establece el número de procesos en paralelo de enlazado de los binarios (por defecto
es 2), tomando como referencia la información del
número de núcleos de nuestro procesador, proporcionada
por el sistema. Este parámetro sólo es aplicable con Ninja.
Usuarios
con 4 GB de memoria RAM, o menos, abstenerse de utilizar todos los
núcleos que tenga su procesador, si este tiene 4 o más
núcleos. Como ejemplo personal (mi CPU anterior, Phenom II
x4 965): 4 instancias de LLD ejecutándose con 4 tareas cada
una (-Wl,--thinlto-jobs=4'), llega a consumir máximos de 4 GB de
memoria RAM.
Si compilamos el paquete con Clang, estableciendo las correspondientes
variables de entorno de LLD, es recomendable establecer este
parámetro a 1, para evitar una sobrecarga de procesos de
compilación.
-DCMAKE_STRIP=/usr/bin/strip : Sustituye llvm-strip por strip,
en el caso de que compilemos el paquete con Clang. El segundo es
bastante mejor que el primero, a la hora de reducir el tamaño de
los binarios compilados.
Compilación
Parámetros de compilación opcionales
Instalación como root de la versión de 64 bits
$ su
# ninja install/strip
# mv /opt/llvm15/bin/llvm-config{,-64}
|
Explicación de los
comandos
mv /opt/llvm15/bin/llvm-config{,-64}
: Renombramos el ejecutable encargado de mostrar la
información sobre la ubicación de las librerías de
LLVM en los procesos de compilación en los que sea necesario su
uso, siguiendo el método utilizado por el CLFS.
Crear el binario ejecutable selector de arquitectura de procesador siguiendo el método del CLFS
Nos descargamos este archivo
y lo compilamos como root con el siguiente comando, para posteriormente
crear el enlace simbólico correspondiente para poder alternar de
una arquitectura a otra, en el uso de dependencias, en función
del proceso de compilación en curso.
# gcc multiarch_wrapper.c -o /opt/llvm15/bin/multiarch_wrapper
# ln -s multiarch_wrapper /opt/llvm15/bin/llvm-config
|
Cuando compilemos código de 32 bits, que necesite de las
dependencias de las librerías de 32 bits de LLVM, ejecutamos la
siguiente variable de entorno, antes de configurar los paquetes de
código fuente correspondientes.
Borrar los
directorios y archivos de instalación que hacen referencia a la
versión 15.0.6, sobrescrita por esta nueva versión
Hacer sólo esto si estamos actualizando desde la versión
anterior instalada siguiendo las instrucciones de este manual. Con el
siguiente comando, borramos los directorios y archivos de instalación
de la versión anterior.
# for i in 15.0.6 ; do \
rm -rf /opt/llvm15/lib64/clang/$i ; \
rm -f /opt/llvm15/lib64/libLLVM-$i.so ; \
rm -f /opt/llvm15/lib64/libclang.so.$i ; \
done |
Estadísticas de Compilación e Instalación de LLVM
Estadísticas de Compilación e Instalación de LLVM |
CPU |
AMD Ryzen 5 5500 |
MHz |
3593.250 (BoostMax=4457.000) |
RAM |
32 GB |
Sistema de archivos |
XFS |
Versión del Kernel |
6.1.4-ml SMP PREEMPT_DYNAMIC x86_64 |
Modo de frecuencia de la CPU |
schedutil |
Versión de Glibc |
2.36 |
Enlazador dinámico |
LLD 15.0.6 |
Compilador |
Clang 15.0.6 + Ccache 4.7.4 |
Parámetros de optimización |
-03 -march=znver3
-mtune=znver3 -fexperimental-new-pass-manager -mllvm -polly -mllvm -polly-vectorizer=stripmine
-flto=thin -Wl,--lto-aa-pipeline=globals-aa
-Wl,--lto-newpm-passes=memcpyopt |
Parámetros de compilación |
-v -j12 |
Ocupación de espacio en disco del proceso de compilación |
5,7 GB |
Tiempo de compilación |
50' 30" |
Archivos instalados |
6.971 |

|
Enlaces simbólicos creados |
122 |

|
Ocupación de espacio en disco |
2,1 GB |
Desinstalación como root
1)
MODO TRADICIONAL
Este programa no tiene soporte para desinstalación con el comando 'ninja uninstall'
2)
MODO MANUALINUX
El principal inconveniente del comando anterior es
que
tenemos que tener el directorio de compilación en nuestro
sistema para poder desinstalar el programa. En algunos casos esto
supone muchos megas de espacio en disco. Con el paquete de scripts que
pongo a continuación logramos evitar
el único inconveniente que tiene la compilación
de
programas, y es el tema de la desinstalación de los mismos
sin
la necesidad de tener obligatoriamente una copia de las fuentes
compiladas.
llvm-15.0.7-scripts.tar.gz
$ su
# tar zxvf llvm-15.0.7-scripts.tar.gz
# cd llvm-15.0.7-scripts
# ./Desinstalar_llvm-15.0.7 |
Copia de Seguridad como root
Con este otro script creamos una copia de seguridad de los binarios
compilados, recreando la estructura de directorios de los mismos en un
directorio de copias de seguridad (copibin)
que se crea en el directorio /var. Cuando se haya creado el paquete comprimido de
los binarios podemos copiarlo como usuario a nuestro home
y borrar el que ha creado el script de respaldo, teniendo en cuenta que si queremos
volver a restaurar la copia, tendremos que volver a copiarlo al lugar
donde se ha creado.
$ su
# tar zxvf llvm-15.0.7-scripts.tar.gz
# cd llvm-15.0.7-scripts
# ./Respaldar_llvm-15.0.7 |
Restaurar la Copia de Seguridad
como root
Y con este otro script (que se copia de forma automática
cuando
creamos la copia de respaldo del programa) restauramos la copia de
seguridad como root cuando resulte necesario.
$ su
# cd /var/copibin/restaurar_copias
# ./Restaurar_llvm-15.0.7
|
Configurar
el sistema para el uso de Clang
1) /etc/ld.so.conf
Añadimos
la ruta a las librerías compartidas en el
archivo /etc/ld.so.conf.
include ld.so.conf.d/*.conf
/usr/X11R6/lib
/usr/lib
/usr/lib/qt3/lib
/usr/local/lib
/opt/e17/lib
/opt/llvm15/lib64
/opt/llvm15/lib
|
Cuando lo hayamos editado y guardado ejecutamos la
actualización de la caché de las
librerías compartidas.
2) Añadir la ruta a los
binarios y las páginas de manual a nuestro PATH
2a) Variable de entorno PATH de usuario
Editamos el archivo de nuestro home, ~/.bashrc (si no existe lo creamos)
y añadimos lo siguiente al final del mismo:
export
PATH=/opt/llvm15/bin:$PATH
export MANPATH=/opt/llvm15/share/man:$MANPATH
|
2b) Variable de entorno PATH del sistema
Si queremos establecer una variable de entorno global del sistema, abrimos un editor de texto y añadimos lo siguiente:
#!/bin/sh
export
PATH=/opt/llvm15/bin:$PATH
export MANPATH=/opt/llvm15/share/man:$MANPATH
|
Lo guardamos con el nombre clang.sh, y lo instalamos en /etc/profile.d.
$ su -c "install -m755 clang.sh /etc/profile.d" |
Tenemos que cerrar el emulador de terminal y volverlo a abrir para que
la variable de entorno aplicada sea efectiva. Es conveniente guardar
una copia de este script para posteriores
instalaciones de nuestro sistema.
La ventaja de utilizar el directorio /etc/profile.d es que es común a todas las distribuciones y nos evita tener que editar otros archivos del sistema como por ejemplo, /etc/profile.
Para comprobar que el binario clang está incluido en el path, abrimos una ventana de terminal y ejecutamos el siguiente comando:
[jose@localhost ~]$ clang --version
clang version 15.0.7
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/llvm15/bin
|
2c) Lectura de las páginas de manual
2d) Lectura de la documentación en formato HTML
/opt/llvm15/share/doc/LLVM/llvm/html/index.html | /opt/llvm15/share/doc/LLVM/clang/html/index.html
Optimizaciones de CPU para Clang
Los procesadores soportados por Clang,
son practicamente los mismos que los de GCC, con las
excepciones en las que se permite más de una
definición para hacer referencia a un determinado
procesador. Por ejemplo, barcelona
no está soportado por Clang,
hasta la versión 3.6, con lo que tendremos que utilizar el otro término
alternativo: amdfam10.
El parámetro '-mtune' ha sido introducido a partir de la
versión 3.4
de Clang.
Si utilizamos versiones anteriores, tendremos que utilizar '-mcpu'.
La tabla que pongo a continuación no difiere mucho de la
utilizada en los manuales de instalación ubicados en la web,
las filas con el color amarillo indican las definiciones de procesador
soportadas
por Clang,
que no aparecen en las opciones de optimización de GCC.
$
export {C,CXX}FLAGS='-O3 -march=znver3 -mtune=znver3'
|
Donde pone znver3
se indica el procesador respectivo de cada sistema
seleccionándolo de la siguiente tabla: |
Nota informativa sobre las optimizaciones para GCC
|
* La opción '-march=' establece el procesador mínimo con el que funcionará el programa compilado, la opción '-mtune=' el procesador específico para el que será optimizado.
* Los valores separados por comas, son equivalentes, es decir, que lo mismo da poner '-march=k8' que '-march=athlon64'.
* En versiones de GCC 3.2 e inferiores se utiliza la opción '-mcpu=' en lugar de '-mtune='.
|
Nota informativa sobre las optimizaciones para Clang
|
* La opción '-mtune=' está soportada a partir de la versión 3.4 de Clang.
* Los valores de color azul no son compatibles con Clang.
* Las filas con el fondo de color amarillo son valores exclusivos de Clang y, por lo tanto, no son aplicables con GCC.
|
Valores |
CPU |
Genéricos |
generic |
Produce un código
binario optimizado para la mayor parte de procesadores existentes.
Utilizar este valor si no sabemos el nombre del procesador que
tenemos en nuestro equipo. Este valor sólo es aplicable en
la opción '-mtune=', si utilizamos GCC. Esta opción está disponible a
partir de GCC 4.2. |
native |
Produce un código
binario optimizado para el procesador que tengamos en nuestro sistema,
siendo éste detectado utilizando la instrucción cpuid.
Procesadores antiguos pueden no ser detectados utilizando este valor.
Esta opción está disponible a
partir de GCC 4.2. |
x86-64 |
Procesador genérico con extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 1.9. |
x86-64-v2 |
Procesador
genérico con con soporte de instrucciones X86-64 (MMX, SSE,
SSE2, LAHFSAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3) y extensiones
64-bit. Esta opción está disponible a partir de GCC 11 y Clang 12. |
x86-64-v3 |
Procesador
genérico con con soporte de instrucciones X86-64 (MMX, SSE,
SSE2, LAHFSAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3, AVX, AVX2, F16C,
FMA, LZCNT, MOVBE, XSAVE, XSAVEC, FMA4) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11 y Clang 12. |
x86-64-v4 |
Procesador
genérico con con soporte de instrucciones X86-64 (MMX, SSE,
SSE2, LAHFSAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3, AVX, AVX2, F16C,
FMA, LZCNT, MOVBE, XSAVE, XSAVEC, AVX512*, FMA4) y extensiones 64-bit.
Esta opción está disponible a partir de GCC 11 y Clang 12. |
Intel |
alderlake |
Intel Alderlake con
soporte de instrucciones x86-64 (MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND,
FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC,
XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD,
AVX512VNNI, AVX512BF16, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD,
CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16,
AMX-TILE, AMX-INT8, AVX-VNNI) y extensiones 64-bit. Esta opción
está disponible a partir de GCC 11 y Clang 12. |
atom |
Intel Atom
con soporte de instrucciones MMX, SSE, SSE2, SSE3, SSSE3 y
extensiones 64-bit. Esta opción está disponible
desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición bonnell. |
bonnell |
Intel Bonnell con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3 y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
broadwell |
Intel Broadwell con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT,
AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2,
F16C, RDSEED, ADCX, PREFETCHW y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9 y Clang 3.6. |
cannonlake |
Intel Cannonlake Server con soporte de instrucciones MOVBE, MMX, SSE,
SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL,
FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW,
CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
AVX512CD, AVX512VBMI, AVX512IFMA, SHA, UMIP y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 3.9. |
cascadelake |
Intel Cascadelake con
soporte de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1,
SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI,
BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES,
AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI y
extensiones 64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 8. |
cooperlake |
Intel
Cooper Lake con
soporte de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI,
BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB,
AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI, AVX512BF16 y
extensiones 64-bit. Esta opción está disponible a
partir de GCC 10 y Clang 9. |
core2 |
Intel Core2
con soporte de instrucciones MMX, SSE, SSE2, SSE3, SSSE3 y
extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.3. |
core-avx2 |
Intel Core (Haswell). Esta opción está disponible desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición haswell. |
core-avx-i |
Intel Core (ivyBridge)
con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, AVX, AES, PCLMUL, FSGSBASE, RDRND, F16C y
extensiones 64-bit. Esta opción está disponible
desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición ivybridge. |
corei7 |
Intel Core i7 con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1 y SSE4.2 y extensiones 64-bit. Soporta también los procesadores Intel
Core i3 e i5. Esta opción está disponible desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición nehalem. |
corei7-avx |
Intel Core i7 con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, AVX, AES y PCLMUL y
extensiones 64-bit. Soporta también los
procesadores Intel Core i3 e i5. Esta opción está disponible desde GCC 4.6, hasta GCC 4.8. A partir de GCC 4.9 se utiliza la definición sandybridge. |
goldmont |
Intel Goldmont con soporte
de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2,
POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE y extensiones
64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 5. |
goldmont-plus |
Intel Goldmont Plus con
soporte de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1,
SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, PTWRITE,
RDPID, SGX, UMIP y extensiones 64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 7. |
haswell |
Intel Haswell con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT,
AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2,
F16C y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
i386 |
Intel i386.
|
i486 |
Intel i486. |
i586, pentium |
Intel Pentium sin soporte de instrucciones MMX. |
i686 |
Produce un código binario optimizado para la mayor parte de
procesadores compatibles con la serie 80686 de Intel. Todos los actuales lo son. |
icelake-client |
Intel Icelake Client con soporte de instrucciones MOVBE, MMX, SSE,
SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL,
FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW,
CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI,
AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ,
VAES y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 7. |
icelake-server |
Intel Icelake Server con soporte de instrucciones MOVBE, MMX, SSE,
SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL,
FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW,
CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI,
AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ,
VAES, PCONFIG, WBNOINVD y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 7. |
intel |
Intel Haswell y Silvermont. Este valor sólo es aplicable en
la opción '-mtune='. Esta opción está disponible a partir
de GCC 4.9. |
ivybridge |
Intel Ivy Bridge con soporte de instrucciones
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX,
AES, PCLMUL, FSGSBASE, RDRND, F16C y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
knl |
Intel Knights Landing con soporte de instrucciones
MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2,
AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX,
PREFETCHW, AVX512F, AVX512PF, AVX512ER y extensiones 64-bit. Esta opción está disponible a partir
de GCC 5 y Clang 3.4. |
knm |
Intel Knights Mill con soporte de instrucciones MOVBE, MMX, SSE, SSE2,
SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, AVX512F,
AVX512PF, AVX512ER, AVX512CD, AVX5124VNNIW, AVX5124FMAPS,
AVX512VPOPCNTDQ y extensiones 64-bit. Esta opción está disponible a
partir de GCC 8 y Clang 6. |
lakemont |
Intel Quark Lakemont MCU, basado en el procesador Intel Pentium. Esta opción está disponible a partir
de GCC 6 y Clang 3.9. |
nehalem |
Intel Nehalem con soporte de instrucciones MMX,
SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT y extensiones
64-bit. Esta opción está disponible a partir
de GCC 4.9. |
nocona |
Versión mejorada de Intel Pentium4 con soporte de instrucciones MMX, SSE, SSE2, SSE3 y extensiones 64-bit. |
penryn |
Intel
Penryn con soporte de instrucciones MMX, SSE, SSE2, SSE3,
SSSE3 y SSE4.1. |
pentiumpro |
Intel PentiumPro. |
pentium2 |
Intel Pentium2 basado en PentiumPro con soporte de instrucciones MMX. |
pentium3, pentium3m |
Intel Pentium3 basado en PentiumPro con soporte de instrucciones MMX y SSE. |
pentium4, pentium4m |
Intel Pentium4 con soporte de instrucciones MMX, SSE y SSE2. |
pentium-m |
Versión de bajo
consumo de Intel Pentium3 con soporte de instrucciones MMX, SSE y SSE2.
Utilizado por los portátiles Centrino. |
pentium-mmx |
Intel PentiumMMX basado en Pentium con soporte de instrucciones MMX. |
prescott |
Versión mejorada de Intel Pentium4 con soporte de instrucciones MMX, SSE, SSE2 y SSE3. |
rocketlake |
Intel Rocket Lake con
soporte de instrucciones x86-64 (MOVBE, MMX, SSE, SSE2, SSE3, SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND,
FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC,
XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI,
AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ,
AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11. |
sandybridge |
Intel Sandy Bridge con soporte de instrucciones
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX,
AES, PCLMUL y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9 y Clang 3.6. |
sapphirerapids |
Intel Sapphire Rapids
con soporte de instrucciones x86-64 (MOVBE, MMX, SSE, SSE2, SSE3,
SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT,
XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD,
AVX512VNNI, AVX512BF16, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD,
CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16,
AMX-TILE, AMX-INT8 and AVX-VNNI) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11 y Clang 12. |
silvermont |
Intel Silvermont con soporte de instrucciones
MOVBE, MMX, SSE, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1,
SSE4.2, POPCNT, AES, PCLMU, RDRND y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9 y Clang 3.6. |
skylake |
Intel Skylake con soporte de instrucciones MOVBE, MMX, SSE, SSE2,
SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT,
XSAVEC, XSAVES y extensiones 64-bit. Esta opción está disponible a partir
de GCC 6 y Clang 3.6. |
skylake-avx512 |
Intel Skylake Server
con soporte de instrucciones MOVBE, MMX, SSE, SSE2,
SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE,
RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT,
XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD y
extensiones 64-bit. Esta opción está disponible a partir
de GCC 6 y Clang 3.9. |
tigerlake |
Intel
Tiger Lake con soporte de instrucciones OVBE, MMX, SSE, SSE2, SSE3,
SSSE3,
SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND,
FMA, BMI,
BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES,
AVX512F,
AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA,
CLWB, UMIP,
RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI,
VPCLMULQDQ,
VAES, PCONFIG, WBNOINVD, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT y
extensiones 64-bit. Esta opción está disponible a partir
de GCC 10 y Clang 10. |
tremont |
Intel Tremont con soporte
de instrucciones MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2,
POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, PTWRITE, RDPID,
SGX, UMIP, GFNI-SSE, CLWB, ENCLV y extensiones 64-bit. Esta opción está disponible a
partir de GCC 9 y Clang 7. |
westmere |
Intel Westmere con soporte de instrucciones
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES,
PCLMUL y extensiones 64-bit. Esta opción está disponible a partir
de GCC 4.9. |
yonah |
Procesadores
basados en la microarquitectura de Pentium M, con soporte de
instrucciones MMX, SSE, SSE2 y SSE3. |
AMD |
amdfam10, barcelona |
Procesadores basados en
AMD Family 10h core con soporte de instrucciones x86-64 (MMX, SSE,
SSE2, SSE3, SSE4A, 3DNow!, enhanced 3DNow!, ABM y extensiones
64-bit). Esta opción está disponible a partir de GCC 4.3. La definición barcelona está disponible a partir de Clang 3.6. |
athlon, athlon-tbird |
AMD Athlon con soporte de instrucciones MMX, 3DNow!, enhanced 3DNow! y SSE prefetch. |
athlon4, athlon-xp, athlon-mp |
Versiones mejoradas de AMD Athlon con soporte de instrucciones MMX, 3DNow!, enhanced 3DNow! y full SSE. |
bdver1 |
Procesadores basados en
AMD Family 15h core con soporte de instrucciones x86-64 (FMA4, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE,
SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM y extensiones
64-bit). Esta opción está disponible a partir
de GCC 4.7. |
bdver2 |
Procesadores basados en
AMD Family 15h core con soporte de instrucciones x86-64 (BMI, TBM, F16C, FMA, LWP, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE,
SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM y extensiones
64-bit). Esta opción está disponible a partir
de GCC 4.7. |
bdver3 |
Procesadores basados en
AMD Family 15h core con soporte de instrucciones x86-64 (FMA4, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE,
SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM y extensiones
64-bit). Esta opción está disponible a partir
de GCC 4.8 y Clang 3.4. |
bdver4 |
Procesadores basados en AMD Family 15h core con soporte de instrucciones x86-64
(BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP,
LWP, AES, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A,
SSSE3, SSE4.1, SSE4.2, ABM y extensiones 64-bit). Esta opción está
disponible a partir de GCC 4.9 y Clang 3.5. |
btver1 |
Procesadores basados en
AMD Family 14h core con soporte de instrucciones x86-64 (MMX, SSE,
SSE2, SSE3, SSE4A, CX16, ABM y extensiones 64-bit). Esta opción está disponible a partir
de GCC 4.6. |
btver2 |
Procesadores basados en
AMD Family 16h core con soporte de instrucciones x86-64 (MOVBE, F16C,
BMI, AVX, PCL_MUL, AES, SSE4.2, SSE4.1, CX16, ABM, SSE4A, SSSE3, SSE3,
SSE2, SSE, MMX y extensiones 64-bit). Esta opción
está disponible a partir
de GCC 4.8. |
geode |
AMD integrado con soporte de instrucciones MMX y 3DNow!. Esta opción está disponible a partir de GCC 4.3. |
k6 |
AMD K6 con soporte de instrucciones MMX. |
k6-2, k6-3 |
Versiones mejoradas de AMD K6 con soporte de instrucciones MMX y 3DNow!. |
k8, opteron, athlon64, athlon-fx |
Procesadores basados en
AMD K8 core con soporte de instrucciones x86-64 (MMX, SSE, SSE2,
3DNow!, enhanced 3DNow! y extensiones 64-bit). |
k8-sse3, opteron-sse3, athlon64-sse3 |
Versiones mejoradas de
AMD K8 core con soporte de instrucciones SSE3. Esta opción
está disponible a partir de GCC 4.3. |
znver1 |
Procesadores basados en
AMD Family 17h core con soporte de instrucciones x86-64 (BMI, BMI2,
F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES,
PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1,
SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT y extensiones
64-bit). Esta opción está disponible a partir de GCC 6 y Clang 4. |
znver2 |
Procesadores basados en
AMD Family 17h core con soporte de instrucciones x86-64 (BMI, BMI2,
,CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA,
CLZERO, AES, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3,
SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT y extensiones
64-bit). Esta opción está disponible a partir de GCC 9 y Clang 9. |
znver3 |
Procesadores basados en
AMD Family 19h core con soporte de instrucciones x86-64 (BMI, BMI2,
CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA,
CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3,
SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID,
WBNOINVD, PKU, VPCLMULQDQ, VAES) y extensiones 64-bit. Esta
opción está disponible a partir de GCC 11 y Clang 12. |
Niveles de optimización soportados por Clang
Niveles de optimización soportados por Clang
|
-O0
|
Sin optimizaciones. Es el
nivel más rápido para compilar programas y
genera el código más depurable.
|
-O1
|
Un nivel intermedio entre -O0 y -O2.
|
-O2 |
Un nivel moderado de optimización.
|
-O3
|
Lo mismo que -O2, excepto que permite
optimizaciones que alargan el proceso de compilación
y pueden llegar a generar un binario de tamaño
más grande, con la idea de hacer que se ejecute
más rápido.
|
-Ofast
|
Activa todas las
optimizaciones de -O3, junto
con otras optimizaciones agresivas que pueden violar el
estricto cumplimiento de los estándares del lenguaje
de programación.
|
-Os
|
Lo mismo que -O2, con optimizaciones adicionales
para reducir el tamaño del binario resultante.
|
-Oz |
Lo mismo que -Os,
pero con una reducción de tamaño del binario
resultante, más agresiva.
|
-O
|
Equivalente a -O2.
|
-O4 y superiores
|
Actualmente equivale a -O3.
|
-Og |
Equivalente a -O1. |
Optimizaciones adicionales para Clang
Optimizaciones adicionales para Clang
|
New Pass Manager |
-fexperimental-new-pass-manager
-fno-legacy-pass-manager (a partir de Clang 12) |
Activa el uso del nuevo
gestor de pases de análisis y optimización de LLVM.
Aunque lleva el nombre de experimental, es una optimización de
nivel superior bastante estable y puede ser aplicada también con
las optimizaciones LTO y ThinLTO, cuando éstas son procesadas
por el enlazador dinámico, ya sea GNU gold o LLD.
Si utilizamos esta opción con LLD y LTO o ThinLTO y
añadimos también los pases de análisis y
optimización de LLVM podemos obtener unos resultados muy
óptimos en función del pase de optimización que
utilicemos.
Esta optimización se puede establecer como predefinida de Clang, estableciendo la variable de CMake, -DENABLE_EXPERIMENTAL_NEW_PASS_MANAGER=ONen
el proceso de configuración de LLVM. Variable que se
incluyó
por defecto en este manual con la versión 10 de Clang, y que se
retiró a partir de la versión 11 de Clang, porque desde
la versión 10 de Clang hasta la 12, la combinación New Pass Manager+Polly
daba errores de compilación en varios paquetes, lo que obligaba a
tener que añadir en cada manual de los ubicados en esta web,
donde se produce el error, el parámetro -fno-experimental-new-pass-manager,
que desactiva el uso de New Pass Manager, si lo hemos activado por
defecto en el proceso de compilación de Clang. En otros
manuales, directamente hay que desactivar el uso de Polly.
Desde que
se modificó la integración de Polly en Clang, venía
sucediendo esto, algo que se ha solucionado en la
versión 13 de Clang.
A partir de Clang 12, esta opción se considera lo
suficientemente estable para no llamarla experimental, con lo que el
nombre del parámetro de optimización ha cambiado a -fno-legacy-pass-manager, pasando a ser -fexperimental-new-pass-manager un alias del primero y fno-experimental-new-pass-manager un alias de -flegacy-pass-manager.
Cuando se sustituya de forma definitiva el gestor de pases antiguo por
el nuevo, los alias serán eliminados de Clang y también
de este manual y de los respectivos manuales de la web. Más
información en este enlace.
A partir de Clang 14, se ha retirado el alias fno-experimental-new-pass-manager.
|
Polly |
-mllvm -polly |
Activa el uso de Polly, un optimizador de características similares a la optimización Graphite de GCC.
Este optimizador solo funciona en el nivel '-O3' de
optimización. Puede provocar errores de compilación y de ejecución en
determinados paquetes.
La definición de la optimización Graphite también es válida para Polly y consiste en utilizar la representación de la figura geométrica del poliedro
para ejecutar en paralelo los bucles de programación que contenga el
código fuente de un programa, en el binario resultante del proceso de
compilación, acelerando de forma considerable el tiempo de ejecución
del mismo. |
-mllvm -polly-vectorizer=stripmine |
Activa la generación automática de código vectorizado, a través de Polly. Este parámetro debe ir precedido del anterior. Desde Clang 3.5 es el parámetro predefinido de Polly utilizado en los manuales de la web. A partir de la versión 3.7, se ha sustituido el valor polly por stripmine. El primer valor se puede seguir utilizando pero se recomienda utilizar el segundo.
|
-mllvm -polly-parallel |
Activa la generación automática de código OpenMP, a través de Polly.
Este parámetro debe ir precedido del inicial de esta
sección. Este parámetro lo pongo como experimental, y
sólo lo podremos aplicar en aquellos paquetes que contengan
código OpenMP,
en combinación con el utilizado por el compilador para dicho
proceso. |
-mllvm-polly-omp-backend=LLVM |
Activa que Polly utilice libomp en lugar de libgomp (GNU) que es la predefinida, para generar el código OpenMP. |
-mllvm -polly-position=before-vectorizer |
Activa que Polly
se ejecute antes que LLVM en el proceso de optimización y no
después, que es el modo de trabajar predefinido. Este
parámetro debe ir precedido del inicial de esta sección.
En
determinados procesos de compilación puede mejorar la
optimización del binario resultante. En otros la puede empeorar.
Más información en este enlace.
|
-mllvm -polly-2nd-level-tiling |
Activa un segundo nivel de
optimización de mosaico de bucle. Por defecto, Polly tiene
activada la optimización de mosaico (tiling). Con esta
opción hacemos que le dé otra pasada más profunda
de este tipo de optimización específico, al código
a compilar. |
-mllvm -polly-pattern-matching-based-opts |
Activa optimizaciones basadas en patrones idénticos. |
-mllvm -polly-loop-fusion-greedy |
Intenta fusionar de forma agresiva todos los bucles
de programación, independientemente del rendimiento que pueda
producir. Esta opción está a partir de la versión
14 de Polly. |
LTO |
-flto |
Activa la optimización LTO, equivalente a la optimización LTO de GCC.
Puede provocar errores de compilación y de ejecución en
determinados paquetes. Tenemos que tener instalado y configurado el paquete Binutils, con el enlazador dinámico ld.gold como el predefinido del sistema, para que este parámetro sea funcional. La otra alternativa es utilizar LLD como enlazador dinámico.
Además de haber compilado el plugin LLVM Gold
como se explica en este manual. La carga de este plugin se realiza de
forma automática, sin tener que añadir ningún
parámetro adicional.
En procesos de compilación que se generen librerías estáticas, o que intervenga el programa nm de Binutils, tendremos que establecer la siguiente variable de entorno, antes de ejecutar el script de configuración del paquete.
$ export AR=llvm-ar RANLIB=llvm-ranlib NM=llvm-nm |
En el manual de GCC
explico de forma más extendida el porqué del uso de esta
variable de entorno, en la sección de preguntas y respuestas
relacionada con la optimización LTO.
|
ThinLTO |
-flto=thin |
ThinLTO
es una variante
más agresiva de LTO, introducida a partir de la versión
3.9 de LLVM. Lo que se busca con esta optimización es reducir
a la mínima expresión el tiempo necesario para generar el
binario ejecutable correspondiente a partir de los archivos objeto que
intervengan en el proceso de enlace, aprovechando la capacidad
multinúcleo de los procesadores actuales, que es el principal
inconveniente
que se nos presenta cuando hacemos uso de la tradicional
optimización LTO. Podemos encontrar más
información y la correspondiente comparativa en esta entrada del blog de la web de LLVM.
A diferencia de LTO que utiliza sólo un archivo objeto para
volcar el proceso de enlazado, ThinLTO divide el mismo en
múltiples archivos objeto, lo que puede llegar a rebasar el
límite de procesos por usuario establecidos en nuestro sistema,
impidiendo por ejemplo, si tenemos un limite de 1024, que en paquetes
como Inkscape o GTK3, no podamos utilizar esta optimización.
Para solucionar este inconveniente, primero comprobaremos el
límite de procesos por usuario que tenemos en nuestro sistema
con el siguiente comando:
[jose@localhost ~]$ ulimit -n
1024 |
En mi caso personal son 1024, que elevo a 4096, con el mismo comando al que le añado el número dado.
Como este valor es volátil y desaparece cuando reiniciamos el
sistema, creamos el script correspondiente para que dicho valor quede
establecido por defecto al inicio del sistema. Abrimos un editor de
texto y añadimos lo siguiente:
Lo guardamos con el nombre ulimit.sh y lo instalamos en /etc/profile.d.
$ su -c "install -m755 ulimit.sh /etc/profile.d" |
En el siguiente reinicio del sistema, comprobamos que el valor establecido por el script es el que está en uso.
[jose@localhost ~]$ ulimit -n
4096 |
|
OpenMP |
-fopenmp=libomp
|
OpenMP
es una API de programación creada única y exclusivamente
para aprovechar la potencia de los procesadores multinúcleo, si
el nuestro no lo es, no es necesario seguir leyendo esto. Esta
optimización sólo es operativa en aquellos paquetes de
código fuente que están previamente preparados para
utilizarla: ImageMagick, Blender, Inkscape, etc.
La versión actual de Clang es compatible con la
versión 5.0 de OpenMP e inferiores. El parámetro a
añadir varía del utilizado por
GCC, y permite elegir qué librería utilizar para el
enlazado del binario ejecutable. Si no especificamos ninguna y dejamos
que el script de configuración del paquete detecte el
parámetro -fopenmp,
el mismo se enlazará contra la librería libomp de LLVM.
En versiones antiguas de Clang, se enlaza por defecto contra la
librería libgomp de GCC.
Desde la versión 3.9 de Clang, también se puede
seleccionar la versión de OpenMP a utilizar por el compilador,
en el caso de que el script de configuración del paquete, no
detecte de forma correcta la versión más reciente. En
este caso el parámetro a añadir al inicial, sería
uno de los siguientes:
-fopenmp-version=31 >> OpenMP 3.1
-fopenmp-version=40 >> OpenMP 4.0
-fopenmp-version=45 >> OpenMP 4.5 (versión predefinida de Clang 10 si sólo se utiliza el parámetro -fopenmp)
-fopenmp-version=50
>> OpenMP 5.0 (a partir de Clang 10. Versión
predefinida de Clang 11 si sólo se utiliza el
parámetro -fopenmp)
-fopenmp-version=51 >> OpenMP 5.1 (a partir de Clang 11. Soporte en fase previa de implementación)
Que quedaría así en una variable de entorno, un ejemplo con OpenMP 4.5:
$ export {C,CXX}FLAGS+=" -fopenmp=libomp -fopenmp-version=45"
|
Es posible que en algunos procesos tengamos que añadir una variable de entorno LDFLAGS, tipo export LDFLAGS+=' -lomp'
para que la librería de OpenMP proporcionada por LLVM intervenga
en el proceso de enlazado. En paquetes como ImageMagick es necesario
hacer una sustitución masiva después de ejecutar el
script de configuración para sustituir el parámetro -lgomp, añadido de forma automática por el script de configuración, por el parámetro -lomp. Un ejemplo:
$ find . -name 'Makefile' -type f | xargs sed -i 's:-lgomp:-lomp:g' |
Como experiencia personal con algunos paquetes, mi recomendación
es que se utilicen los siguientes parámetros para el uso de esta
optimización.
$ export {C,CXX}FLAGS+=" -fopenmp=libomp -fopenmp-version=50"
$ export LDFLAGS+=" -lomp"
|
En paquetes como LibRaw, si dejamos que el script de
configuración establezca el parámetro -fopenmp por
sí mismo, nos encontraremos que, la librería resultante
del proceso de compilación, no quedará enlazada contra
libomp y, por lo tanto, no hará uso de las
características de esta optimización. En cambio, en otros
paquetes como MAME, sí que funciona este parámetro sin
que tengamos que añadir nada por nuestra cuenta.
NOTA IMPORTANTE=
Con Clang 14, existe un error (inicialmente subsanado, pero que, en las
siguientes versiones de corrección de errores, se ha vuelto a
reproducir) que no añade de forma correcta, el directorio
/opt/llvm15/lib64, a la ruta predefinida de búsqueda de
librerías de Clang, lo que nos obliga a tener que completar
la variable de entorno anterior con lo que está en rojo,
siendo obligatorio el uso de esta variable siempre:
$ export {C,CXX}FLAGS+=" -fopenmp=libomp -fopenmp-version=50"
$ export LDFLAGS+=" -L$(llvm-config --libdir) -lomp"
|
Si no queremos hacer uso de la misma, la otra opción más
simple es crear un enlace simbólico al directorio /usr/lib64 de
la librería libomp:
# ln -s /opt/llvm15/lib64/libomp.so /usr/lib64 |
|
PGO |
-fprofile-generate=ruta a directorio o archivo
-fprofile-use=ruta a directorio o archivo |
PGO son las siglas con las que se conoce a la optimización Profile Guided Optimization (Optimización Guiada por Perfiles). El compilador recopila
información del total de funciones y bloques de datos que
contiene el binario ejecutable, tanto en el proceso de
compilación como en una posterior ejecución del mismo.
Dichos datos serán utilizados en un segundo proceso de
compilación, pudiendo utilizarlos en posteriores procesos de
compilación, siempre y cuando, el código fuente no sea
alterado de forma significativa.
La optimización PGO se divide en dos modos:
instrumentación (la que explico aquí) y muestreo, que
requiere del uso de aplicaciones externas como Perf y AutoFDO,
realizando todo el proceso de forma manual por parte del usuario:
ejecución del binario compilado con perf para obtener las
muestras y su posterior conversión con AutoFDO a un formato
legible por Clang.
A diferencia de las otras
optimizaciones explicadas en este manual, ésta requiere de un
proceso más elaborado para su aplicación, que explico a
continuación:
1) Creamos un directorio de ubicación de los perfiles de
optimización guiada con permisos de escritura para todos los
usuarios.
$ su
# mkdir -p /var/pgo
# chmod 777 /var/pgo |
2) Establecemos la variable de entorno de generación del perfil
de optimización con la ruta del directorio de perfiles de
optimización que hemos creado, más el nombre del
paquete que vamos a compilar, por ejemplo, mc. Añadimos un nivel de optimización -O2 y un parámetro de generación de símbolos de depuración, g1 o -gline-tables-only que es lo mismo.
$ export {C,CXX}FLAGS+=' -O2 -g1 -fprofile-generate=/var/pgo/mc |
3) Ejecutamos el script de configuración pertinente y compilamos
el paquete. En la ruta indicada se habrán creado una serie de archivos de
datos con el nombre default_*.profraw.
Instalamos el paquete y lo ejecutamos. Si el paquete de código
fuente contiene tests, lo mejor para recopilar información es
ejecutar en el mismo make check después de haber compilado el mismo (nos ahorramos tener que
instalarlo). En unos paquetes esto resulta efectivo (por ejemplo, ImageMagick o POV-Ray), en otros, al ser los tests muy básicos, lo mejor es ejecutar la aplicación.
4) Convertimos el formato en crudo de los archivos default_*.profraw a un formato binario legible por Clang, con el comando llvm-profdata:
$ llvm-profdata merge /var/pgo/mc/default_*.profraw \
--output=/var/pgo/mc/default.profdata |
Con la variable de entorno LLVM_PROFILE_FILE, podemos cambiar la ruta
predefinida de ubicación y el nombre del perfil de
optimización. Un ejemplo de ejecución de un programa, en
el que se sustituye el nombre predefinido, por la ID del proceso de
ejecución. Esto nos permitirá crear varios archivos de
perfil por ejecución del programa, que podremos combinar con el
comando llvm-profdata, para su posterior uso en el segundo proceso de compilación del paquete:
$ LLVM_PROFILE_FILE=/var/pgo/mc/mc-%p.profraw mc |
$ llvm-profdata merge /var/pgo/mc/mc-*.profraw \
--output=/var/pgo/mc/default.profdata |
5) Volvemos a recompilar el paquete. Tenemos dos opciones, una es
empezar de cero con las variables de entorno y añadir la
siguiente, volviendo a ejecutar el script de configuración,
después de haber limpiado el directorio de compilación
con el comando make distclean o make clean según esté configurado:
$ export {C,CXX}FLAGS+=' -fprofile-use=/var/pgo/mc |
La otra más rápida consiste en modificar los archivos
Makefile de forma masiva, modificando el parámetro aplicado, con
el siguiente comando:
$ find . -name 'Makefile' | xargs sed -i 's:fprofile-generate:fprofile-use:g' |
Una vez los hayamos modificado, ejecutamos make clean; make y volvemos a instalar el paquete. El
perfil de optimización creado lo podemos cargar de forma directa
en la siguiente compilación, siempre y cuando el código
fuente no haya sido alterado de forma significativa.
Ya se encargará el compilador de avisarnos de esto. Si tenemos
desactivados los avisos con el parámetro -w, no nos
avisará en absoluto.
Tener en cuenta que si creamos el perfil con el parámetro -O2 -g1,
sin ningún tipo de optimización adicional,
obtendremos más información que nos servirá para
aplicar una optimización PGO más efectiva. Lo cual no
quiere decir que no se pueda realizar el proceso con las mismas
optimizaciones en el comienzo y en el final del mismo.
$ export {C,CXX}FLAGS+=' -fprofile-use=/var/pgo/mc |
Para acelerar todo esto, siempre es bueno crearse unas funciones de
Bash. Abrimos con un editor de texto, el archivo ~/.bashrc, si no
existe lo creamos y añadimos lo siguiente al final del mismo:
optclang-gpgo () { dir="$1"; export {C,CXX}FLAGS+=" -O2 -g1 -fprofile-generate=/var/pgo/$dir"; }
optclang-upgo () { dir="$1"; export {C,CXX}FLAGS+=" -fprofile-use=/var/pgo/$dir"; }
optclang-profdata
() { llvm-profdata merge /var/pgo/$1/default_*.profraw
--output=/var/pgo/$1/default.profdata; rm -f
/var/pgo/$1/default_*.profraw; }
|
Guardamos el archivo, abrimos una ventana de terminal, y ahora
simplemente basta ejecutar el alias correspondiente para añadir
la variable de entorno de esta optimización más el nombre
del directorio que definamos para ubicar los datos del perfil.
Primer proceso de compilación:
Conversión de los datos del perfil (incluye borrado de los
archivos generados por el compilador para reducir el espacio en disco
de los directorios que incluyen los perfiles de optimización)
Segundo proceso de compilación:
Y, por último, siempre que se modifiquen los parámetros de optimización, se debe de
crear un perfil nuevo de optimización porque los resultados pueden
variar significativamente en función de las optimizaciones aplicadas en
el proceso de compilación.
|
CSPGO |
-fprofile-use=ruta a directorio o archivo -fcs-profile-generate=ruta a directorio o archivo
-fprofile-use=ruta a archivo |
Introducida a partir de Clang 9, CSPGO
es una optimización PGO de dos pases, primero se realiza una PGO
normal y, a partir del archivo de perfil creado se vuelve a recompilar
el paquete tomando como referencia dicho archivo, para finalmente,
volver a recompilar el paquete con el archivo de perfil PGO resultante
de la fusión de los archivos de perfil en crudo generados por el
ejecutable (default_*.profraw) y el perfil PGO inicial (default.profdata). Un ejemplo:
1) Primer proceso de compilación tomando como referencia el archivo de perfil PGO creado en la sección anterior:
$ export {C,CXX}FLAGS+=' -O2 -g1 -fprofile-use=/var/pgo/mc -fcs-profile-generate=/var/pgo/mc |
2) Ejecución y testeo del programa.
3) Convertimos el formato en crudo de los archivos default_*.profraw a un formato binario legible por Clang, con el comando llvm-profdata,
mezclándolos con el perfil PGO creado inicialmente, creando un
archivo de perfil de salida con el nombre de la optimización:
$ llvm-profdata merge /var/pgo/mc/default_*.profraw \
/var/pgo/mc/default.profdata --output=/var/pgo/mc/cspgo.profdata |
4) Finalmente, utilizamos el perfil resultante de la fusión, en el proceso de compilación:
$ export {C,CXX}FLAGS+=' -fprofile-use=/var/pgo/mc/cspgo.profdata |
Para acelerar todo esto, siempre es bueno crearse unas funciones de
Bash. Abrimos con un editor de texto, el archivo ~/.bashrc, si no
existe lo creamos y añadimos lo siguiente al final del mismo:
optclang-csgpgo () { dir="$1"; export {C,CXX}FLAGS+=" -O2 -g1 -fprofile-use=/var/pgo/$dir -fcs-profile-generate=/var/pgo/$dir"; }
optclang-csupgo () { dir="$1"; export {C,CXX}FLAGS+=" -fprofile-use=/var/pgo/$dir/cspgo.profdata"; }
optclang-csprofdata
() { llvm-profdata merge /var/pgo/$1/default.profdata
/var/pgo/$1/default_*.profraw --output=/var/pgo/$1/cspgo.profdata; rm -f
/var/pgo/$1/default_*.profraw; }
|
Guardamos el archivo, abrimos una ventana de terminal, y ahora
simplemente basta ejecutar el alias correspondiente para añadir
la variable de entorno de esta optimización más el nombre
del directorio que definamos para ubicar los datos del perfil.
Primer proceso de compilación:
Conversión de los datos del perfil (incluye borrado de los
archivos generados por el compilador para reducir el espacio en disco
de los directorios que incluyen los perfiles de optimización) y
mezcla con el archivo de perfil PGO. Como opción también
le podemos añadir que borre el archivo de perfil PGO
(default.profdata), para dejar solo el archivo de perfil CSPGO
(cspgo.profdata).
Segundo proceso de compilación:
Por último, si se producieran mensajes de error en la ejecución y testeo del programa, del tipo error: undefined reference to '__llvm_profile_runtime', añadimos la siguiente variable de entorno LDFLAGS en el primer proceso de compilación:
$ export LDFLAGS+=" $(clang -print-resource-dir)/lib/linux/libclang_rt.profile-x86_64.a" |
Esto es válido también para la optimización PGO.
|
Para añadir estas optimizaciones adicionales a las variables de entorno de
optimización
de CPU que hayamos establecido, basta ejecutar el comando siguiente,
incluyendo el nivel de optimización nuevamente, para asegurarnos
de que se utilice el mismo en el proceso de compilación:
New Pass Manager
$ export {C,CXX}FLAGS+=' -fexperimental-new-pass-manager' |
Polly
$ export {C,CXX}FLAGS+=' -O3 -mllvm -polly' |
Polly (generación automática de código vectorizado)
$ export {C,CXX}FLAGS+=' -O3 -mllvm -polly -mllvm -polly-vectorizer=stripmine' |
Polly (sólo en aquellos paquetes en los que se active por defecto el parámetro -fopenmp)
$
export {C,CXX}FLAGS+=' -O3 -mllvm -polly -mllvm
-polly-vectorizer=stripmine -mllvm -polly-parallel' |
LTO
$ export {C,CXX}FLAGS+=' -flto'
|
ThinLTO
$ export {C,CXX}FLAGS+=' -flto=thin'
|
En algunos procesos hay que añadir también el parámetro a la variable de entorno LDFLAGS.
$ export {C,CXX,LD}FLAGS+=' -flto=thin'
|
En procesos que se generen librerías estáticas, o intervenga el comando
nm de Binutils, la variable de entorno sería la siguiente, acompañada
de la modificación que sea necesario realizar en paquetes que no
acepten estas variables de entorno.
$ export AR=llvm-ar RANLIB=llvm-ranlib NM=llvm-nm
$ export {C,CXX}FLAGS+=' -flto'
|
Tener en cuenta que el nivel de optimización aplicado en un
proceso de compilación es siempre el último que aparece
en la salida del compilador. Si el script de configuración del
paquete, incluye su propio nivel de optimización, es posible, y
en esta web hay ejemplos, de que éste se muestre detrás
del nivel de optimización que hayamos establecido mediante la
correspondiente variable de entorno en la terminal. Para evitar esto,
tendríamos que recurrir a una edición masiva de los
archivos 'Makefile', con el siguiente comando:
$ find . -name 'Makefile' | xargs sed -i 's:-O2::' |
Para ver las variables de entorno que hemos aplicado antes de ejecutar
el script de configuración, ejecutamos el siguiente comando:
$ echo ${CFLAGS,CXXFLAGS} |
Y si nos hemos equivocado en algo, pues las borramos y volvemos a
empezar. O las sobreescribimos volviendo a aplicar la primera variable
de entorno que hemos establecido, la que no lleva el símbolo '+'.
Clang suele mostrar más mensajes de aviso que GCC, Para eliminarlos
todos (algunos producen errores de compilación), basta establecer la
siguiente variable de entorno, antes de ejecutar el proceso de configuración del paquete correspondiente.
$ export {C,CXX}FLAGS+=' -w' |
Crear alias de bash para facilitar las tareas de compilación de programas con Clang
Lo mejor que podemos hacer para no tener que estar copiando y pegando
variables de entorno relacionadas con Clang,
es automatizar un poco el proceso, creando los
correspondientes alias de bash. A continuación pongo los
míos, que cada usuarios los adapte a sus
necesidades. Abrimos con un editor de texto, el archivo de
configuración personal, ~/.bashrc, si no existe lo creamos, y añadimos lo siguiente al final del contenido del mismo:
alias optclang="export CC=clang CXX=clang++ {C,CXX}FLAGS='-O3 -march=znver3 -mtune=znver3' -fexperimental-new-pass-manager -mllvm -polly -mllvm -polly-vectorizer=stripmine'"
alias optclang-cpu="export CC=clang CXX=clang++ {C,CXX}FLAGS='-O3 -march=znver3 -mtune=znver3'"
alias optclang-lto="export {C,CXX}FLAGS+=' -flto'"
alias optclang--thinlto="export {C,CXX}FLAGS+=' -flto=thin'"
alias optclang-ar="export AR=llvm-ar RANLIB=llvm-ranlib NM=llvm-nm"
|
El principal es optclang,
que establece el uso de compilador, optimización de CPU y
optimización con Polly, en un sólo comando. Si nos falla
la compilación con Polly, sobreescribimos este alias con optclang-cpu, que omite la vectorización de código con Polly. Luego como añadido utilizamos el alias optclang-lto para utilizar la optimización LTO o la optimización ThinLTO con el alias optclang--thinlto, que combinamos con el alias optclang-ar
en procesos en los que se compilan librerías estáticas.
Tener en cuenta que todo esto debe de adaptarse al proceso de
compilación en cuestión. Muchas veces tenemos que
añadir el parámetro -flto
a la propia variable de entorno de uso de compilador (export
{CC,CXX}+=" -flto") para que esta optimización se pueda llevar a
cabo con algunos paquetes.
Con el nuevo soporte de OpenMP añadimos un nuevos alias, aunque su uso queda muy reducido por la escases de paquetes que soportan OpenMP.
alias optclang-omp="export {C,CXX}FLAGS+=' -fopenmp=libomp' LDFLAGS+=' -lomp'"
|
|