https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79681
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I was thinking about --- fold-const.c.jj1 2017-02-17 18:29:24.000000000 +0100 +++ fold-const.c 2017-02-27 14:49:13.816203253 +0100 @@ -3862,6 +3862,39 @@ make_bit_field_ref (location_t loc, tree { tree result, bftype; + /* Attempt to use DECL_BIT_FIELD_REPRESENTATIVE as BIT_FIELD_REF + base if possible during FE folding. */ + if (in_gimple_form + && TREE_CODE (orig_inner) == COMPONENT_REF + && (DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (orig_inner, 1)) + != NULL_TREE)) + { + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (orig_inner, 1)); + tree ninner = build3 (COMPONENT_REF, TREE_TYPE (repr), + TREE_OPERAND (orig_inner, 0), repr, NULL_TREE); + machine_mode nmode; + HOST_WIDE_INT nbitsize, nbitpos; + tree noffset; + int nunsignedp, nreversep, nvolatilep = 0; + tree base = get_inner_reference (ninner, &nbitsize, &nbitpos, + &noffset, &nmode, &nunsignedp, + &nreversep, &nvolatilep); + if (base == inner + && noffset == NULL_TREE + && nbitsize >= bitsize + && nbitpos <= bitpos + && bitpos + bitsize <= nbitpos + nbitsize + && !reversep + && !nreversep + && !nvolatilep) + { + inner = ninner; + bitpos -= nbitpos; + } + else + ggc_free (ninner); + } + alias_set_type iset = get_alias_set (orig_inner); if (iset == 0 && get_alias_set (inner) != iset) inner = fold_build2 (MEM_REF, TREE_TYPE (inner), which quite often just starts using the representative instead of using BIT_FIELD_REF. Unfortunately constexpr.c isn't prepared to handle that either.