On Tue, Feb 20, 2024 at 11:11:22AM +0100, Richard Biener wrote:
> > --- gcc/c-family/c-common.cc.jj     2024-02-17 16:40:42.831571693 +0100
> > +++ gcc/c-family/c-common.cc        2024-02-20 10:58:56.599865656 +0100
> > @@ -7793,9 +7793,14 @@ resolve_overloaded_atomic_exchange (loca
> >    /* Convert object pointer to required type.  */
> >    p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
> >    (*params)[0] = p0; 
> > -  /* Convert new value to required type, and dereference it.  */
> > -  p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
> > -  p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
> > +  /* Convert new value to required type, and dereference it.
> > +     If *p1 type can have padding or may involve floating point which
> > +     could e.g. be promoted to wider precision and demoted afterwards,
> > +     state of padding bits might not be preserved.  */
> > +  build_indirect_ref (loc, p1, RO_UNARY_STAR);
> > +  p1 = build2_loc (loc, MEM_REF, I_type,
> > +              build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1),
> 
> Why the V_C_E to I_type_ptr?  The type of p1 doesn't
> really matter (unless it could be a non-pointer).

Just to help the FE when trying to constexpr evaluate it, because
for constexpr evaluation it evaluates MEM_REF the same as INDIRECT_REF
(and punts on non-0 second argument).  The actual call is non-constexpr,
just wanted to avoid ICEs or something similar, constexpr evaluation can
try to process the arguments (and succeed or fail, doesn't matter,
but not ICE) and then the call will not be constant expression and so
everything won't be.

> Also note that I_type needs to be properly address-space qualified
> in case the access should be to an address-space.  Formerly with
> the INDIRECT_REF that would likely be automagic.

I don't think using __atomic_*exchange on non-default as is valid,
if one doesn't have the exact __atomic_*exchange_N, it is handled
as a library call which is passed pointers and that definitely will
not deal with non-default address spaces.
Furthermore, the type should be the same in all arguments, and
the first argument is just converted to I_type_ptr and dealt with later, so
I don't think it ever worked even for the supported sizes.
int                                                                             
                                                                                
                     
foo (__seg_gs int *a, __seg_gs int *b, __seg_gs int *c)                         
                                                                                
                         
{                                                                               
                                                                                
                      
  return __atomic_compare_exchange (a, b, c, 0, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);                                                              
                                       
}                                                                               
                                                                                
                      
results in
        movl    (%rsi), %eax
        movl    %gs:(%rdx), %edx
        lock cmpxchgl   %edx, (%rdi)
        sete    %dl
        je      .L2
        movl    %eax, (%rsi)
.L2:
i.e. pretty much random what is loaded from a different AS and what is not.

        Jakub

Reply via email to