aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.target/i386/pr105776.c43
-rw-r--r--gcc/tree-ssa-math-opts.cc25
2 files changed, 68 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.target/i386/pr105776.c b/gcc/testsuite/gcc.target/i386/pr105776.c
new file mode 100644
index 0000000..56878bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr105776.c
@@ -0,0 +1,43 @@
+/* PR tree-optimization/105776 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -masm=att" } */
+/* { dg-final { scan-tree-dump-times " = \.MUL_OVERFLOW " 5 "optimized" } } */
+/* { dg-final { scan-assembler-times "\timull\t" 5 } } */
+/* { dg-final { scan-assembler-times "\tsetno\t" 5 } } */
+
+int
+foo (unsigned x, unsigned y)
+{
+ unsigned int r = x * y;
+ return !x || ((int) r / (int) x) == (int) y;
+}
+
+int
+bar (unsigned x, unsigned y)
+{
+ return !x || ((int) (x * y) / (int) x) == (int) y;
+}
+
+int
+baz (unsigned x, unsigned y)
+{
+ if (x == 0)
+ return 1;
+ return ((int) (x * y) / (int) x) == y;
+}
+
+int
+qux (unsigned x, unsigned y, unsigned *z)
+{
+ unsigned int r = x * y;
+ *z = r;
+ return !x || ((int) r / (int) x) == (int) y;
+}
+
+int
+corge (unsigned x, unsigned y, unsigned *z)
+{
+ unsigned int r = x * y;
+ *z = r;
+ return !x || ((int) r / (int) x) == y;
+}
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index d80d53d..9c9ca57 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -3802,6 +3802,21 @@ arith_overflow_check_p (gimple *stmt, gimple *cast_stmt, gimple *&use_stmt,
use_operand_p use;
if (!single_imm_use (divlhs, &use, &cur_use_stmt))
return 0;
+ if (cast_stmt && gimple_assign_cast_p (cur_use_stmt))
+ {
+ tree cast_lhs = gimple_assign_lhs (cur_use_stmt);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (cast_lhs))
+ && TYPE_UNSIGNED (TREE_TYPE (cast_lhs))
+ && (TYPE_PRECISION (TREE_TYPE (cast_lhs))
+ == TYPE_PRECISION (TREE_TYPE (divlhs)))
+ && single_imm_use (cast_lhs, &use, &cur_use_stmt))
+ {
+ cast_stmt = NULL;
+ divlhs = cast_lhs;
+ }
+ else
+ return 0;
+ }
}
if (gimple_code (cur_use_stmt) == GIMPLE_COND)
{
@@ -4390,6 +4405,16 @@ match_arith_overflow (gimple_stmt_iterator *gsi, gimple *stmt,
gimple_stmt_iterator gsi2 = gsi_for_stmt (orig_use_stmt);
maybe_optimize_guarding_check (mul_stmts, use_stmt, orig_use_stmt,
cfg_changed);
+ use_operand_p use;
+ gimple *cast_stmt;
+ if (single_imm_use (gimple_assign_lhs (orig_use_stmt), &use,
+ &cast_stmt)
+ && gimple_assign_cast_p (cast_stmt))
+ {
+ gimple_stmt_iterator gsi3 = gsi_for_stmt (cast_stmt);
+ gsi_remove (&gsi3, true);
+ release_ssa_name (gimple_assign_lhs (cast_stmt));
+ }
gsi_remove (&gsi2, true);
release_ssa_name (gimple_assign_lhs (orig_use_stmt));
}