https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101437

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |pinskia at gcc dot gnu.org

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The ICE is because since the above change when we see the empty type volatile
*p = s; store, we gimplify it as s and *p (which seems wrong for volatiles,
because that is load from *p instead of store to *p) and that *p is gimplified
as read from *p into a temporary vol.0 and hits the same case, where we when we
try to gimplify for vol.0 = *p the from_p part *p, we gimplify it as vol.1 = *p
and like that until we eat all of the stack.

The difference between the struct S {}; case that was handled like that forever
and worked fine is in:
      else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
               && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode)
        {
          /* Historically, the compiler has treated a bare reference
             to a non-BLKmode volatile lvalue as forcing a load.  */
          tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));

          /* Normally, we do not want to create a temporary for a
             TREE_ADDRESSABLE type because such a type should not be
             copied by bitwise-assignment.  However, we make an
             exception here, as all we are doing here is ensuring that
             we read the bytes that make up the type.  We use
             create_tmp_var_raw because create_tmp_var will abort when
             given a TREE_ADDRESSABLE type.  */
          tree tmp = create_tmp_var_raw (type, "vol");
          gimple_add_tmp_var (tmp);
          gimplify_assign (tmp, *expr_p, pre_p);
          *expr_p = NULL;
        }
      else
        /* We can't do anything useful with a volatile reference to
           an incomplete type, so just throw it away.  Likewise for
           a BLKmode type, since any implicit inner load should
           already have been turned into an explicit one by the
           gimplification process.  */
        *expr_p = NULL;

The empty struct has BLKmode and so is thrown away, while the struct with
unsigned int : 1; has QImode or so and goes through the "vol" handling.
I guess we should figure out what a volatile load or store of empty non-zero
size type means, if it can be optimized away or not, and depending on that
either add && !is_empty_type (TREE_TYPE (*expr_p)) to the "vol" handling
condition, or stop doing the gimplify_modify_expr optimization if lhs or rhs is
volatile (and either isn't a zero size type or always).

Reply via email to