This is the mail archive of the gcc@gcc.gnu.org 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: PR63633: May middle-end come up width hard regs for insn expanders?


Am 10/27/2014 08:43 PM, schrieb Jeff Law:
On 10/27/14 13:33, Georg-Johann Lay wrote:
Am 10/24/2014 08:29 PM, schrieb Jakub Jelinek:
On Fri, Oct 24, 2014 at 08:19:57PM +0200, Georg-Johann Lay wrote:
Yes, that's the straight forward approach which works so far.  Bit
tedious,
but well...

In one case expmed generated different code, though: divmodhi instead of
mulhi_highpart for HI division by const_int.  Cheating with costs did
not
help.  However for now I am mostly after correct, ICE-less code.

What I am concerned about is:

1) May it happen that a value lives in a hard-reg across the
expander? The
expander has no means to detect that situation and interfere, e.g.

hard-reg = source_value // middle-end
expand-code             // back-end
sink_value = hard-reg   // middle-end

where "expand-code" is one defind_expand / define_insn that clobbers /
changes (parts of) hard-reg but does *not* get hard-reg as operand.
This is
wrong code obviously.

It can happen, but if it happens, that would mean user code bug, like
using
register asm with an register that is unsuitable for use as global or
local
register var on the target, or it could be backend bug (expansion of some
pattern clobbering register that has other fixed uses).
You shouldn't ICE on it, but what happens is undefined.

Now I have a test case where exact that happens:

- An expander needs to clobber a hard register.
- That hard reg is live at that time and *not* used as operand to the
expander
- That hard reg is neither fixed nor a global register.
- That hard reg is neither used for argument passing nor for frame pointer
   or stack pointer and not for any exotic use like static chain etc.
So can you give more details about the live hard reg?  How did a value get into
that hard reg, how did it get used later? That's where I'd focus my efforts
since that probably shouldn't be happening except in very special circumstances.

The C test case is


__attribute__((noinline,noclone))
unsigned bug_mulhi_highpart (unsigned x)
{
    register unsigned reg26 asm ("26") = 10;
    a = x / 10;
    __asm volatile ("; %0 " : "+r" (reg26));
    return reg26;
}

int main (void)
{
    if (10 != bug_mulhi_highpart (0))
        __builtin_abort();
    return 0;
}


The specification guarantees reg26 to be allocated to R26/27 only at the time it is used as operand to the inline asm.

I am fine if the code above is no legal use of local register variables. However the question arises how a user writing such code can know that the generated code will be wrong?

As you told the compiler has no means to detect the situation as reg26 is not used as operand for divmod. Sometimes the middle-end generates mul_highpart instead so that a user cannot tell what registers are to be avoided even if he is familiar with GCC internals...

Johann


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