aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2007-11-12 13:24:06 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2007-11-12 13:24:06 +0000
commit65648dd47e35451645d3f2fb2cdcd02cf43e1d87 (patch)
tree1748ca812d38b49f003e3b8885790ebee8e08000 /gcc/fold-const.c
parent50d76c246f1268b945c941c24d877b7acc5acae9 (diff)
downloadgcc-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.c36
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: