Jakub Jelinek <ja...@redhat.com> writes: > On Tue, Feb 04, 2014 at 12:21:14PM +0000, Richard Sandiford wrote: >> Jakub Jelinek <ja...@redhat.com> writes: >> >> But then we wouldn't be able to use var-tracking when __builtin_eh_return >> >> is used, since in that case replacing the (set (reg ...) (mem ...)) >> >> with a (plus ...) would be incorrect -- the value we're loading from the >> >> stack will have had a variable adjustment applied. And I know from >> >> painful >> >> experience that being able to debug the unwind code is very useful. :-) >> > >> > Aren't functions using EH_RETURN typically using frame pointer? >> >> Sorry, forgot to respond to this bit. On s390, _Unwind_RaiseException and >> _Unwind_ForcedUnwind don't use a frame pointer, at least not on trunk. >> %r11 is used as a general scratch register instead. E.g.: >> >> 00002ba8 <_Unwind_ForcedUnwind>: >> 2ba8: 90 6f f0 18 stm %r6,%r15,24(%r15) >> 2bac: 0d d0 basr %r13,%r0 >> 2bae: 60 40 f0 50 std %f4,80(%r15) >> 2bb2: 60 60 f0 58 std %f6,88(%r15) >> 2bb6: a7 fa fd f8 ahi %r15,-520 >> 2bba: 58 c0 d0 9e l %r12,158(%r13) >> 2bbe: 58 10 d0 9a l %r1,154(%r13) >> 2bc2: 18 b2 lr %r11,%r2 >> ... >> 2c10: 98 6f f2 20 lm %r6,%r15,544(%r15) >> 2c14: 07 f4 br %r4 > > Looking at pr54693-2.c -O2 -g -m64 -march=z196 (was that the one you meant) > with your patches, I see: > (insn/f:TI 122 30 31 4 (parallel [ > (set/f (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 80 [0x50])) [3 S8 A8]) > (reg:DI 10 %r10)) > (set/f (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 88 [0x58])) [3 S8 A8]) > (reg:DI 11 %r11)) > (set/f (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 96 [0x60])) [3 S8 A8]) > (reg:DI 12 %r12)) > (set/f (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 104 [0x68])) [3 S8 A8]) > (reg:DI 13 %r13)) > (set/f (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 112 [0x70])) [3 S8 A8]) > (reg:DI 14 %r14)) > (set/f (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 120 [0x78])) [3 S8 A8]) > (reg/f:DI 15 %r15)) > ]) pr54693-2.c:16 94 {*store_multiple_di} > (expr_list:REG_DEAD (reg:DI 14 %r14) > (expr_list:REG_DEAD (reg:DI 13 %r13) > (expr_list:REG_DEAD (reg:DI 12 %r12) > (expr_list:REG_DEAD (reg:DI 11 %r11) > (expr_list:REG_DEAD (reg:DI 10 %r10) > (nil))))))) > ... > (insn/f 123 31 124 4 (set (reg/f:DI 15 %r15) > (plus:DI (reg/f:DI 15 %r15) > (const_int -160 [0xffffffffffffff60]))) pr54693-2.c:16 65 {*la_64} > (expr_list:REG_FRAME_RELATED_EXPR (set (reg/f:DI 15 %r15) > (plus:DI (reg/f:DI 15 %r15) > (const_int -160 [0xffffffffffffff60]))) > (nil))) > ... > (insn/f:TI 135 134 136 7 (parallel [ > (set (reg:DI 10 %r10) > (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 240 [0xf0])) [3 S8 A8])) > (set (reg:DI 11 %r11) > (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 248 [0xf8])) [3 S8 A8])) > (set (reg:DI 12 %r12) > (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 256 [0x100])) [3 S8 A8])) > (set (reg:DI 13 %r13) > (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 264 [0x108])) [3 S8 A8])) > (set (reg:DI 14 %r14) > (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 272 [0x110])) [3 S8 A8])) > (set (reg/f:DI 15 %r15) > (mem:DI (plus:DI (reg/f:DI 15 %r15) > (const_int 280 [0x118])) [3 S8 A8])) > ]) pr54693-2.c:25 92 {*load_multiple_di} > (expr_list:REG_CFA_DEF_CFA (plus:DI (reg/f:DI 15 %r15) > (const_int 160 [0xa0])) > (expr_list:REG_CFA_RESTORE (reg/f:DI 15 %r15) > (expr_list:REG_CFA_RESTORE (reg:DI 14 %r14) > (expr_list:REG_CFA_RESTORE (reg:DI 13 %r13) > (expr_list:REG_CFA_RESTORE (reg:DI 12 %r12) > (expr_list:REG_CFA_RESTORE (reg:DI 11 %r11) > (expr_list:REG_CFA_RESTORE (reg:DI 10 %r10) > (nil))))))))) > In a function that doesn't need frame pointer, I'd say this is a serious > bloat of the unwind info, you are saving/restoring %r15 not because you have > to, but just that it seems to be cheaper for the target. So, I'd say you > shouldn't emit DW_CFA_offset 15, 5 on the insn 122 in the prologue and > DW_CFA_restore 15 in the epilogue (twice in this case), that just waste > of .eh_frame/.debug_frame space. I'd say you should represent in > this case the *store_multiple_di as REG_FRAME_RELATED_EXPR > with all but the last set in the PARALLEL, and on the *load_multiple_di > remove REG_CFA_RESTORE (r15) note and change REG_CFA_DEF_CFA note to > REG_CFA_ADJUST_CFA note which would say that stack pointer has been > incremented by 160 bytes (epilogue expansion knows that value). > > Then just handle REG_CFA_ADJUST_CFA note in > insn_stack_adjust_offset_pre_post. Handling REG_CFA_DEF_CFA > note there would be harder (as you need to know the current cfa at that > point), so perhaps just punt there if you see REG_CFA_DEF_CFA note.
What do you want var-tracking to do about the __builtin_eh_return case though? It isn't correct to say that the instruction adds the frame size to the stack pointer then, since the loaded value includes the eh_return adjustment. Pretending it is a constant addition in order to satisfy the sanity check seems a bit hackish, but there again it'd be a shame to lose tracking for the whole function just because of that. Thanks, Richard