This avoids folding
_1 = { _2, _3, _4, _5 }; _2 = BIT_FIELD_REF <_1, ..>; to _1 = { _2, _3, _4, _5 }; _2 = { _4, _5 }; when the first CTOR doesn't become dead. This in turn makes FRE handle partial loads from mem = _1; by inserting BIT_FIELD_REFs on _1 (instead of CTORs which FRE refuses to insert). For gcc.target/i386/pr83008.c this means eliding the memory and producing quite optimal code. simplify_bitfield_ref used to need GENERIC folding for BIT_FIELD_REF of CTOR but we since moved the folding to match.pd and leaving the GENERIC call in defeats the single_use check. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2019-11-05 Richard Biener <rguent...@suse.de> PR tree-optimization/92280 * match.pd (BIT_FIELD_REF of CTOR): Unless the original CTOR had a single use do not create a new CTOR. * tree-ssa-forwprop.c (simplify_bitfield_ref): Do not re-fold BIT_FIELD_REF of a CTOR via GENERIC. Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 277813) +++ gcc/match.pd (working copy) @@ -5565,15 +5565,19 @@ (define_operator_list COND_TERNARY (if (elt < CONSTRUCTOR_NELTS (ctor)) (view_convert { CONSTRUCTOR_ELT (ctor, elt)->value; }) { build_zero_cst (type); }) - { - vec<constructor_elt, va_gc> *vals; - vec_alloc (vals, count); - for (unsigned i = 0; - i < count && elt + i < CONSTRUCTOR_NELTS (ctor); ++i) - CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE, - CONSTRUCTOR_ELT (ctor, elt + i)->value); - build_constructor (type, vals); - }))) + /* We don't want to emit new CTORs unless the old one goes away. + ??? Eventually allow this if the CTOR ends up constant or + uniform. */ + (if (single_use (@0)) + { + vec<constructor_elt, va_gc> *vals; + vec_alloc (vals, count); + for (unsigned i = 0; + i < count && elt + i < CONSTRUCTOR_NELTS (ctor); ++i) + CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE, + CONSTRUCTOR_ELT (ctor, elt + i)->value); + build_constructor (type, vals); + })))) /* The bitfield references a single constructor element. */ (if (k.is_constant (&const_k) && idx + n <= (idx / const_k + 1) * const_k) Index: gcc/tree-ssa-forwprop.c =================================================================== --- gcc/tree-ssa-forwprop.c (revision 277813) +++ gcc/tree-ssa-forwprop.c (working copy) @@ -1786,7 +1786,7 @@ simplify_bitfield_ref (gimple_stmt_itera { gimple *stmt = gsi_stmt (*gsi); gimple *def_stmt; - tree op, op0, op1, op2; + tree op, op0, op1; tree elem_type; unsigned idx, size; enum tree_code code; @@ -1804,20 +1804,7 @@ simplify_bitfield_ref (gimple_stmt_itera return false; op1 = TREE_OPERAND (op, 1); - op2 = TREE_OPERAND (op, 2); code = gimple_assign_rhs_code (def_stmt); - - if (code == CONSTRUCTOR) - { - tree tem = fold_ternary (BIT_FIELD_REF, TREE_TYPE (op), - gimple_assign_rhs1 (def_stmt), op1, op2); - if (!tem || !valid_gimple_rhs_p (tem)) - return false; - gimple_assign_set_rhs_from_tree (gsi, tem); - update_stmt (gsi_stmt (*gsi)); - return true; - } - elem_type = TREE_TYPE (TREE_TYPE (op0)); if (TREE_TYPE (op) != elem_type) return false;