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