My architecture is MicroBlaze, and I'm developing on the Xilinx ZCU102. The C++ version is 17. I built the code on Vitis 2022.2 version.
My original code had a .text section of only 60,000 bytes. After porting to C++, it increased to 180,000 bytes. I referred to this article and added the following two flags in CMake, but the effect was limited.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
I also added the following function, but it still didn't help.
extern "C" void __cxa_pure_virtual() { while(1); }
Next, I used this GitHub ELF analyzer to analyze it, and many functions appeared that I had never seen before porting c++ code.
$ elf-size-analyze -t mb- my.elf --rom -H
...
? 144.6 KiB 81.43
d_print_comp_inner 13.2 KiB 7.45
_svfprintf_r 10.9 KiB 6.15
_dtoa_r 6.8 KiB 3.84
_vfiprintf_r 5.5 KiB 3.08
_svfiprintf_r 4.8 KiB 2.70
d_type 3.2 KiB 1.78
execute_cfa_program 2.7 KiB 1.50
d_expression_1 2.4 KiB 1.35
execute_stack_op 2.4 KiB 1.34
d_print_mod 2.2 KiB 1.24
_malloc_r 2.2 KiB 1.23
__divdi3 2.0 KiB 1.10
__udivdi3 1.9 KiB 1.06
d_special_name 1.9 KiB 1.05
__moddi3 1.9 KiB 1.05
__umoddi3 1.8 KiB 1.00
search_object 1.8 KiB 0.99
d_demangle_callback.constprop.0 1.7 KiB 0.94
_realloc_r 1.6 KiB 0.91
d_unqualified_name 1.6 KiB 0.88
__sfvwrite_r 1.3 KiB 0.74
d_name 1.2 KiB 0.70
cplus_demangle_operators 1.1 KiB 0.64
uw_frame_state_for 1.1 KiB 0.64
d_maybe_print_fold_expression 1.0 KiB 0.57
uw_update_context_1 1.0 KiB 0.57
__malloc_av_ 1.0 KiB 0.57
XpbrServExtTbl 1.0 KiB 0.56
...
How can I reduce the size of my code? Thank you very much.
--- update ---
When I gradually commented out portions of my code to identify what caused a significant increase in the size of my .text section, I found that by removing the following code, my .text size reverted to 60000 bytes. However, I'm at a loss. Does C++ vector emplace_back do something specific?
template <typename T> using VEC = std::vector<T>;
using vecf = VEC<double>;
vecf delay_ns;
for (size_t i = 0; i < 10; i++) {
delay_ns.emplace_back(2.0);
}
-Osinstead of some other optimization level?newexpressions at all (directly or indirectly) that can force the executable to still have code for exception handling (sinceoperator new(), by default, still throws exceptions). This includes using standard containers since their default allocators usenewexpressions.std::vector::emplace_back()resizes the vector which (e.g. ifstd::vector::capacity()is less than the newstd::vector::size()) results in increasing the vector's capacity (number of elements it can contain without reallocation), which is done using the vector's allocator, which (by default) uses anewexpression, which (by default) can throw an exception - which can force the executable to still have code for exception handling.std::vectorconstructs an empty container with a default-constructed allocator - it's not unimaginable that the act of default-constructing a vector will not execute anynewexpression, so not (on its own) force the executable to have exception handling code, but a later call ofemplace_back()of that vector might. Dunno - it's the OP who reported (previous comment) isolating his concern to a usage ofemplace_back()and, since representative code isn't given, all we can do is speculate.