This patch introduces a new option mfs-split-ehcode. This will push all code reachable only from landing pad into cold code
Test Plan:
llvm-lit --show-all llvm/test/CodeGen/X86/machine-function-splitter.ll
Also tested on file
using namespace std; class MyException{}; class Dummy { public: Dummy(string s) : MyName(s) { PrintMsg("Created Dummy:"); } Dummy(const Dummy& other) : MyName(other.MyName){ PrintMsg("Copy created Dummy:"); } ~Dummy(){ PrintMsg("Destroyed Dummy:"); } void PrintMsg(string s) { cout << s << MyName << endl; } string MyName; int level; }; void C(Dummy d, int i) { cout << "Entering FunctionC" << endl; d.MyName = " C"; throw MyException(); cout << "Exiting FunctionC" << endl; } void B(Dummy d, int i) { cout << "Entering FunctionB" << endl; d.MyName = "B"; C(d, i + 1); cout << "Exiting FunctionB" << endl; } void A(Dummy d, int i) { cout << "Entering FunctionA" << endl; d.MyName = " A" ; // Dummy* pd = new Dummy("new Dummy"); //Not exception safe!!! B(d, i + 1); // delete pd; cout << "Exiting FunctionA" << endl; } int main() { cout << "Entering main" << endl; try { throw(1); } catch (MyException& e) { cout << "Caught an exception of type: " << typeid(e).name() << endl; } catch(int b){ cout << "Caught b = " << b << endl; } cout << "Exiting main." << endl; }
Got the output:
Entering main Created Dummy: M Copy created Dummy: M Entering FunctionA Copy created Dummy: A Entering FunctionB Copy created Dummy:B Entering FunctionC Destroyed Dummy: C Destroyed Dummy:B Destroyed Dummy: A Destroyed Dummy: M Caught an exception of type: 11MyException Exiting main.
Command used to compile: clang++ hello-wrold.cpp -fsplit-machine-functions -mllvm -mfs-split-ehcode -fuse-ld=lld -Wl, -z keep-text-section-prefix
objdump on sections:
Sections: Idx Name Size VMA Type 0 00000000 0000000000000000 1 .interp 0000001c 00000000002002a8 DATA 2 .note.ABI-tag 00000020 00000000002002c4 3 .dynsym 000002a0 00000000002002e8 4 .gnu.version 00000038 0000000000200588 5 .gnu.version_r 00000080 00000000002005c0 6 .gnu.hash 00000030 0000000000200640 7 .hash 000000e8 0000000000200670 8 .dynstr 000003b8 0000000000200758 9 .rela.dyn 00000090 0000000000200b10 10 .rela.plt 000001f8 0000000000200ba0 11 .rodata 00000108 0000000000200d98 DATA 12 .gcc_except_table 00000134 0000000000200ea0 DATA 13 .eh_frame_hdr 000000b4 0000000000200fd4 DATA 14 .eh_frame 0000031c 0000000000201088 DATA 15 .text 000005f5 00000000002023b0 TEXT 16 .text.hot 00000000 00000000002029a5 TEXT 17 .text.unlikely 00000000 00000000002029a5 TEXT 18 .text.startup 0000004b 00000000002029b0 TEXT 19 .text.exit 00000000 00000000002029fb TEXT 20 .init 0000001b 00000000002029fc TEXT 21 .fini 0000000d 0000000000202a18 TEXT 22 .text.split 000001fe 0000000000202a25 TEXT <----- split section 23 .plt 00000160 0000000000202c30 TEXT 24 .fini_array 00000008 0000000000203d90 25 .init_array 00000010 0000000000203d98 26 .dynamic 000001c0 0000000000203da8 27 .got 00000020 0000000000203f68 DATA 28 .bss.rel.ro 00000058 0000000000203f88 BSS 29 .data 00000004 0000000000204fe0 DATA 30 .tm_clone_table 00000000 0000000000204fe8 DATA 31 .got.plt 000000c0 0000000000204fe8 DATA 32 .bss 00000130 00000000002050c0 BSS 33 .comment 000000c7 0000000000000000 34 .gnu.build.attributes 000007f8 0000000000000000 35 .gnu.build.attributes.hot 00000570 0000000000000000 36 .gnu.build.attributes.unlikely 00000570 0000000000000000 37 .gnu.build.attributes.startup 00000570 0000000000000000 38 .gnu.build.attributes.exit 00000570 0000000000000000 39 .symtab 00000b10 0000000000000000 40 .shstrtab 000001ef 0000000000000000 41 .strtab 00000b5e 0000000000000000
Almost 33% code moved to text.split from .text for above file
Current testing ongoing on HVVM ongoing
Objdump of clang produced after compiling llvm with clang generated from above changes (Notice the text.split section):
FILE SIZE VM SIZE -------------- -------------- 31.7% 250Ki 0.0% 0 .strtab 23.1% 182Ki 40.9% 182Ki .text 11.4% 89.8Ki 20.2% 89.8Ki .eh_frame 10.6% 84.2Ki 0.0% 0 .symtab 7.5% 59.0Ki 13.2% 59.0Ki .dynstr 2.8% 21.9Ki 4.9% 21.9Ki .eh_frame_hdr 2.5% 19.6Ki 4.4% 19.6Ki .dynsym 2.2% 17.1Ki 3.8% 17.1Ki .rodata 1.5% 12.2Ki 2.7% 12.2Ki .gcc_except_table 1.3% 10.3Ki 2.3% 10.3Ki .text.split. <---- 1.5% text.split 1.2% 9.19Ki 2.1% 9.19Ki .rela.plt 0.9% 7.03Ki 0.8% 3.64Ki [20 Others] 0.8% 6.55Ki 1.5% 6.55Ki .hash 0.8% 6.14Ki 1.4% 6.14Ki .plt 0.4% 3.09Ki 0.7% 3.09Ki .got.plt 0.4% 3.05Ki 0.7% 3.05Ki .gnu.hash 0.3% 2.62Ki 0.0% 0 [ELF Section Headers] 0.3% 1.99Ki 0.0% 0 .gnu.build.attributes 0.2% 1.64Ki 0.4% 1.64Ki .gnu.version 0.2% 1.36Ki 0.0% 0 .gnu.build.attributes.exit 0.2% 1.36Ki 0.0% 0 .gnu.build.attributes.hot 100.0% 790Ki 100.0% 445Ki TOTAL
Used this clang and verified functionality by adding try catch inside clang
terminate called after throwing an instance of 'int'
0. Program arguments: ../bin/clang++ archit.cpp #0 0x00007f69116866c3 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/data/users/archsaxe/server-llvm/llvm-project/build3/bin/../lib/libLLVMSupport.so.15git+0x24e6c3) #1 0x00007f69116844ee llvm::sys::RunSignalHandlers() (/data/users/archsaxe/server-llvm/llvm-project/build3/bin/../lib/libLLVMSupport.so.15git+0x24c4ee) #2 0x00007f6911686b6f SignalHandler(int) Signals.cpp:0:0 #3 0x00007f6914a4fce0 __restore_rt (/lib64/libpthread.so.0+0x12ce0) #4 0x00007f6910791a4f raise (/lib64/libc.so.6+0x4ea4f) #5 0x00007f6910764db5 abort (/lib64/libc.so.6+0x21db5) #6 0x00007f691113309b (/lib64/libstdc++.so.6+0x9009b) #7 0x00007f691113953c (/lib64/libstdc++.so.6+0x9653c) #8 0x00007f6911139597 (/lib64/libstdc++.so.6+0x96597) #9 0x00007f69111397f8 (/lib64/libstdc++.so.6+0x967f8) Aborted (core dumped)
After adding catch blocks above errors got resolved