return true;
}
/* Optimizes
- a = c;
- b = a;
+ DEST = SRC;
+ DEST2 = DEST; # DEST2 = SRC2;
into
- a = c;
- b = c;
- GSIP is the second statement and SRC is the common
+ DEST = SRC;
+ DEST2 = SRC;
+ GSIP is the first statement and SRC is the common
between the statements.
*/
static bool
if (operand_equal_p (dest, src, 0))
return false;
- tree vuse = gimple_vuse (stmt);
- /* If the vuse is the default definition, then there is no store beforehand. */
- if (SSA_NAME_IS_DEFAULT_DEF (vuse))
- return false;
- gimple *defstmt = SSA_NAME_DEF_STMT (vuse);
- if (!gimple_assign_load_p (defstmt)
- || !gimple_store_p (defstmt))
- return false;
- if (gimple_has_volatile_ops (defstmt))
- return false;
-
- tree dest2 = gimple_assign_lhs (defstmt);
- tree src2 = gimple_assign_rhs1 (defstmt);
-
- /* If the original store is `src2 = src2;` skip over it. */
- if (operand_equal_p (src2, dest2, 0))
- return false;
- if (!operand_equal_p (src, dest2, 0))
- return false;
-
-
- /* For 2 memory refences and using a temporary to do the copy,
- don't remove the temporary as the 2 memory references might overlap.
- Note t does not need to be decl as it could be field.
- See PR 22237 for full details.
- E.g.
- t = *a;
- *b = t;
- Cannot be convert into
- t = *a;
- *b = *a;
- Though the following is allowed to be done:
- t = *a;
- *a = t;
- And convert it into:
- t = *a;
- *a = *a;
- */
- if (!operand_equal_p (src2, dest, 0)
- && !DECL_P (dest) && !DECL_P (src2))
- return false;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
+ tree vdef = gimple_vdef (stmt);
+ imm_use_iterator iter;
+ gimple *use_stmt;
+ bool changed = false;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef)
{
- fprintf (dump_file, "Simplified\n ");
- print_gimple_stmt (dump_file, stmt, 0, dump_flags);
- fprintf (dump_file, "after previous\n ");
- print_gimple_stmt (dump_file, defstmt, 0, dump_flags);
- }
- gimple_assign_set_rhs_from_tree (gsip, unshare_expr (src2));
- update_stmt (stmt);
+ if (!gimple_assign_load_p (use_stmt)
+ || !gimple_store_p (use_stmt))
+ continue;
+ if (gimple_has_volatile_ops (use_stmt))
+ continue;
+ tree dest2 = gimple_assign_lhs (use_stmt);
+ tree src2 = gimple_assign_rhs1 (use_stmt);
+ /* If the new store is `src2 = src2;` skip over it. */
+ if (operand_equal_p (src2, dest2, 0))
+ continue;
+ if (!operand_equal_p (dest, src2, 0))
+ continue;
+ /* For 2 memory refences and using a temporary to do the copy,
+ don't remove the temporary as the 2 memory references might overlap.
+ Note t does not need to be decl as it could be field.
+ See PR 22237 for full details.
+ E.g.
+ t = *a; #DEST = SRC;
+ *b = t; #DEST2 = SRC2;
+ Cannot be convert into
+ t = *a;
+ *b = *a;
+ Though the following is allowed to be done:
+ t = *a;
+ *a = t;
+ And convert it into:
+ t = *a;
+ *a = *a;
+ */
+ if (!operand_equal_p (dest2, src, 0)
+ && !DECL_P (dest2) && !DECL_P (src))
+ continue;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Simplified\n ");
+ print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
+ fprintf (dump_file, "after previous\n ");
+ print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+ }
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (src));
+ update_stmt (use_stmt);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "into\n ");
- print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "into\n ");
+ print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
+ }
+ statistics_counter_event (cfun, "copy prop for aggregate", 1);
+ changed = true;
}
- statistics_counter_event (cfun, "copy prop for aggregate", 1);
- return true;
+ return changed;
}
/* *GSI_P is a GIMPLE_CALL to a builtin function.