public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* C++: Letting compiler know asm block can call function that can throw?
@ 2012-03-29  7:05 Stephan Bergmann
  2012-03-29  7:44 ` Jakub Jelinek
  2012-03-29 16:14 ` Richard Henderson
  0 siblings, 2 replies; 22+ messages in thread
From: Stephan Bergmann @ 2012-03-29  7:05 UTC (permalink / raw)
  To: gcc

Hi all,

In LibreOffice's ever-beloved low-level code to synthesize calls to C++ 
virtual functions, I'm having the following problem (on Linux x86_64). 
The function callVirtualMethod at 
<http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61> 
effectively does the following:

First, call dummy_can_throw_anything that can potentially throw (see 
below for why that's there).  Second, in an asm block, call some virtual 
function (that can potentially throw).  Third, call x86_64::fill_struct 
that can potentially throw (it doesn't, but nobody bothered to annotate 
it as "throw ()").

Now, at least GCC 4.7.0 with -O0 produces a .gcc_except_table section 
for callVirtualMethod, with two call-site table entries each spanning 
the first (dummy_can_throw_anything) and third (x86_64::fill_struct) 
calls, resp., but none spanning the second (asm block) call.  These 
entries are effectively nop, simply calling back into _Unwind_Resume, 
and compiling at higher optimization levels leaves them out anyway 
(leading to callVirtualMethod having no corresponding .gcc_except_table 
section).

The problem is that if the virtual function called through the asm block 
throws an exception, that then immediately leads to std::terminate.  My 
understanding is that because the ip is at the call instruction in the 
asm block that is between the two call-site table entries, the unwind 
machinery thinks this cannot happen and bails out.  (When compiled -O2, 
the code happens to work fine, as there is no .gcc_except_table section 
for this frame at all, so unwinding simply passes through it without 
calling the personality function.)

Making sure that there are no calls to (compiler-visible) functions that 
can throw within callVirtualMethod would happen to make the code also 
work with -O0.  But that would remain a fragile solution.

Is there a way to let the compiler know that the asm block potentially 
calls functions that can throw?  So that it could emit correct code, 
regardless of whether callVirtualMethod happens to have a corresponding 
.gcc_except_table section or not.

(The call to dummy_can_throw_anything, copied from the corresponding 
older code for 32-bit x86, is there for the following reason:  At least 
with some compiler version and some optimization level, on x86 it was 
discovered that the compiler did not emit the .eh_frame data necessary 
for unwinding to successfully pass through this frame at all.  As the 
corresponding x86 code does not have a call to x86_64::fill_struct, the 
compiler apparently considered callVirtualMethod a leaf function and 
optimized accordingly.  The dummy_can_throw_anything hack happened to 
make it do the right thing again, but again this is a fragile solution, 
anyway, that could be replaced with something robust if there were a way 
to annotate the asm block as "calls functions that can throw.")

Stephan

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29  7:05 C++: Letting compiler know asm block can call function that can throw? Stephan Bergmann
@ 2012-03-29  7:44 ` Jakub Jelinek
  2012-03-29  8:48   ` Stephan Bergmann
  2012-03-29 16:14 ` Richard Henderson
  1 sibling, 1 reply; 22+ messages in thread
From: Jakub Jelinek @ 2012-03-29  7:44 UTC (permalink / raw)
  To: Stephan Bergmann; +Cc: gcc

On Thu, Mar 29, 2012 at 09:05:29AM +0200, Stephan Bergmann wrote:
> In LibreOffice's ever-beloved low-level code to synthesize calls to
> C++ virtual functions, I'm having the following problem (on Linux
> x86_64). The function callVirtualMethod at <http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61>
> effectively does the following:
> 
> First, call dummy_can_throw_anything that can potentially throw (see
> below for why that's there).  Second, in an asm block, call some
> virtual function (that can potentially throw).  Third, call
> x86_64::fill_struct that can potentially throw (it doesn't, but
> nobody bothered to annotate it as "throw ()").

If the asm isn't in headers, but just in a single short source file
or two, you could try compiling that file with -fnon-call-exceptions.
It is nothing I'd recommend for the whole codebase though.

	Jakub

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29  7:44 ` Jakub Jelinek
@ 2012-03-29  8:48   ` Stephan Bergmann
  2012-03-29  9:16     ` Richard Guenther
  0 siblings, 1 reply; 22+ messages in thread
From: Stephan Bergmann @ 2012-03-29  8:48 UTC (permalink / raw)
  Cc: gcc

On 03/29/2012 09:44 AM, Jakub Jelinek wrote:
> On Thu, Mar 29, 2012 at 09:05:29AM +0200, Stephan Bergmann wrote:
>> In LibreOffice's ever-beloved low-level code to synthesize calls to
>> C++ virtual functions, I'm having the following problem (on Linux
>> x86_64). The function callVirtualMethod at<http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61>
>> effectively does the following:
>>
>> First, call dummy_can_throw_anything that can potentially throw (see
>> below for why that's there).  Second, in an asm block, call some
>> virtual function (that can potentially throw).  Third, call
>> x86_64::fill_struct that can potentially throw (it doesn't, but
>> nobody bothered to annotate it as "throw ()").
>
> If the asm isn't in headers, but just in a single short source file
> or two, you could try compiling that file with -fnon-call-exceptions.
> It is nothing I'd recommend for the whole codebase though.

Turns out I had to move the callVirtualMethod function containing the 
asm into a source file of its own, anyway.  (Otherwise, even if it no 
longer explicitly called functions that can throw, and thus no longer 
had corresponding .gcc_except_table entries, exception throwing still 
lead to std::terminate.  There are other functions in the same source 
file callVirtualMethod was originally in that do have .gcc_except_table 
entries.  Kind of invalidates my previous explanation of why exception 
handling bailed out to std::terminate.  Looks like I haven't groked it 
yet, anyway.)

So an explicit -fnon-call-exceptions on the command line seems to indeed 
help.  Unfortunately, moving that into a

   #pragma GCC optimize ("non-call-exceptions")

at the top of the source file that defines callVirtualMethod (and 
nothing more) does *not* work.  Is that a bug?

Anyway, would it be worthwhile filing an RFE for an asm annotation 
telling the compiler that it contains code that can throw?

Thanks,
Stephan

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29  8:48   ` Stephan Bergmann
@ 2012-03-29  9:16     ` Richard Guenther
  2012-03-29 12:51       ` Stephan Bergmann
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Guenther @ 2012-03-29  9:16 UTC (permalink / raw)
  To: Stephan Bergmann; +Cc: gcc

On Thu, Mar 29, 2012 at 10:47 AM, Stephan Bergmann <sbergman@redhat.com> wrote:
> On 03/29/2012 09:44 AM, Jakub Jelinek wrote:
>>
>> On Thu, Mar 29, 2012 at 09:05:29AM +0200, Stephan Bergmann wrote:
>>>
>>> In LibreOffice's ever-beloved low-level code to synthesize calls to
>>> C++ virtual functions, I'm having the following problem (on Linux
>>> x86_64). The function callVirtualMethod
>>> at<http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61>
>>> effectively does the following:
>>>
>>> First, call dummy_can_throw_anything that can potentially throw (see
>>> below for why that's there).  Second, in an asm block, call some
>>> virtual function (that can potentially throw).  Third, call
>>> x86_64::fill_struct that can potentially throw (it doesn't, but
>>> nobody bothered to annotate it as "throw ()").
>>
>>
>> If the asm isn't in headers, but just in a single short source file
>> or two, you could try compiling that file with -fnon-call-exceptions.
>> It is nothing I'd recommend for the whole codebase though.
>
>
> Turns out I had to move the callVirtualMethod function containing the asm
> into a source file of its own, anyway.  (Otherwise, even if it no longer
> explicitly called functions that can throw, and thus no longer had
> corresponding .gcc_except_table entries, exception throwing still lead to
> std::terminate.  There are other functions in the same source file
> callVirtualMethod was originally in that do have .gcc_except_table entries.
>  Kind of invalidates my previous explanation of why exception handling
> bailed out to std::terminate.  Looks like I haven't groked it yet, anyway.)
>
> So an explicit -fnon-call-exceptions on the command line seems to indeed
> help.  Unfortunately, moving that into a
>
>  #pragma GCC optimize ("non-call-exceptions")
>
> at the top of the source file that defines callVirtualMethod (and nothing
> more) does *not* work.  Is that a bug?

The optimize pragma has only very limited support for this kind of options,
so yes, it's techincally a bug but don't hold your breath.

> Anyway, would it be worthwhile filing an RFE for an asm annotation telling
> the compiler that it contains code that can throw?

I suppose yes.

Richard.

> Thanks,
> Stephan

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29  9:16     ` Richard Guenther
@ 2012-03-29 12:51       ` Stephan Bergmann
  2012-03-29 13:59         ` Michael Matz
  0 siblings, 1 reply; 22+ messages in thread
From: Stephan Bergmann @ 2012-03-29 12:51 UTC (permalink / raw)
  To: gcc

On 03/29/2012 11:16 AM, Richard Guenther wrote:
> On Thu, Mar 29, 2012 at 10:47 AM, Stephan Bergmann<sbergman@redhat.com>  wrote:
>> So an explicit -fnon-call-exceptions on the command line seems to indeed
>> help.  Unfortunately, moving that into a
>>
>>   #pragma GCC optimize ("non-call-exceptions")
>>
>> at the top of the source file that defines callVirtualMethod (and nothing
>> more) does *not* work.  Is that a bug?
>
> The optimize pragma has only very limited support for this kind of options,
> so yes, it's techincally a bug but don't hold your breath.

OK.  (It's just that the way LibreOffice is build, its a PITA to compile 
a single file with differing options...)

>> Anyway, would it be worthwhile filing an RFE for an asm annotation telling
>> the compiler that it contains code that can throw?
>
> I suppose yes.

<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52770> "RFE: Letting 
compiler know asm block can call function that can throw."

Thanks,
Stephan

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 12:51       ` Stephan Bergmann
@ 2012-03-29 13:59         ` Michael Matz
  2012-03-29 14:12           ` Andrew Haley
  2012-03-30  8:23           ` Richard Guenther
  0 siblings, 2 replies; 22+ messages in thread
From: Michael Matz @ 2012-03-29 13:59 UTC (permalink / raw)
  To: Stephan Bergmann; +Cc: gcc

Hi,

On Thu, 29 Mar 2012, Stephan Bergmann wrote:

> > > Anyway, would it be worthwhile filing an RFE for an asm annotation 
> > > telling the compiler that it contains code that can throw?
> >
> > I suppose yes.
> 
> <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52770> "RFE: Letting 
> compiler know asm block can call function that can throw."

Actually, with -fnon-call-exceptions volatile asms are already supposed to 
be throwing.  It's just that this got lost with tree-ssa.  With the patch 
and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as 
possibly throwing.

Without -fnon-call-exceptions some parser changes would be required.  How 
about "asm throw (...)" ?


Ciao,
Michael.
Index: tree-eh.c
===================================================================
--- tree-eh.c	(revision 183716)
+++ tree-eh.c	(working copy)
@@ -1959,6 +1959,7 @@ lower_eh_constructs_2 (struct leh_state
       }
       /* FALLTHRU */
 
+    case GIMPLE_ASM:
     case GIMPLE_ASSIGN:
       /* If the stmt can throw use a new temporary for the assignment
          to a LHS.  This makes sure the old value of the LHS is
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 183716)
+++ tree-cfg.c	(working copy)
@@ -580,6 +580,8 @@ make_edges (void)
 
 	    case GIMPLE_ASM:
 	      make_gimple_asm_edges (bb);
+	      if (is_ctrl_altering_stmt (last))
+		make_eh_edges (last);
 	      fallthru = true;
 	      break;
 

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 13:59         ` Michael Matz
@ 2012-03-29 14:12           ` Andrew Haley
  2012-03-29 15:10             ` Stephan Bergmann
  2012-03-29 15:43             ` Michael Matz
  2012-03-30  8:23           ` Richard Guenther
  1 sibling, 2 replies; 22+ messages in thread
From: Andrew Haley @ 2012-03-29 14:12 UTC (permalink / raw)
  To: gcc

On 03/29/2012 02:59 PM, Michael Matz wrote:
> Actually, with -fnon-call-exceptions volatile asms are already supposed to 
> be throwing.  It's just that this got lost with tree-ssa.  With the patch 
> and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as 
> possibly throwing.
> 
> Without -fnon-call-exceptions some parser changes would be required.  How 
> about "asm throw (...)" ?

Is there any point?  I would have thought that -fnon-call-exceptions was
exactly what you need.

Andrew.

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 14:12           ` Andrew Haley
@ 2012-03-29 15:10             ` Stephan Bergmann
  2012-03-29 15:43             ` Michael Matz
  1 sibling, 0 replies; 22+ messages in thread
From: Stephan Bergmann @ 2012-03-29 15:10 UTC (permalink / raw)
  To: gcc

On 03/29/2012 04:12 PM, Andrew Haley wrote:
> On 03/29/2012 02:59 PM, Michael Matz wrote:
>> Actually, with -fnon-call-exceptions volatile asms are already supposed to
>> be throwing.  It's just that this got lost with tree-ssa.  With the patch
>> and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as
>> possibly throwing.
>>
>> Without -fnon-call-exceptions some parser changes would be required.  How
>> about "asm throw (...)" ?
>
> Is there any point?  I would have thought that -fnon-call-exceptions was
> exactly what you need.

But it looks wrong to me to have to mark the complete compilation unit 
for something that should only affect a single asm declaration.  (Also, 
having to specify -fnon-call-exceptions "externally," on the command 
line, is somewhat awkward.)

Stephan

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 14:12           ` Andrew Haley
  2012-03-29 15:10             ` Stephan Bergmann
@ 2012-03-29 15:43             ` Michael Matz
  2012-03-29 20:38               ` Eric Botcazou
  1 sibling, 1 reply; 22+ messages in thread
From: Michael Matz @ 2012-03-29 15:43 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc

Hi,

On Thu, 29 Mar 2012, Andrew Haley wrote:

> On 03/29/2012 02:59 PM, Michael Matz wrote:
> > Actually, with -fnon-call-exceptions volatile asms are already supposed to 
> > be throwing.  It's just that this got lost with tree-ssa.  With the patch 
> > and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as 
> > possibly throwing.
> > 
> > Without -fnon-call-exceptions some parser changes would be required.  How 
> > about "asm throw (...)" ?
> 
> Is there any point?  I would have thought that -fnon-call-exceptions was
> exactly what you need.

non-call-exceptions is a relatively big hammer.  It marks _all_ 
non-trivial instructions as throwing.  Providing an explicit marker would 
allow for more granularity.  Granted, the request didn't come often over 
the last years, but it seems like a relatively self-contained and useful 
addition to inline asms.


Ciao,
Michael.

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29  7:05 C++: Letting compiler know asm block can call function that can throw? Stephan Bergmann
  2012-03-29  7:44 ` Jakub Jelinek
@ 2012-03-29 16:14 ` Richard Henderson
  2012-03-29 17:16   ` Jan Hubicka
  1 sibling, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2012-03-29 16:14 UTC (permalink / raw)
  To: Stephan Bergmann; +Cc: gcc

On 03/29/2012 03:05 AM, Stephan Bergmann wrote:
> Hi all,
> 
> In LibreOffice's ever-beloved low-level code to synthesize calls to
> C++ virtual functions, I'm having the following problem (on Linux
> x86_64). The function callVirtualMethod at
> <http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61>
> effectively does the following:

Quoting:

    asm volatile (

        // Fill the xmm registers
        "movq %6, %%rax\n\t"

        "movsd   (%%rax), %%xmm0\n\t"
        "movsd  8(%%rax), %%xmm1\n\t"
        "movsd 16(%%rax), %%xmm2\n\t"
        "movsd 24(%%rax), %%xmm3\n\t"
        "movsd 32(%%rax), %%xmm4\n\t"
        "movsd 40(%%rax), %%xmm5\n\t"
        "movsd 48(%%rax), %%xmm6\n\t"
        "movsd 56(%%rax), %%xmm7\n\t"

        // Fill the general purpose registers
        "movq %5, %%rax\n\t"

        "movq    (%%rax), %%rdi\n\t"
        "movq   8(%%rax), %%rsi\n\t"
        "movq  16(%%rax), %%rdx\n\t"
        "movq  24(%%rax), %%rcx\n\t"
        "movq  32(%%rax), %%r8\n\t"
        "movq  40(%%rax), %%r9\n\t"

        // Perform the call
        "movq %4, %%r11\n\t"
        "movq %7, %%rax\n\t"
        "call *%%r11\n\t"

        // Fill the return values
        "movq   %%rax, %0\n\t"
        "movq   %%rdx, %1\n\t"
        "movsd %%xmm0, %2\n\t"
        "movsd %%xmm1, %3\n\t"
        : "=m" ( rax ), "=m" ( rdx ), "=m" ( xmm0 ), "=m" ( xmm1 )
        : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR )
        : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11"
    );

Semi-off-topic, I think this asm can be better done with only the
call inside the asm, and the rest handled by the compiler.

  {
    register sal_uInt64 hard_r8 __asm__("rax"); // etc
    register double hard_xmm0 __asm__("xmm0"); // etc

    hard_rdi = pGPR[0]; //etc
    hard_xmm0 = pFPR[0]; //etc
    hard_rax = nFPR;

    asm volatile ("call *%[method]"
                  : "+r"(hard_rax), //etc
                    "+x"(hard_xmm0), //etc
                  : "g" [method] (pMethod)
                  : "memory");

    rax = hard_rax;
    rdx = hard_rdx;
    xmm0 = hard_xmm0;
    xmm1 = hard_xmm1;
  }


Of course, there's still the problem of getting the unwind data correct at
the point of the asm.  I commented about that in the PR you filed.


r~

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 16:14 ` Richard Henderson
@ 2012-03-29 17:16   ` Jan Hubicka
  2012-03-29 18:34     ` Richard Henderson
  0 siblings, 1 reply; 22+ messages in thread
From: Jan Hubicka @ 2012-03-29 17:16 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Stephan Bergmann, gcc

> On 03/29/2012 03:05 AM, Stephan Bergmann wrote:
> > Hi all,
> > 
> > In LibreOffice's ever-beloved low-level code to synthesize calls to
> > C++ virtual functions, I'm having the following problem (on Linux
> > x86_64). The function callVirtualMethod at
> > <http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61>
> > effectively does the following:
> 
> Quoting:
> 
>     asm volatile (
> 
>         // Fill the xmm registers
>         "movq %6, %%rax\n\t"
> 
>         "movsd   (%%rax), %%xmm0\n\t"
>         "movsd  8(%%rax), %%xmm1\n\t"
>         "movsd 16(%%rax), %%xmm2\n\t"
>         "movsd 24(%%rax), %%xmm3\n\t"
>         "movsd 32(%%rax), %%xmm4\n\t"
>         "movsd 40(%%rax), %%xmm5\n\t"
>         "movsd 48(%%rax), %%xmm6\n\t"
>         "movsd 56(%%rax), %%xmm7\n\t"
> 
>         // Fill the general purpose registers
>         "movq %5, %%rax\n\t"
> 
>         "movq    (%%rax), %%rdi\n\t"
>         "movq   8(%%rax), %%rsi\n\t"
>         "movq  16(%%rax), %%rdx\n\t"
>         "movq  24(%%rax), %%rcx\n\t"
>         "movq  32(%%rax), %%r8\n\t"
>         "movq  40(%%rax), %%r9\n\t"
> 
>         // Perform the call
>         "movq %4, %%r11\n\t"
>         "movq %7, %%rax\n\t"
>         "call *%%r11\n\t"
> 
>         // Fill the return values
>         "movq   %%rax, %0\n\t"
>         "movq   %%rdx, %1\n\t"
>         "movsd %%xmm0, %2\n\t"
>         "movsd %%xmm1, %3\n\t"
>         : "=m" ( rax ), "=m" ( rdx ), "=m" ( xmm0 ), "=m" ( xmm1 )
>         : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR )
>         : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11"
>     );
> 
> Semi-off-topic, I think this asm can be better done with only the
> call inside the asm, and the rest handled by the compiler.
> 
>   {
>     register sal_uInt64 hard_r8 __asm__("rax"); // etc
>     register double hard_xmm0 __asm__("xmm0"); // etc
> 
>     hard_rdi = pGPR[0]; //etc
>     hard_xmm0 = pFPR[0]; //etc
>     hard_rax = nFPR;
> 
>     asm volatile ("call *%[method]"
>                   : "+r"(hard_rax), //etc
>                     "+x"(hard_xmm0), //etc
>                   : "g" [method] (pMethod)
>                   : "memory");
> 
>     rax = hard_rax;
>     rdx = hard_rdx;
>     xmm0 = hard_xmm0;
>     xmm1 = hard_xmm1;
>   }
> 
> 
> Of course, there's still the problem of getting the unwind data correct at
> the point of the asm.  I commented about that in the PR you filed.

I think i386 still has the problem that it is small register class target and if you
set rdi/rax and friends as hard registers, you risk reload failures. 
Do we prevent code motion of hard registers sets i.e. at GIMPLE level? (I know pre-reload
scheduler was improved here, but I would not rely on it either).
As soon as hard_rdi/hard_rax set is moved upwards or downwards across memset/division
or other stuff requiring rax or rdx, reload will ICE.

Honza
> 
> 
> r~

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 17:16   ` Jan Hubicka
@ 2012-03-29 18:34     ` Richard Henderson
  2012-03-30  8:19       ` Richard Guenther
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2012-03-29 18:34 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: Stephan Bergmann, gcc

On 03/29/2012 01:16 PM, Jan Hubicka wrote:
>> Of course, there's still the problem of getting the unwind data correct at
>> the point of the asm.  I commented about that in the PR you filed.
> 
> I think i386 still has the problem that it is small register class target and if you
> set rdi/rax and friends as hard registers, you risk reload failures. 

True, and if this were i386 code I would certainly recommend using the [acd]
constraints instead (for suitible regparm signature).  But this is explicitly
x86_64 code and the compiler has 8 registers otherwise available.

> Do we prevent code motion of hard registers sets i.e. at GIMPLE level?

I don't know for positive, but I'd certainly consider it a bug if we don't.
There are plenty of targets which have no alternative but to use this style
of programming for inline syscalls.


r~

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 15:43             ` Michael Matz
@ 2012-03-29 20:38               ` Eric Botcazou
  0 siblings, 0 replies; 22+ messages in thread
From: Eric Botcazou @ 2012-03-29 20:38 UTC (permalink / raw)
  To: Michael Matz; +Cc: gcc, Andrew Haley

> non-call-exceptions is a relatively big hammer.  It marks _all_
> non-trivial instructions as throwing.

The "all" goes against the "relatively" here, and "relatively" is more correct.
Not all non-trivial instructions are marked as throwing, e.g. loads and stores 
from/to the stack aren't.

-- 
Eric Botcazou

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 18:34     ` Richard Henderson
@ 2012-03-30  8:19       ` Richard Guenther
  2012-03-30 12:21         ` Jan Hubicka
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Guenther @ 2012-03-30  8:19 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Jan Hubicka, Stephan Bergmann, gcc

On Thu, Mar 29, 2012 at 8:34 PM, Richard Henderson <rth@redhat.com> wrote:
> On 03/29/2012 01:16 PM, Jan Hubicka wrote:
>>> Of course, there's still the problem of getting the unwind data correct at
>>> the point of the asm.  I commented about that in the PR you filed.
>>
>> I think i386 still has the problem that it is small register class target and if you
>> set rdi/rax and friends as hard registers, you risk reload failures.
>
> True, and if this were i386 code I would certainly recommend using the [acd]
> constraints instead (for suitible regparm signature).  But this is explicitly
> x86_64 code and the compiler has 8 registers otherwise available.
>
>> Do we prevent code motion of hard registers sets i.e. at GIMPLE level?

Yes we do (modulo bugs).

> I don't know for positive, but I'd certainly consider it a bug if we don't.
> There are plenty of targets which have no alternative but to use this style
> of programming for inline syscalls.
>
>
> r~

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-29 13:59         ` Michael Matz
  2012-03-29 14:12           ` Andrew Haley
@ 2012-03-30  8:23           ` Richard Guenther
  1 sibling, 0 replies; 22+ messages in thread
From: Richard Guenther @ 2012-03-30  8:23 UTC (permalink / raw)
  To: Michael Matz; +Cc: Stephan Bergmann, gcc

On Thu, Mar 29, 2012 at 3:59 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Thu, 29 Mar 2012, Stephan Bergmann wrote:
>
>> > > Anyway, would it be worthwhile filing an RFE for an asm annotation
>> > > telling the compiler that it contains code that can throw?
>> >
>> > I suppose yes.
>>
>> <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52770> "RFE: Letting
>> compiler know asm block can call function that can throw."
>
> Actually, with -fnon-call-exceptions volatile asms are already supposed to
> be throwing.  It's just that this got lost with tree-ssa.  With the patch
> and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as
> possibly throwing.
>
> Without -fnon-call-exceptions some parser changes would be required.  How
> about "asm throw (...)" ?
>
>
> Ciao,
> Michael.
> Index: tree-eh.c
> ===================================================================
> --- tree-eh.c   (revision 183716)
> +++ tree-eh.c   (working copy)
> @@ -1959,6 +1959,7 @@ lower_eh_constructs_2 (struct leh_state
>       }
>       /* FALLTHRU */
>
> +    case GIMPLE_ASM:
>     case GIMPLE_ASSIGN:
>       /* If the stmt can throw use a new temporary for the assignment
>          to a LHS.  This makes sure the old value of the LHS is

This does not handle using a temporary for all (register) outputs ...
I suppose the code should walk all SSA defs instead of looking at
the LHS only.

> Index: tree-cfg.c
> ===================================================================
> --- tree-cfg.c  (revision 183716)
> +++ tree-cfg.c  (working copy)
> @@ -580,6 +580,8 @@ make_edges (void)
>
>            case GIMPLE_ASM:
>              make_gimple_asm_edges (bb);
> +             if (is_ctrl_altering_stmt (last))
> +               make_eh_edges (last);
>              fallthru = true;
>              break;

Otherwise this looks reasonable.  With a testcase, I suppose ;)

Richard.

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-30  8:19       ` Richard Guenther
@ 2012-03-30 12:21         ` Jan Hubicka
  2012-03-30 12:23           ` Richard Guenther
  0 siblings, 1 reply; 22+ messages in thread
From: Jan Hubicka @ 2012-03-30 12:21 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Richard Henderson, Jan Hubicka, Stephan Bergmann, gcc

> On Thu, Mar 29, 2012 at 8:34 PM, Richard Henderson <rth@redhat.com> wrote:
> > On 03/29/2012 01:16 PM, Jan Hubicka wrote:
> >>> Of course, there's still the problem of getting the unwind data correct at
> >>> the point of the asm.  I commented about that in the PR you filed.
> >>
> >> I think i386 still has the problem that it is small register class target and if you
> >> set rdi/rax and friends as hard registers, you risk reload failures.
> >
> > True, and if this were i386 code I would certainly recommend using the [acd]
> > constraints instead (for suitible regparm signature).  But this is explicitly
> > x86_64 code and the compiler has 8 registers otherwise available.

Sure, still rdi/rax is the only option for some of instructions, so x86-64
doesn't really solve all the problems.
> >
> >> Do we prevent code motion of hard registers sets i.e. at GIMPLE level?
> 
> Yes we do (modulo bugs).

Good. Note that this also include transformations like frward substitution into
area where hard register is live (i.e. it is not enough to just not touch hard
registers as volatile, but one needs to prevent moving other code in).

Honza
> 
> > I don't know for positive, but I'd certainly consider it a bug if we don't.
> > There are plenty of targets which have no alternative but to use this style
> > of programming for inline syscalls.
> >
> >
> > r~

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-30 12:21         ` Jan Hubicka
@ 2012-03-30 12:23           ` Richard Guenther
  2012-03-30 15:46             ` Jan Hubicka
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Guenther @ 2012-03-30 12:23 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: Richard Henderson, Stephan Bergmann, gcc

2012/3/30 Jan Hubicka <hubicka@ucw.cz>:
>> On Thu, Mar 29, 2012 at 8:34 PM, Richard Henderson <rth@redhat.com> wrote:
>> > On 03/29/2012 01:16 PM, Jan Hubicka wrote:
>> >>> Of course, there's still the problem of getting the unwind data correct at
>> >>> the point of the asm.  I commented about that in the PR you filed.
>> >>
>> >> I think i386 still has the problem that it is small register class target and if you
>> >> set rdi/rax and friends as hard registers, you risk reload failures.
>> >
>> > True, and if this were i386 code I would certainly recommend using the [acd]
>> > constraints instead (for suitible regparm signature).  But this is explicitly
>> > x86_64 code and the compiler has 8 registers otherwise available.
>
> Sure, still rdi/rax is the only option for some of instructions, so x86-64
> doesn't really solve all the problems.
>> >
>> >> Do we prevent code motion of hard registers sets i.e. at GIMPLE level?
>>
>> Yes we do (modulo bugs).
>
> Good. Note that this also include transformations like frward substitution into
> area where hard register is live (i.e. it is not enough to just not touch hard
> registers as volatile, but one needs to prevent moving other code in).

Motion across hardreg sets/uses are not restricted.  And I would not expect
an optimizing compiler to do that (it's your own fault to use hardregs in
complex C code).

Richard.

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-30 12:23           ` Richard Guenther
@ 2012-03-30 15:46             ` Jan Hubicka
  2012-04-02 14:08               ` Michael Matz
  0 siblings, 1 reply; 22+ messages in thread
From: Jan Hubicka @ 2012-03-30 15:46 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Jan Hubicka, Richard Henderson, Stephan Bergmann, gcc

> 
> Motion across hardreg sets/uses are not restricted.  And I would not expect
> an optimizing compiler to do that (it's your own fault to use hardregs in
> complex C code).

Well, the syscall sequence is an example of somehting that should be inlined
into arbitrary code w/o potential risk of ICEs.  But I guess if things works in
practice (as they seem), we don't need to worry much at the moment.  Most of
code movement we do is very simple. I don't see how to convince GCC to move
memcpy or division into the middle of a basic block containing the libcall
sequence.... Even when the basic block can be broken up with
-fno-call-exceptions at the asm statement by an EH edge...

Honza
> 
> Richard.

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-03-30 15:46             ` Jan Hubicka
@ 2012-04-02 14:08               ` Michael Matz
  2012-04-02 14:17                 ` Jakub Jelinek
  0 siblings, 1 reply; 22+ messages in thread
From: Michael Matz @ 2012-04-02 14:08 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: Richard Guenther, Richard Henderson, Stephan Bergmann, gcc

Hi,

On Fri, 30 Mar 2012, Jan Hubicka wrote:

> > Motion across hardreg sets/uses are not restricted.  And I would not expect
> > an optimizing compiler to do that (it's your own fault to use hardregs in
> > complex C code).
> 
> Well, the syscall sequence is an example of somehting that should be 
> inlined into arbitrary code w/o potential risk of ICEs.

The syscall sequence doesn't consist of multiple independend instructions, 
but rather is one asm with the right constraints.  So gcc has no chance to 
move something between the register setup (which only is explicit after 
reload) and the syscall instruction.  If syscall sequences were 
implemented like this:

inline int syscall1(int number, long arg1) {
  register int ax __asm__("eax");
  register long di __asm__("rdi");
  ax = number;
  di = arg1;
  __asm__ volatile ("syscall");
}

_then_ we would probably get miscompilations here and there.


Ciao,
Michael.

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-04-02 14:08               ` Michael Matz
@ 2012-04-02 14:17                 ` Jakub Jelinek
  2012-04-02 16:04                   ` Michael Matz
  0 siblings, 1 reply; 22+ messages in thread
From: Jakub Jelinek @ 2012-04-02 14:17 UTC (permalink / raw)
  To: Michael Matz
  Cc: Jan Hubicka, Richard Guenther, Richard Henderson, Stephan Bergmann, gcc

On Mon, Apr 02, 2012 at 04:07:59PM +0200, Michael Matz wrote:
> On Fri, 30 Mar 2012, Jan Hubicka wrote:
> 
> > > Motion across hardreg sets/uses are not restricted.  And I would not expect
> > > an optimizing compiler to do that (it's your own fault to use hardregs in
> > > complex C code).
> > 
> > Well, the syscall sequence is an example of somehting that should be 
> > inlined into arbitrary code w/o potential risk of ICEs.
> 
> The syscall sequence doesn't consist of multiple independend instructions, 
> but rather is one asm with the right constraints.  So gcc has no chance to 
> move something between the register setup (which only is explicit after 
> reload) and the syscall instruction.  If syscall sequences were 
> implemented like this:
> 
> inline int syscall1(int number, long arg1) {
>   register int ax __asm__("eax");
>   register long di __asm__("rdi");
>   ax = number;
>   di = arg1;
>   __asm__ volatile ("syscall");
> }
> 
> _then_ we would probably get miscompilations here and there.

That is actually what is used on most targets, including x86_64 (i?86 is an
exception here, because it has single hard register constraints for most of
the interesting registers).

	Jakub

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-04-02 14:17                 ` Jakub Jelinek
@ 2012-04-02 16:04                   ` Michael Matz
  2012-04-16 20:01                     ` Hans-Peter Nilsson
  0 siblings, 1 reply; 22+ messages in thread
From: Michael Matz @ 2012-04-02 16:04 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Jan Hubicka, Richard Guenther, Richard Henderson, Stephan Bergmann, gcc

Hi,

On Mon, 2 Apr 2012, Jakub Jelinek wrote:

> > inline int syscall1(int number, long arg1) {
> >   register int ax __asm__("eax");
> >   register long di __asm__("rdi");
> >   ax = number;
> >   di = arg1;
> >   __asm__ volatile ("syscall");
> > }
> > 
> > _then_ we would probably get miscompilations here and there.
> 
> That is actually what is used on most targets, including x86_64

Yikes!  That's indeed the case.  I'll want to retract what I said, concede 
with Honza that we're lucky and add that we're lucky mostly because 
register variables are not regarded as gimple registers, hence all stores 
to such variables are regarded as VDEFs.  So there will be VDEF/VUSE 
chains between initializer and syscall, which prevents most code motion 
into that chain.  That itself doesn't e.g. prevent the load/store 
disambiguator from disambiguating two such decls, even if they refer to 
the same hardreg.  So we really are merely lucky, with enough effort we 
probably could create a "miscompiling" testcase.


Ciao,
Michael.

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

* Re: C++: Letting compiler know asm block can call function that can throw?
  2012-04-02 16:04                   ` Michael Matz
@ 2012-04-16 20:01                     ` Hans-Peter Nilsson
  0 siblings, 0 replies; 22+ messages in thread
From: Hans-Peter Nilsson @ 2012-04-16 20:01 UTC (permalink / raw)
  To: Michael Matz
  Cc: Jakub Jelinek, Jan Hubicka, Richard Guenther, Richard Henderson,
	Stephan Bergmann, gcc

On Mon, 2 Apr 2012, Michael Matz wrote:
> On Mon, 2 Apr 2012, Jakub Jelinek wrote:
>
> > > inline int syscall1(int number, long arg1) {
> > >   register int ax __asm__("eax");
> > >   register long di __asm__("rdi");
> > >   ax = number;
> > >   di = arg1;
> > >   __asm__ volatile ("syscall");
> > > }
> > >
> > > _then_ we would probably get miscompilations here and there.
> >
> > That is actually what is used on most targets, including x86_64
>
> Yikes!  That's indeed the case.  I'll want to retract what I said, concede
> with Honza that we're lucky and add that we're lucky mostly because
> register variables are not regarded as gimple registers, hence all stores
> to such variables are regarded as VDEFs.  So there will be VDEF/VUSE
> chains between initializer and syscall, which prevents most code motion
> into that chain.  That itself doesn't e.g. prevent the load/store
> disambiguator from disambiguating two such decls, even if they refer to
> the same hardreg.  So we really are merely lucky, with enough effort we
> probably could create a "miscompiling" testcase.

Lucky perhaps, but documented lucky: this is documented (grep
sysint extend.texi) to work, to avoid having talented gcc
hackers saying "oh, that worked?  You have to _stop doing that_;
you've just been lucky in previous versions" rather that "oops,
looks like I broke that; I'll fix it post-haste".

(There's *one* test-case in gcc.target/cris/asmreg-1.c; this
could certainly do with more coverage.)

brgds, H-P

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

end of thread, other threads:[~2012-04-16 20:01 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-29  7:05 C++: Letting compiler know asm block can call function that can throw? Stephan Bergmann
2012-03-29  7:44 ` Jakub Jelinek
2012-03-29  8:48   ` Stephan Bergmann
2012-03-29  9:16     ` Richard Guenther
2012-03-29 12:51       ` Stephan Bergmann
2012-03-29 13:59         ` Michael Matz
2012-03-29 14:12           ` Andrew Haley
2012-03-29 15:10             ` Stephan Bergmann
2012-03-29 15:43             ` Michael Matz
2012-03-29 20:38               ` Eric Botcazou
2012-03-30  8:23           ` Richard Guenther
2012-03-29 16:14 ` Richard Henderson
2012-03-29 17:16   ` Jan Hubicka
2012-03-29 18:34     ` Richard Henderson
2012-03-30  8:19       ` Richard Guenther
2012-03-30 12:21         ` Jan Hubicka
2012-03-30 12:23           ` Richard Guenther
2012-03-30 15:46             ` Jan Hubicka
2012-04-02 14:08               ` Michael Matz
2012-04-02 14:17                 ` Jakub Jelinek
2012-04-02 16:04                   ` Michael Matz
2012-04-16 20:01                     ` Hans-Peter Nilsson

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).