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