integer types involves undefined behavior on overflow and the
operation can be expressed with unsigned arithmetic. */
-bool
+static bool
arith_code_with_undefined_signed_overflow (tree_code code)
{
switch (code)
}
}
+/* Return true if STMT has an operation that operates on a signed
+ integer types involves undefined behavior on overflow and the
+ operation can be expressed with unsigned arithmetic. */
+
+bool
+gimple_with_undefined_signed_overflow (gimple *stmt)
+{
+ if (!is_gimple_assign (stmt))
+ return false;
+ tree lhs = gimple_assign_lhs (stmt);
+ if (!lhs)
+ return false;
+ tree lhs_type = TREE_TYPE (lhs);
+ if (!INTEGRAL_TYPE_P (lhs_type)
+ && !POINTER_TYPE_P (lhs_type))
+ return false;
+ if (!TYPE_OVERFLOW_UNDEFINED (lhs_type))
+ return false;
+ if (!arith_code_with_undefined_signed_overflow
+ (gimple_assign_rhs_code (stmt)))
+ return false;
+ return true;
+}
+
/* Rewrite STMT, an assignment with a signed integer or pointer arithmetic
operation that can be transformed to unsigned arithmetic by converting
its operand, carrying out the operation in the corresponding unsigned
extern tree gimple_fold_indirect_ref (tree);
extern bool gimple_fold_builtin_sprintf (gimple_stmt_iterator *);
extern bool gimple_fold_builtin_snprintf (gimple_stmt_iterator *);
-extern bool arith_code_with_undefined_signed_overflow (tree_code);
+extern bool gimple_with_undefined_signed_overflow (gimple *);
extern void rewrite_to_defined_overflow (gimple_stmt_iterator *);
extern gimple_seq rewrite_to_defined_overflow (gimple *);
extern void replace_call_with_value (gimple_stmt_iterator *, tree);
fprintf (dump_file, "tree could trap...\n");
return false;
}
- else if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
- && arith_code_with_undefined_signed_overflow
- (gimple_assign_rhs_code (stmt)))
+ else if (gimple_with_undefined_signed_overflow (stmt))
/* We have to rewrite stmts with undefined overflow. */
need_to_rewrite_undefined = true;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
{
gassign *stmt = dyn_cast <gassign *> (gsi_stmt (gsi));
- tree lhs;
if (!stmt)
;
else if (is_false_predicate (cond)
gsi_replace (&gsi, new_stmt, true);
}
- else if (((lhs = gimple_assign_lhs (stmt)), true)
- && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
- && arith_code_with_undefined_signed_overflow
- (gimple_assign_rhs_code (stmt)))
+ else if (gimple_with_undefined_signed_overflow (stmt))
rewrite_to_defined_overflow (&gsi);
else if (gimple_vdef (stmt))
{
gsi_replace (&gsi, new_call, true);
}
- lhs = gimple_get_lhs (gsi_stmt (gsi));
+ tree lhs = gimple_get_lhs (gsi_stmt (gsi));
if (lhs && TREE_CODE (lhs) == SSA_NAME)
ssa_names.add (lhs);
gsi_next (&gsi);
gsi2 = gsi_start (stmts);
while (!gsi_end_p (gsi2))
{
- gimple *stmt = gsi_stmt (gsi2);
- if (is_gimple_assign (stmt)
- && arith_code_with_undefined_signed_overflow
- (gimple_assign_rhs_code (stmt)))
+ if (gimple_with_undefined_signed_overflow (gsi_stmt (gsi2)))
rewrite_to_defined_overflow (&gsi2);
gsi_next (&gsi2);
}
static inline void
ifcombine_rewrite_to_defined_overflow (gimple_stmt_iterator gsi)
{
- gassign *ass = dyn_cast <gassign *> (gsi_stmt (gsi));
- if (!ass)
+ if (!gimple_with_undefined_signed_overflow (gsi_stmt (gsi)))
return;
- tree lhs = gimple_assign_lhs (ass);
- if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && arith_code_with_undefined_signed_overflow
- (gimple_assign_rhs_code (ass)))
- rewrite_to_defined_overflow (&gsi);
+ rewrite_to_defined_overflow (&gsi);
}
when the target loop header is executed and the stmt may
invoke undefined integer or pointer overflow rewrite it to
unsigned arithmetic. */
- if (is_gimple_assign (stmt)
- && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
- && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (stmt)))
- && arith_code_with_undefined_signed_overflow
- (gimple_assign_rhs_code (stmt))
+ if (gimple_with_undefined_signed_overflow (stmt)
&& (!ALWAYS_EXECUTED_IN (bb)
|| !(ALWAYS_EXECUTED_IN (bb) == level
|| flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
gsi = gsi_start (stmts2);
while (!gsi_end_p (gsi))
{
- gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_assign (stmt)
- && arith_code_with_undefined_signed_overflow
- (gimple_assign_rhs_code (stmt)))
+ if (gimple_with_undefined_signed_overflow (gsi_stmt (gsi)))
rewrite_to_defined_overflow (&gsi);
gsi_next (&gsi);
}
!gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_assign (stmt))
- if (tree lhs = gimple_assign_lhs (stmt))
- if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)))
- {
- enum tree_code code = gimple_assign_rhs_code (stmt);
- if (arith_code_with_undefined_signed_overflow (code))
- {
- gimple_stmt_iterator gsip = gsi;
- gimple_stmt_iterator gsin = gsi;
- gsi_prev (&gsip);
- gsi_next (&gsin);
- rewrite_to_defined_overflow (&gsi);
- unsigned uid = gimple_uid (stmt);
- if (gsi_end_p (gsip))
- gsip = gsi_after_labels (bb);
- else
- gsi_next (&gsip);
- for (; gsi_stmt (gsip) != gsi_stmt (gsin);
- gsi_next (&gsip))
- gimple_set_uid (gsi_stmt (gsip), uid);
- }
- }
+ if (gimple_with_undefined_signed_overflow (stmt))
+ {
+ gimple_stmt_iterator gsip = gsi;
+ gimple_stmt_iterator gsin = gsi;
+ gsi_prev (&gsip);
+ gsi_next (&gsin);
+ rewrite_to_defined_overflow (&gsi);
+ unsigned uid = gimple_uid (stmt);
+ if (gsi_end_p (gsip))
+ gsip = gsi_after_labels (bb);
+ else
+ gsi_next (&gsip);
+ for (; gsi_stmt (gsip) != gsi_stmt (gsin);
+ gsi_next (&gsip))
+ gimple_set_uid (gsi_stmt (gsip), uid);
+ }
}
if (opcode == BIT_IOR_EXPR