public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: question regarding asm()
@ 1997-10-28  8:31 Christian Iseli
  1997-10-28 10:25 ` Joern Rennecke
  1997-10-29  5:13 ` Bernd Schmidt
  0 siblings, 2 replies; 17+ messages in thread
From: Christian Iseli @ 1997-10-28  8:31 UTC (permalink / raw)
  To: crux, meissner; +Cc: law, rth, pcg, egcs

> Bernd Schmidt writes:
> | > Yup.  I wouldn't be suprised if this ends up being similar to the problems
> | > with passing args in registers for SMALL_REGISTER_CLASS machines.
> | 
> | I'd like to mention here that the reload patch I posted here a few months ago
> | does not only cause better code to be generated on the x86, it should also
> | solve these problems by taking hard register lifetimes into account and only
> | using free hard regs for reloads.
> 
> I hoped to start looking at this.  I am concerned about breaking the
> Linux kernel due to changing semantics.  Have you considered changing
> it so it still has the same semantics regarding input/output reloads?

*RAMBLING MODE ON*

I tried the patch and it seems to solve many problems for me.

I'm configuring GCC on a small embedded 8-bit microprocessor named CoolRISC
(< http://www.coolrisc.com/ > in case you want more info... :-)

We will be transfering the copyright of the whole thing to the FSF shortly, and send
the source for inclusion in the GCC and/or EGCS distributions, but
in case anybody wants a sneak preview, I can probably arrange that...

Anyway, I've come across quite a few stumbling blocks while developing this
back-end, and one of the major pain I have is with reload...

The first thing to say is that registers are scarce.  16 8-bit registers, of which
1 is unusable (status register) and 1 is an accumulator which gets clobbered by most
operations.  Adresses use 16 bits, and thus 2 registers are needed to hold one address.
4 groups of 2 registers can be used to reference memory.  One of those group is used
as the stack pointer, leaving 3 free groups, except when a frame pointer is needed...
Needless to say, a program compiled without -O (and thus needing a frame pointer) has
little chance of success.

So I have seen a lot of messages "Cannot find a register to spill"...

The usuall scenario goes thusly; we have a bunch of insns looking like so:
 1 (set (reg A) something)
 2 (set (reg B) (mem (plus (reg A) const)))
 3 (set (reg C) something)
 4 (set (reg D) (mem (plus (reg C) const)))
 5 (set (mem (plus (reg B) const))
        (some_op (mem (plus (reg B) const)) (mem (plus (reg D) const)))

Local-alloc does its thing and is able to allocate A and B to hard register P1
and C and D to hard register P2.

Now reload starts and pretty soon discovers that it has to spill hard register P1
to use it as a reload reg.  Things now look like this:
 1 (set (reg A) something)
 2 (set (reg B) (mem (plus (reg A) const)))
 3 (set (reg P2) something)
 4 (set (reg P2) (mem (plus (reg P2) const)))
 5 (set (mem (plus (reg B) const))
        (some_op (mem (plus (reg B) const)) (mem (plus (reg P2) const)))

Then, it comes back to insn 5 and calls
find_reloads.  The conclusion of find_reloads is that it will need four
address registers (of class ADDR_REGS), plus 2 optional reloads of the mem
parameters.  Strangely enough, all reloads end up being some form of input* reloads.
Since at most 3 address registers can be found, reload dies miserably.
Of course, by carefully looking at the RTL, it is clear that (in this example) 1
address registers would be enough.

I'm not yet sure how to teach reload to solve this problem.  In the meantime, I
tried Bernd's patch and it seems to solve (or avoid) partly the problem.  The
resulting compiler produced slightly better code, but died a few times with the
"forbidden register was spilled" message.  Most of the time, GCC was trying to
spill the (unneeded) frame pointer.  I applied a small patch to tell reload that
it's OK to spill the FP when it is not needed and now I'm left with only a few
cases where reload dies while trying to spill a forbidden (pseudo) register.

BTW, I use the PlumHall validation suite to test the compiler...  When I have a
little time, I'll try to use the GCC test suite.

*RAMBLING MODE OFF*

Bernd, does your patch try to address my reload problem, or is it merely a
side effect?  BTW, your patch does not apply cleanly on egcs-971023, the last
hunk of local-alloc.c fails.  I think the hunk below is correct though...

Seems I used enough bandwisth already...  Anybody care to comment on this?

Cheers,
					Christian


*************** block_alloc (b)
*** 1710,1726 ****
        {
  	for (i = qty_first_reg[q]; i >= 0; i = reg_next_in_qty[i])
  	  reg_renumber[i] = qty_phys_reg[q] + reg_offset[i];
- 	if (qty_scratch_rtx[q])
- 	  {
- 	    if (GET_CODE (qty_scratch_rtx[q]) == REG)
- 	      abort ();
- 
- 	    qty_scratch_rtx[q] = gen_rtx (REG, GET_MODE (qty_scratch_rtx[q]),
- 					  qty_phys_reg[q]);
- 
- 	    scratch_block[scratch_index] = b;
- 	    scratch_list[scratch_index++] = qty_scratch_rtx[q];
- 	  }
        }
  }
  \f
--- 1583,1588 ----


^ permalink raw reply	[flat|nested] 17+ messages in thread
* Re: question regarding asm()
@ 1997-12-09  7:28 Christian Iseli
  0 siblings, 0 replies; 17+ messages in thread
From: Christian Iseli @ 1997-12-09  7:28 UTC (permalink / raw)
  To: crux; +Cc: meissner, law, rth, pcg, egcs

Hello again...

I see one of your reload patches got into the latest snapshot... great!

I twiddled a little bit the other one (dated August 21...) and applied
it as well.  I still had some cases where the compiler stopped saying
"fixed or forbidden register was spilled...".  So I whipped up the
following kludge and now my test cases seem to compile fine (and run
fine too... :-)

Do you see anything blatantly wrong with this fix to your patch?

Thanks for your feedback,
					Christian

*** reload1.c.orig	Tue Dec  9 14:27:30 1997
--- reload1.c	Tue Dec  9 15:47:06 1997
*************** order_regs_for_reload (chain, global)
*** 1550,1563 ****
        hard_reg_n_uses[i].regno = i;
        hard_reg_n_uses[i].uses = 0;
  
!       if (fixed_regs[i] || i == HARD_FRAME_POINTER_REGNUM)
  	{
  	  SET_HARD_REG_BIT (bad_spill_regs, i);
  	  continue;
  	}
  
        regno = chain->inverse_renum_before[i];
!       if (regno < 0)
  	SET_HARD_REG_BIT (bad_spill_regs, i);
        else if (regno > 0 && ! REGNO_REG_SET_P (spilled_pseudos, regno))
  	{
--- 1550,1566 ----
        hard_reg_n_uses[i].regno = i;
        hard_reg_n_uses[i].uses = 0;
  
!       if (fixed_regs[i]
! 	  || (i == HARD_FRAME_POINTER_REGNUM
! 	      && (!SMALL_REGISTER_CLASSES
! 		  || frame_pointer_needed)))
  	{
  	  SET_HARD_REG_BIT (bad_spill_regs, i);
  	  continue;
  	}
  
        regno = chain->inverse_renum_before[i];
!       if (regno < 0 && !SMALL_REGISTER_CLASSES)
  	SET_HARD_REG_BIT (bad_spill_regs, i);
        else if (regno > 0 && ! REGNO_REG_SET_P (spilled_pseudos, regno))
  	{
*************** order_regs_for_reload (chain, global)
*** 1571,1577 ****
  	}
  
        regno = chain->inverse_renum_after[i];
!       if (regno < 0)
  	SET_HARD_REG_BIT (bad_spill_regs, i);
        else if (regno > 0 && ! REGNO_REG_SET_P (spilled_pseudos, regno)
  	       && regno != chain->inverse_renum_before[i])
--- 1574,1580 ----
  	}
  
        regno = chain->inverse_renum_after[i];
!       if (regno < 0 && !SMALL_REGISTER_CLASSES)
  	SET_HARD_REG_BIT (bad_spill_regs, i);
        else if (regno > 0 && ! REGNO_REG_SET_P (spilled_pseudos, regno)
  	       && regno != chain->inverse_renum_before[i])

^ permalink raw reply	[flat|nested] 17+ messages in thread
* Re: question regarding asm()
@ 1997-10-29  9:17 Christian Iseli
  0 siblings, 0 replies; 17+ messages in thread
From: Christian Iseli @ 1997-10-29  9:17 UTC (permalink / raw)
  To: crux; +Cc: meissner, law, rth, pcg, egcs

Thanks for the feedback.

> (parallel
>  (set (mem:DI (plus:SI (reg:SI r1) (reg:SI r2)))
>       (plus:DI (mem:DI (plus:SI (reg:SI r3) (reg:SI r4)))
>                (mem:DI (plus:SI (reg:SI r5) (reg:SI r6)))))
>  (clobber (reg:SI r7)))

Yup, this looks familiar... :-)  In my case it's SI mode, with
a single register in the address (plus a const), but it's probably
the same problem.

Any idea how to "improve" find_reloads anyone? :-) :-)

					Christian

^ permalink raw reply	[flat|nested] 17+ messages in thread
* Re: question regarding asm()
@ 1997-10-29  2:28 Christian Iseli
  0 siblings, 0 replies; 17+ messages in thread
From: Christian Iseli @ 1997-10-29  2:28 UTC (permalink / raw)
  To: amylaar; +Cc: crux, pcg, egcs

> You should rather use an extra hard register number for the frame pointer,
> and then eliminate this frame pointer either to the hard frame pointer or
> to the stack.
         ^^^^^
(I guess you mean the stack pointer...)

Hmm...  That's what I'm doing already.  reload, at least with Bernd's
patch applied, puts the HARD_FRAME_POINTER_REGNO in the bad_spill_regs,
even when frame_pointer_needed is 0.  That's what I patched...

					Christian

^ permalink raw reply	[flat|nested] 17+ messages in thread
* question regarding asm()
@ 1997-10-07 23:14 Marc Lehmann
  1997-10-09  9:26 ` dtm
  1997-10-15 21:03 ` Jeffrey A Law
  0 siblings, 2 replies; 17+ messages in thread
From: Marc Lehmann @ 1997-10-07 23:14 UTC (permalink / raw)
  To: egcs

Sorry to post this question again, but my last e-mail was definitely ignored,
and the documentation still is wrong.... (And I still have no idea
how, for example, kernel people are supposed to tell gcc NOT to
use some registers in an asm that are used in an asm...)

----- Forwarded message from Marc Lehmann -----

David Edelsohn wrote:
>	Clobber just means that GCC cannot make assumptions about the
>register after the call, not before.

That's what I expected, but the docs seems to sugest otherwise..

>You explicitly use r9 and r10 in your pattern but never tell GCC.  The
>pattern should list r9 and r10 as

It's not "my" pattern, it is taken as an example from the gcc info files, so
the documentation is wrong and should be fixed.

>inputs so that GCC knows not to touch them.  In fact you should leave the
>destinations as open register but make those required inputs so that GCC
>fills them in during register allocation.

The problem is that one cannot on all ports of gcc select
specific registers as input (in that case, r9), but
only register classes.

How am I supposed to tell gcc that (say..) register r13 is NOT to be used as
input in an asm when the target machine has no constraint specificly for
r13? (on the x86 you have almost one class per reg, so that's not a problem,
but this is not true for %ebp... there is NO way to tell gcc NOT to use %ebp
as an input operand, or do I miss sth.?)

      -----==-
      ----==-- _
      ---==---(_)__  __ ____  __       Marc Lehmann
      --==---/ / _ \/ // /\ \/ /       pcg@goof.com
      -=====/_/_//_/\_,_/ /_/\_\
    The choice of a GNU generation

----- End of forwarded message from Marc Lehmann -----

^ permalink raw reply	[flat|nested] 17+ messages in thread
[parent not found: <9710040128.AA17540@rios1.watson.ibm.com>]
* question regarding asm()
@ 1997-10-03 18:13 Marc Lehmann
  0 siblings, 0 replies; 17+ messages in thread
From: Marc Lehmann @ 1997-10-03 18:13 UTC (permalink / raw)
  To: egcs

in the info file, this asm is given as an example of specifying registers to
be clobbered:

>     asm ("movl %0,r9;movl %1,r10;call _foo"
>          : /* no outputs */
>          : "g" (from), "g" (to)
>          : "r9", "r10");

Now I have a question.. is gcc supposed to avoid allocating r9 to %1 ??

in fact, gcc tries to avoid allocating "clobbered" registers for input operands,
but if there are no registers left gcc will nevertheless use them.

So, under register pressure, gcc might use r9 for input operand %1.

There was a problem in the linux kernel because egcs allocated
a register for an input operand that was also in the clobberlist
(and actually was overwritten before the input operand was used).

so whats wrong?

a) the example in the documentation
b) gcc, because it allocates wrong registers for the input operands
c) me, because I'm totally confused tonight..

;?

      -----==-
      ----==-- _
      ---==---(_)__  __ ____  __       Marc Lehmann
      --==---/ / _ \/ // /\ \/ /       pcg@goof.com
      -=====/_/_//_/\_,_/ /_/\_\
    The choice of a GNU generation

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~1997-12-09  7:28 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-10-28  8:31 question regarding asm() Christian Iseli
1997-10-28 10:25 ` Joern Rennecke
1997-10-29  5:13 ` Bernd Schmidt
  -- strict thread matches above, loose matches on Subject: below --
1997-12-09  7:28 Christian Iseli
1997-10-29  9:17 Christian Iseli
1997-10-29  2:28 Christian Iseli
1997-10-07 23:14 Marc Lehmann
1997-10-09  9:26 ` dtm
1997-10-15 21:03 ` Jeffrey A Law
1997-10-16  8:31   ` Richard Henderson
1997-10-16 15:19     ` Jeffrey A Law
1997-10-17  1:22       ` Bernd Schmidt
1997-10-17 12:44         ` Jeffrey A Law
1997-10-17 12:53         ` Michael Meissner
1997-10-20  4:29           ` Bernd Schmidt
     [not found] <9710040128.AA17540@rios1.watson.ibm.com>
1997-10-04  6:04 ` Marc Lehmann
1997-10-03 18:13 Marc Lehmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).