Ian Lance Taylor
Thu Mar 15 17:40:00 GMT 2007
Michael Matz <firstname.lastname@example.org> writes:
> Without this change, this call will be miscompiled on 32bit hosts:
> __sync_fetch_and_add_8 (ptr, -(unsigned long long)1);
> Because the -1LL will be 0xffffffffffffffff in the tree expression. Now
> the expand_expr call above will turn that tree constant into a RTL
> constant, namely (const_int -1 [0xffffffff]), that is correct as far as I
> can see, as RTL constants are implicitely sign extended.
> Now, without my change the convert_to_mode() call will turn that RTL
> constant into the wrong 64bit unsigned variant of this (mode is DImode,
> and due to the unsigned flag being set for the convert_to_mode call),
> namely (const_int [0xffffffff]   ), i.e. it's zero extended.
Hmmm, interesting problem. This kind of thing isn't usually a problem
at the RTL level because we don't usually see CONST_INTs which are
larger than HOST_BITS_PER_WIDE_INT, so we don't get much opportunity
to mess them up. It's increasingly painful to not have correct modes
> The tree argument 1 will be: <integer_cst <unsigned char> 255>, which is
> correct, as the prototype for this builtin indeed has an unsigned char
> integer type in arguments. Now the expand_expr above will turn that into
> (const_int 255 [0xff]), also still sort of correct.
That doesn't sound right. immed_double_const with QImode should
return const_int 0xffffffff here. Why do we have 0xff?
More information about the Gcc-patches