diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr105776.c | 43 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.cc | 25 |
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)); } |