+ /* Rewrite LHS IMAG/REALPART_EXPR similar to
+ gimplify_modify_expr_complex_part. */
+ if ((TREE_CODE (lhs) == IMAGPART_EXPR
+ || TREE_CODE (lhs) == REALPART_EXPR)
+ && DECL_P (TREE_OPERAND (lhs, 0))
+ && bitmap_bit_p (suitable_for_renaming,
+ DECL_UID (TREE_OPERAND (lhs, 0))))
+ {
+ tree other = make_ssa_name (TREE_TYPE (lhs));
+ tree lrhs = build1 (TREE_CODE (lhs) == IMAGPART_EXPR
+ ? REALPART_EXPR : IMAGPART_EXPR,
+ TREE_TYPE (other),
+ TREE_OPERAND (lhs, 0));
+ gimple *load = gimple_build_assign (other, lrhs);
+ location_t loc = gimple_location (stmt);
+ gimple_set_location (load, loc);
+ gimple_set_vuse (load, gimple_vuse (stmt));
+ gsi_insert_before (&gsi, load, GSI_SAME_STMT);
+ gimple_assign_set_lhs (stmt, TREE_OPERAND (lhs, 0));
+ gimple_assign_set_rhs_with_ops
+ (&gsi, COMPLEX_EXPR,
+ TREE_CODE (lhs) == IMAGPART_EXPR
+ ? other : gimple_assign_rhs1 (stmt),
+ TREE_CODE (lhs) == IMAGPART_EXPR
+ ? gimple_assign_rhs1 (stmt) : other, NULL_TREE);
+ stmt = gsi_stmt (gsi);
+ unlink_stmt_vdef (stmt);
+ update_stmt (stmt);
+ continue;
+ }
+
+ /* Rewrite a vector insert via a BIT_FIELD_REF on the LHS
+ into a BIT_INSERT_EXPR. */
+ if (TREE_CODE (lhs) == BIT_FIELD_REF
+ && DECL_P (TREE_OPERAND (lhs, 0))
+ && bitmap_bit_p (suitable_for_renaming,
+ DECL_UID (TREE_OPERAND (lhs, 0)))
+ && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0)))
+ && TYPE_MODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != BLKmode
+ && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
+ TYPE_SIZE_UNIT (TREE_TYPE
+ (TREE_TYPE (TREE_OPERAND (lhs, 0)))),
+ 0)
+ && (tree_to_uhwi (TREE_OPERAND (lhs, 2))
+ % tree_to_uhwi (TYPE_SIZE (TREE_TYPE (lhs))) == 0))
+ {
+ tree var = TREE_OPERAND (lhs, 0);
+ tree val = gimple_assign_rhs1 (stmt);
+ if (! types_compatible_p (TREE_TYPE (TREE_TYPE (var)),
+ TREE_TYPE (val)))
+ {
+ tree tem = make_ssa_name (TREE_TYPE (TREE_TYPE (var)));
+ gimple *pun
+ = gimple_build_assign (tem,
+ build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (tem), val));
+ gsi_insert_before (&gsi, pun, GSI_SAME_STMT);
+ val = tem;
+ }
+ tree bitpos = TREE_OPERAND (lhs, 2);
+ gimple_assign_set_lhs (stmt, var);
+ gimple_assign_set_rhs_with_ops
+ (&gsi, BIT_INSERT_EXPR, var, val, bitpos);
+ stmt = gsi_stmt (gsi);
+ unlink_stmt_vdef (stmt);
+ update_stmt (stmt);
+ continue;
+ }
+
+ /* Rewrite a vector insert using a MEM_REF on the LHS
+ into a BIT_INSERT_EXPR. */
+ if (TREE_CODE (lhs) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
+ && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0))
+ && DECL_P (sym)
+ && bitmap_bit_p (suitable_for_renaming, DECL_UID (sym))
+ && VECTOR_TYPE_P (TREE_TYPE (sym))
+ && TYPE_MODE (TREE_TYPE (sym)) != BLKmode
+ /* If it is a full replacement we can do better below. */
+ && maybe_ne (wi::to_poly_offset
+ (TYPE_SIZE_UNIT (TREE_TYPE (lhs))),
+ wi::to_poly_offset
+ (TYPE_SIZE_UNIT (TREE_TYPE (sym))))
+ && known_ge (mem_ref_offset (lhs), 0)
+ && known_gt (wi::to_poly_offset
+ (TYPE_SIZE_UNIT (TREE_TYPE (sym))),
+ mem_ref_offset (lhs))
+ && multiple_of_p (sizetype,
+ TREE_OPERAND (lhs, 1),
+ TYPE_SIZE_UNIT (TREE_TYPE (lhs))))
+ {
+ tree val = gimple_assign_rhs1 (stmt);
+ if (! types_compatible_p (TREE_TYPE (val),
+ TREE_TYPE (TREE_TYPE (sym))))
+ {
+ poly_uint64 lhs_bits, nelts;
+ tree temtype = TREE_TYPE (TREE_TYPE (sym));
+ if (poly_int_tree_p (TYPE_SIZE (TREE_TYPE (lhs)),
+ &lhs_bits)
+ && multiple_p (lhs_bits,
+ tree_to_uhwi
+ (TYPE_SIZE (TREE_TYPE
+ (TREE_TYPE (sym)))),
+ &nelts)
+ && maybe_ne (nelts, 1u)
+ && valid_vector_subparts_p (nelts))
+ temtype = build_vector_type (temtype, nelts);
+ tree tem = make_ssa_name (temtype);
+ gimple *pun
+ = gimple_build_assign (tem,
+ build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (tem), val));
+ gsi_insert_before (&gsi, pun, GSI_SAME_STMT);
+ val = tem;
+ }
+ tree bitpos
+ = wide_int_to_tree (bitsizetype,
+ mem_ref_offset (lhs) * BITS_PER_UNIT);
+ gimple_assign_set_lhs (stmt, sym);
+ gimple_assign_set_rhs_with_ops
+ (&gsi, BIT_INSERT_EXPR, sym, val, bitpos);
+ stmt = gsi_stmt (gsi);
+ unlink_stmt_vdef (stmt);
+ update_stmt (stmt);
+ continue;
+ }
+