When for example complex lowering wants to extract the imaginary part of a complex variable for lowering a complex move we can end up with it generating __imag <VIEW_CONVERT_EXPR <_22> > which is valid GENERIC. It then feeds that to the gimplifier via force_gimple_operand but that fails to split up this chain of handled components, generating invalid GIMPLE catched by verification when PR109644 is fixed.
The following rectifies this by noting in gimplify_compound_lval when the base object which we gimplify first ends up being a register. Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. * gimplify.cc (gimplify_compound_lval): When the base gimplified to a register make sure to split up chains of operations. --- gcc/gimplify.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index b0bdd1b46cd..9755f79fb2d 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -3281,15 +3281,21 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if (need_non_reg && (fallback & fb_rvalue)) prepare_gimple_addressable (p, pre_p); + /* Step 3: gimplify size expressions and the indices and operands of - ARRAY_REF. During this loop we also remove any useless conversions. */ + ARRAY_REF. During this loop we also remove any useless conversions. + If we operate on a register also make sure to properly gimplify + to individual operations. */ + bool reg_operations = is_gimple_reg (*p); for (; expr_stack.length () > 0; ) { tree t = expr_stack.pop (); if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF) { + gcc_assert (!reg_operations); + /* Gimplify the low bound and element type size. */ tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, is_gimple_reg, fb_rvalue); @@ -3306,10 +3312,18 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } else if (TREE_CODE (t) == COMPONENT_REF) { + gcc_assert (!reg_operations); + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, is_gimple_reg, fb_rvalue); ret = MIN (ret, tret); } + else if (reg_operations) + { + tret = gimplify_expr (&TREE_OPERAND (t, 0), pre_p, post_p, + is_gimple_val, fb_rvalue); + ret = MIN (ret, tret); + } STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0)); -- 2.35.3