Am 27.06.24 um 10:51 schrieb Stefan Schulze Frielinghaus:
On Thu, Jun 27, 2024 at 09:45:32AM +0200, Georg-Johann Lay wrote:
Am 24.05.24 um 11:13 Am 25.06.24 um 16:03 schrieb Paul Koning:
On Jun 24, 2024, at 1:50 AM, Stefan Schulze Frielinghaus 
<stefa...@linux.ibm.com> wrote:
On Mon, Jun 10, 2024 at 07:19:19AM +0200, Stefan Schulze Frielinghaus wrote:
On Fri, May 24, 2024 at 11:13:12AM +0200, Stefan Schulze Frielinghaus wrote:
This implements hard register constraints for inline asm.  A hard register
constraint is of the form {regname} where regname is any valid register.  This
basically renders register asm superfluous.  For example, the snippet

int test (int x, int y)
{
   register int r4 asm ("r4") = x;
   register int r5 asm ("r5") = y;
   unsigned int copy = y;
   asm ("foo %0,%1,%2" : "+d" (r4) : "d" (r5), "d" (copy));
   return r4;
}

could be rewritten into

int test (int x, int y)
{
   asm ("foo %0,%1,%2" : "+{r4}" (x) : "{r5}" (y), "d" (y));
   return x;
}

I like this idea but I'm wondering: regular constraints specify what sort of 
value is needed, for example an int vs. a short int vs. a float.  The notation 
you've shown doesn't seem to have that aspect.

The other comment is that I didn't see documentation updates to reflect this 
new feature.

        paul

  Stefan Schulze Frielinghaus:
This implements hard register constraints for inline asm.  A hard register
constraint is of the form {regname} where regname is any valid register.  This
basically renders register asm superfluous.  For example, the snippet

int test (int x, int y)
{
    register int r4 asm ("r4") = x;
    register int r5 asm ("r5") = y;
    unsigned int copy = y;
    asm ("foo %0,%1,%2" : "+d" (r4) : "d" (r5), "d" (copy));
    return r4;
}

could be rewritten into

int test (int x, int y)
{
    asm ("foo %0,%1,%2" : "+{r4}" (x) : "{r5}" (y), "d" (y));
    return x;
}

Hi, can this also be used in machine descriptions?

It would make some insn handling much simpler, for example in
the avr backend.

That backend has insns that represent assembly sequences in libgcc
which have a smaller register footprint than plain calls.  However
this requires that such insns have explicit description of which regs
go in and out.

The current solution uses hard regs, which works, but a proper
implementation would use register constraints.  I tries that a while
ago, and register constraints lead to a code bloat even in places that
don't use these constraints due to the zillions of new register classes
like R22_1, R22;2, R22_4, R20_1, R20_2, R20_4 etc. that were required.

Your approach would allow to use hard register constraints in insns,
and so far the only problem is to determine how much hard regs are
used by the constraint.  The gen tools that generates cc code from md
would use the operand's machine mode to infer the number of hard regs.

I have this on my todo list but ignored it for the very first draft.  At
the moment this already fails because genoutput cannot parse the
constraint format.

In my "alpha draft" I implemented this feature by emitting moves to hard
registers during expand.  This had the limitation that I couldn't

One problem is that you cannot just introduce hard registers at that
time because a hard reg may live across the sequence, see for example
avr.cc::avr_emit3_fix_outputs() and avr_fix_operands().

support multiple alternatives in combination with hard-register
constraints.  I'm still not sure whether this is a feature we really
want or whether it should be rather denied.  Anyhow, with this kind of
implementation I doubt that this would be feasible for machine
descriptions.  I moved on with my current draft where the constraint
manifests during register allocation.  This also allows multiple
alternatives.  I think one of the (major?) advantages of doing it this
way is that operands are kept in pseudos which means they are
automagically saved/restored over function boundaries and what not.  Or
in other words, the register constraint manifests at the asm boundary
which is probably what users expect and should be less error prone

As far as I know, a local register variable is only supposed to be
loaded to the specified register when the variable is used as an
operand to some inline asm.  Only in such asm statements, the
variable will live in the specified register.  So "surviving" a
function call is not even a problem to solve with the current local
regvar semantic?

(again just thinking of implicit code which gets injected as e.g. by
sanitizers introducing calls etc.).

So long story short, I would like to look into this but currently it
doesn't work.  I'm also not sure to which extend this could be used.
However, once I have some more time I will have a look at the avr
backend for examples.

Cheers,
Stefan

Great.  When you have any questions about the avr backend, don't
hesitate to ask me.

Cheers,
Johann

Reply via email to