How to know what is included in each optimization level of Clang?

for example, GCC can use “$ arm-none-eabi-gcc -Q -O1/O2/O3/Os/O0 --help=optimizers” to show the specific optimization flags include in each optimize level. But what is Clang’s command to show?

Clang doesn’t really let you configure which bits of the optimizer get run (with a few exceptions like the vectorizers). You can get a report of what actually ran during compilation (and how long it took) with something like -Xclang -ftime-report=per-pass

In some papers, iterative compilation methods or machine learning methods are used to find the best combination of compiler flags to achieve the best performance of the compilation goal. In this way, the new compilation flag combination can replace the original -Ox. For the Clang/llvm compiler, how can I find the compiler flag used by -Ox by default? And how to change or create a compilation flag combination?

-Ox isn’t an alias, it is the compiler flag in question. There’s no other way to get that optimisation pipeline.

For experimentation you can probably get close by splitting compilation up into phases:

  1. Use Clang to produce LLVM IR, clang whatever.c -Xclang -disable-llvm-passes -Os -emit-llvm -o whatever.bc (the optimization level doesn’t matter much here, since it mostly affects the passes you’ve told Clang not to run.
  2. Use the opt developer tool to run combinations of passes. This does have the ability to print which passes it’ll run and fiddle around. It’s not exactly the same list Clang would use, but close. Use something like opt -Os --print-pipeline-passes whatever.bc to get a starting-point.
  3. Finally, feed the optimized .bc back into Clang to generate a .o file.

FWIW, I do have a patch ( that makes clang -mllvm -print-pipeline-passes work without having to go through opt, since opt -Ox and clang -Ox aren’t necessarily the same.


Thank you. I use a separate helloworld. c for testing, which can separate the compilation and optimization stages. First, use opt to optimize the bc file, and then generate an executable file from the optimized bc file. However, if this is a project and there are many C files and S files in it, how to carry out this process? Should I first optimize each bc file and then combine these files, or first merge all bc files and then optimize it?

I experimented with a file in the project, but when opt it , it will report errors , the command I used and feedback as follow:

$ clang --target=riscv32-unknown-elf --sysroot=/opt/riscv/riscv32-unknown-elf --gcc-toolchain=/opt/riscv/ -x assembler-with-cpp  -DSYSTEM_CLOCK=108000000 -DSYSCLK_USING_HXTAL  -march=rv32imac -mabi=ilp32 -mcmodel=medlow  -ffunction-sections -fdata-sections -fno-common -DDOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP -DDOWNLOAD_MODE_STRING=\"FLASHXIP\"  -I/opt/riscv/riscv32-unknown-elf/include -I/opt/riscv/riscv32-unknown-elf/include/c++/12.2.0 -I/opt/riscv/riscv32-unknown-elf/include/c++/12.2.0/riscv32-unknown-elf -I/opt/riscv/riscv32-unknown-elf/include/c++/12.2.0/backward -I/opt/riscv/lib/gcc/riscv32-unknown-elf/12.2.0/include -I/opt/riscv/lib/gcc/riscv32-unknown-elf/12.2.0/include-fixed -I. -I../../../NMSIS/Core/Include -I../../../SoC/gd32vf103/Board/gd32vf103v_rvstar/Include -I../../../SoC/gd32vf103/Common/Include -Iinc -MMD -MT ../../../SoC/gd32vf103/Common/Source/GCC/intexc_gd32vf103.S.o -MF ../../../SoC/gd32vf103/Common/Source/GCC/intexc_gd32vf103.S.o.d -emit-llvm ../../../SoC/gd32vf103/Common/Source/GCC/intexc_gd32vf103.S -c -o test.bc

$ opt test.bc -O1 -o test1.bc
opt: test.bc:1:1: error: expected top-level entity
ELF��4]q������*�.�2�6�:�>�B�F���������s��~sP�~sж~s% 4�����Rs�B|�Rs�4�Rs�"4�@B�B2C�CRE�ErF�VW�WbX�XN�N&O�Oaas 0]q������*�.�2�6�:�>�B�F���������s��~sP�~sж~��~sp0�Rs�B|�Rs�4�Rs�"4�@B�B2C�CRE�ErF�VW�WbX�XN�N&O�Oaas 0�It�t
                                                         > t +>tt3+t-irq_entryexc_entry.textcore_exception_handlerdefault_intexc_handlerUndef_Handler.rela.text.irq.rela.text.trap.strtab.symtab.Ltmp0v�4k@�@f@�$

Is this error because there is a problem with the command I used to generate the bc file?

You can’t generate bitcode from assembly source (unfortunately!)

The best you can do in this situation is to take the assembly, wrap it in __asm { ... }, save it as a .c file, and compile that. Even so, you’ll just end up with a bitcode file consisting solely of module asm values.