Hi, On Fri, 26 Aug 2016, Bernd Schmidt wrote:
> And that comment puzzles me. Surely prologue and epilogue are executed only > once currently, so how does frequency come into it? Again - please provide an > example. int some_global; int foo (void) { if (!some_global) { call_this(); call_that(); x = some + large / computation; while (x--) { much_more_code(); } some_global = 1; } return some_global; } Now you need the full pro/epilogue (saving/restoring all call clobbered regs presumably used by the large computation and loop) for only one call of that function (the first), and then never again. But you do need a part of it always assuming the architecture is right, and this is a shared library, namely the setup of the PIC pointer for the access to some_global. A prologue does many things, and in some cases many of them aren't necessary for all calls (indeed that's often the case for functions containing early-outs), so much so that the full prologue including unnecessary parts needs more time than the functional body of a functions particular call. It's obvious that it would be better to move those parts of the prologue to places where they actually are needed: int f2 (void) { setup_pic_reg(); if (!some_global) { save_call_clobbers(); code_from_above(); restore_call_clobbers(); } retreg = some_global; restore_pic_reg(); } That includes moving parts of the prologue into loops: int g() { int sum = 0; for (int i = 0; i < NUM; i++) { sum += i; if (sum >= CUTOFF) { some_long_winded_expression(); that_eventually_calls_abort(); } } return sum; } Here all parts of the prologue that somehow make it possible to call other functions are necessary only when the program will abort eventually: hence is necessary only at one call of g() at most. Again it's sensible to move those parts inside the unlikely condition, even though it's inside a loop. Ciao, Michael.