diff options
author | Richard Guenther <rguenther@suse.de> | 2007-11-12 13:24:06 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2007-11-12 13:24:06 +0000 |
commit | 65648dd47e35451645d3f2fb2cdcd02cf43e1d87 (patch) | |
tree | 1748ca812d38b49f003e3b8885790ebee8e08000 /gcc/fold-const.c | |
parent | 50d76c246f1268b945c941c24d877b7acc5acae9 (diff) | |
download | gcc-65648dd47e35451645d3f2fb2cdcd02cf43e1d87.zip gcc-65648dd47e35451645d3f2fb2cdcd02cf43e1d87.tar.gz gcc-65648dd47e35451645d3f2fb2cdcd02cf43e1d87.tar.bz2 |
re PR tree-optimization/34027 (-Os code size nearly doubled)
2007-11-12 Richard Guenther <rguenther@suse.de>
PR middle-end/34027
* fold-const.c (fold_binary): Fold n - (n / m) * m to n % m.
(fold_binary): Fold unsinged FLOOR_DIV_EXPR to TRUNC_DIV_EXPR.
* gcc.dg/pr34027-1.c: New testcase.
* gcc.dg/pr34027-2.c: Likewise.
From-SVN: r130097
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a09c9ea..5b81d88 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -9653,6 +9653,21 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return omit_one_operand (type, t1, arg0); } } + + /* X + (X / CST) * -CST is X % CST. */ + if (TREE_CODE (arg1) == MULT_EXPR + && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR + && operand_equal_p (arg0, + TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)) + { + tree cst0 = TREE_OPERAND (TREE_OPERAND (arg1, 0), 1); + tree cst1 = TREE_OPERAND (arg1, 1); + tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (cst1), cst1, cst0); + if (sum && integer_zerop (sum)) + return fold_convert (type, + fold_build2 (TRUNC_MOD_EXPR, + TREE_TYPE (arg0), arg0, cst0)); + } } /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the @@ -10061,6 +10076,19 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) && integer_all_onesp (arg0)) return fold_build1 (BIT_NOT_EXPR, type, op1); + + /* X - (X / CST) * CST is X % CST. */ + if (INTEGRAL_TYPE_P (type) + && TREE_CODE (arg1) == MULT_EXPR + && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR + && operand_equal_p (arg0, + TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0) + && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1), + TREE_OPERAND (arg1, 1), 0)) + return fold_convert (type, + fold_build2 (TRUNC_MOD_EXPR, TREE_TYPE (arg0), + arg0, TREE_OPERAND (arg1, 1))); + if (! FLOAT_TYPE_P (type)) { if (integer_zerop (arg0)) @@ -11221,6 +11249,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) fold_convert (type, arg0), sh_cnt); } } + + /* For unsigned integral types, FLOOR_DIV_EXPR is the same as + TRUNC_DIV_EXPR. Rewrite into the latter in this case. */ + if (INTEGRAL_TYPE_P (type) + && TYPE_UNSIGNED (type) + && code == FLOOR_DIV_EXPR) + return fold_build2 (TRUNC_DIV_EXPR, type, op0, op1); + /* Fall thru */ case ROUND_DIV_EXPR: |