type
status
date
slug
summary
tags
icon
password
一、 为什么要进行编译选项的讲解?
因为不同的编译人员需要不同的编译需求。一个编译器为了能够更好的与优化人员进行进行交互,所以有些功能会需要添加相应的编译选项才能实现。
本文会通过讲解前端选项、优化选项、生成代码选项、链接选项进行讲解。其中涉及到的主要优化内容LLVM IR pass的内容会在下一篇进行讲解。(挖坑)
广义的LLVM指的是整个LLVM的架构,狭义的LLVM指的是LLVM后端。

1、 预处理(用的很少不做示例)
预处理主要是处理源代码文件里面以#开头的源程序语句。常用的选项有以下几种
选项 | 功能 |
-include<file> | 将隐式的#include添加到预定义缓冲区中,在对源文件进行预处理之前读取该缓冲区 |
-I<filename> | 将指定的目录添加到include文件的搜索路径中 |
-undef | 取消所有的系统定义宏 |
-U<macroname> | 在预处理源文件之前读取的预定义缓冲区中添加一个隐式#undef |
2、 语言和模式
语言和模式用的还蛮多。因为作为一个初学者码农,难免会在写代码的时候使用中文来解释当前语句起的什么作用。但是编译器有时候并不能很好的解释中文,所以语言选项就显得十分重要。
选项 | 功能 |
-x<language> | 将后续输入文件视为具有<language>类型的语言 |
-std=<language> | 指定要编译的语言标准 |
-stdlib=<library> | 指定要使用的C++标准库;支持的选项是libstdc++和libc++。如果未指定会使用默认值。 |
-ObjC, -ObjC++ | 将源输入文件分别处理为Objective-C和Object-C++输入 |
二、 优化选项(重要)
开发人员往往专注于功能的开发实现,而对代码的优化关注较少。对代码的优化要从多方面进行考虑。
1、 优化级别
- O优化选项用来控制编译器对程序编译时的优化级别,常用的优化级别有:-O0、-O1、-O2、-O3、-Ofast等。
选项 | 功能和包含的优化选项 |
-O0 | 意味着没有优化。但这个级别的编译最快,并生成最可调试的代码。此时生成的汇编最接近程序源代码的语句。 |
-O1 | 只开启少量优化,主要对代码的分支、常量以及表达式进行优化。
大函数所需的编译时间和内存消耗都会稍微增加。在这种设置下,编译器会尝试减小代码文件的大小,减少执行时间,但并不执行需要大量编译时间的优化。
主要的编译选项有:-instcombine(冗余指令合并)、-simplifycfg(简化上下文无关文法)、-loops、-loop-unroll(在循环中执行代码时进行循环展开) |
-O2 | 在-O1的基础上增加了自动向量优化,在编译时会有一定的时间空间损耗。包括了循环展开和函数内联。
添加了-inline(内联优化)、-fvectorize(循环向量化优化)、-fslp-vectorize(运行基本块级向量化)等 |
-O3 | -O3类似于-O2,进行最强的优化,包括向量化和更复杂的函数优化。
添加了-aggressive-instcombime、-callsite-splitting、-domtree(支配树优化])等 |
-Os | 针对代码大小进行优化。启用除经常增加代码大小的优化之外的所有优化 |
-Ofast | 无视严格的标准合规性。 启用所有优化。它还支持并非对所有符合标准的程序都有效的优化 |
-Oz | 积极优化尺寸而不是速度。如果这些指令需要较少的字节进行编码,则可能会增加执行的指令数。 |
2、 代码生成选项
代码生成阶段可以通过编译阶段选项指定不同的处理阶段,通过数据选项选择对数据的处理方式,通过目标平台选项生成指定平台的代码,通过后端选项打开不同后端支持的优化功能。
① 编译阶段
指定编译器执行到哪个阶段,包括预编译阶段、编译阶段、汇编阶段、链接阶段、生成目标可执行文件。
选项 | 功能 |
-E | 运行预编译阶段 |
-emit-llvm -S | 运行编译阶段,生成.ll中间代码文件 |
-S | 运行编译阶段,生成.s汇编文件 |
-c | 运行编译、汇编阶段,但不运行链接阶段,生成目标.o文件 |
-o | 运行编译、汇编、链接阶段,生成可执行文件 |
② 数据选项(先留个白,不知道这个有什么作用)
③ 目标平台
可以指定生成代码的目标运行机器,包括X86、AMDGPU、ARM等
选项 | 功能 |
-march=<cpu> | 指定Clang为特定的处理器生成代码 |
-mmacosx-version-min=<version> | 为Mac OS X构建时,指定应用程序支持的最低版本 |
--cuda-host-only | 只编译CUDA的主机端代码 |
④ 后端选项
针对后端有有特定的优化,最主要的就是转化成目标平台特定汇编代码的组件。LLVM支持多种后端,比如:X86、ARM等。每种后端都有自己的指令集和寄存器架构,Clang为后端提供了特定的优化,比如指令选择、指令调度、寄存器分配等。
选项 | 功能 |
-mavx2 | 支持MMX、SSE、AVX和AVX2内置函数和指令集 |
-msse | 支持MMX和SSE内置函数和代码的生成 |
-mllvm -disable-x86-lea-opt | 禁用LEA优化 |
-malign-double | 按double类型对齐 |
- 作者:JucanaYu
- 链接:https://jucanayu.top/article/376e0c4a-161b-4d0a-ae50-06dec9ceb508
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。