On Sat, 8 Jan 2022, Martin Uecker via Gcc wrote:

Am Samstag, den 08.01.2022, 13:41 +0100 schrieb Richard Biener:
On January 8, 2022 9:32:24 AM GMT+01:00, Martin Uecker <ma.uec...@gmail.com> 
wrote:
Hi Richard,

thank you for your quick response!

I have a question regarding reodering of volatile
accesses and trapping operations. My initial
assumption (and  hope) was that compilers take
care to avoid creating traps that are incorrectly
ordered relative to observable behavior.

I had trouble finding examples, and my cursory
glace at the code seemed to confirm that GCC
carefully avoids this.  But then someone showed
me this example, where this can happen in GCC:


volatile int x;

int foo(int a, int b, _Bool store_to_x)
{
 if (!store_to_x)
   return a / b;
 x = b;
 return a / b;
}


https://godbolt.org/z/vq3r8vjxr

In this example a division is hoisted
before the volatile store. (the division
by zero which could trap is UB, of course).

As Martin Sebor pointed out this is done
as part of redundancy elimination
in tree-ssa-pre.c and that this might
simply be an oversight (and could then be
fixed with a small change).

Could you clarify whether such reordering
is intentional and could be exploited in
general also in other optimizations or
confirm that this is an oversight that
affects only this specific case?

If this is intentional, are there examples
where this is important for optimization?

In general there is no data flow information that
prevents traps from being reordered with respect
to volatile accesses.

Yes, although I think potentially trapping ops
are not moved before calls (as this would be
incorrect).  So do you think it would be feasable
to prevent this for volatile too?

The specific case could be
easily mitigated in PRE. Another case would be

A = c / d;
X = 1;
If (use_a)
  Bar (a);

Where we'd sink a across x into the guarded Bb I suspect.

Yes. Related example:

https://godbolt.org/z/5WGhadre3

volatile int x;
void bar(int a);

void foo(int c, int d)
{
 int a = c / d;
 x = 1;
 if (d)
   bar(a);
}

foo:
       mov     DWORD PTR x[rip], 1
       test    esi, esi
       jne     .L4
       ret
.L4:
       mov     eax, edi
       cdq
       idiv    esi
       mov     edi, eax
       jmp     bar


It would be nice to prevent this too, although
I am less concerned about this direction, as
the UB has already happened so there is not
much we could guarantee about this anyway.

In the other case, it could affect correct
code before the trap.

-fnon-call-exceptions helps with the first testcase but not with the second one. I don't know if that's by accident, but the flag seems possibly relevant.

--
Marc Glisse

Reply via email to