This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PUSH and POP next to first/last register use

Thank you Jim and Paolo for your answers.

Acctually I do not need to worry about the order in which the pushes and pops are done, as these would be taken care of in the special assembler I am using. All I need in the output assembly is to have the PUSH appearing before the first time the reg is used and the POP just after the last time it is used. The reason is that the (simple) assembler I am using operates on each basic-block seperately and it would be confused to see a PUSH of a register without seeing that register being used.

Here is what I did to implement this 'shrink-wrapping'; however I am getting errors:

I increased the number of registers from 32 to 64, with the last 32 being a unallocatable by gcc (FIXED_REGISTERS is set high). In the proglogue and epilogue I emit the following moves:

emit_move_insn (gen_rtx_REG (SImode, regno+32), gen_rtx_REG (SImode, regno));
emit_move_insn (gen_rtx_REG (SImode, regno), gen_rtx_REG (SImode, regno+32));

My intetion was then to create a special case in the machine description where all the MOVES to a ref above 32 are printed as "PUSH" and anything MOVES from a reg above 32 become "POP". However, having the previous definitions in the pro and epilogue crash the compiler with:

internal compiler error: in final, at final.c:1569

Many thanks for your help!

Sami Khawam

The University of Edinburgh

Paolo Bonzini wrote:

 > I suppose this would require using REGNO_FIRST_UID(N) and
 > REGNO_LAST_UID(N) at some point, however I would be very grateful if
 > you can help me with it, as it seems that REGNO_FIRST_UID(N) is still
 > reset to 0 when TARGET_ASM_FUNCTION_PROLOGUE is called.

REGNO_FIRST_UID and REGNO_LAST_UID are set by reg_scan (see passes.c), but they do not take into account the CFG -- i.e. REGNO_FIRST_UID is not guaranteed to dominate all uses, and REGNO_LAST_UID is not guaranteed to postdominate them.

Using them is almost never the right thing to do -- witness the fact that there are only three users in the whole of gcc's middle-end:

1) in CSE, and it is just a way to pick an order for registers

2) in initialize_uninitialized_subregs, and only as an optimization to skip insns that surely don't refer to a reg.

3) loop.c, which is 9000 lines of complex code with a lot of heuristics that were designed two major releases ago -- a lot of things changed since then, and loop.c is going to be removed sooner or later.

What you want to do would mean multiple pushes or pops, right? You may want to do a dominator/postdominator walk, it is quite cheap in HEAD.


This is called "shrink-wrapping". I would think this works best if you emit the saves/restores into the prologue/epilogue, and then run a shrink-wrapping optimization pass that tries to move them inward as far as you can.

This should be feasible for store/load instructions, but for push/pop this will be complicated. This will change stack offsets, so it will interfere with frame pointer elimination. You need to worry about other things that change the stack, like alloca and Variable Length Array allocations and deallocations. You will need to worry about the -fdefer-pop optimization, as that may leave the stack unbalanced for some sections of code. And of course if you have overlapping register lifetimes, then the push/pops for those registers will conflict. You either have to use the union of the register lifetimes for both registers, or else only shrink-wrap one of them. This all sounds like more trouble than it is worth for a target that uses push/pop for register saves and restores.
Jim Wilson, GNU Tools Support,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]