The following patch implements patterns to catch x / abs (x) and x / -x, taking advantage of undefinedness at x == 0 as opposed to the PR having testcases with explicit != 0 checks.
Bootstrap / regtest pending on x86_64-unknown-linux-gnu. Richard. 2016-09-28 Richard Biener <rguent...@suse.de> PR middle-end/77407 * match.pd: Add X / abs (X) -> X < 0 ? -1 : 1 and X / -X -> -1 simplifications. * gcc.dg/pr77407.c: New testcase. Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 240565) +++ gcc/match.pd (working copy) @@ -147,12 +147,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (op @0 integer_onep) (non_lvalue @0))) -/* X / -1 is -X. */ (for div (trunc_div ceil_div floor_div round_div exact_div) + /* X / -1 is -X. */ (simplify (div @0 integer_minus_onep@1) (if (!TYPE_UNSIGNED (type)) - (negate @0)))) + (negate @0))) + /* X / abs (X) is X < 0 ? -1 : 1. */ + (simplify + (div @0 (abs @0)) + (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) + && TYPE_OVERFLOW_UNDEFINED (type)) + (cond (lt @0 { build_zero_cst (type); }) + { build_minus_one_cst (type); } { build_one_cst (type); }))) + /* X / -X is -1. */ + (simplify + (div @0 (negate @0)) + (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) + && TYPE_OVERFLOW_UNDEFINED (type)) + { build_minus_one_cst (type); }))) /* For unsigned integral types, FLOOR_DIV_EXPR is the same as TRUNC_DIV_EXPR. Rewrite into the latter in this case. */ Index: gcc/testsuite/gcc.dg/pr77407.c =================================================================== --- gcc/testsuite/gcc.dg/pr77407.c (revision 0) +++ gcc/testsuite/gcc.dg/pr77407.c (working copy) @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fstrict-overflow -fdump-tree-gimple" } */ + +int foo (int c) +{ + if (c != 0) + c /= __builtin_abs (c); + return c; +} + +int bar (int c) +{ + if (c != 0) + c /= -c; + return c; +} + +/* { dg-final { scan-tree-dump-times "/" 0 "gimple" } } */