summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-12 04:01:04 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-12 04:01:04 +0000
commit59ff7b6e271e2d9b3cd5df791e039d9c12d178e0 (patch)
treefc30e6d27de3e811bf01d5d624f1b7c9f3a541d8 /gcc/fold-const.c
parentd38cff3040db5b167aec03750793417522d85f6c (diff)
downloadgcc-59ff7b6e271e2d9b3cd5df791e039d9c12d178e0.tar.gz
* stor-layout.c (round_up, round_down): Move ...
* fold-const.c (round_up, round_down): ... here. Use multiple_of_p to avoid any arithmetic at all. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@85848 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0b225c05e02..f7e90be6eaa 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -10678,4 +10678,74 @@ fold_ignored_result (tree t)
}
}
+/* Return the value of VALUE, rounded up to a multiple of DIVISOR.
+ This can only be applied to objects of a sizetype. */
+
+tree
+round_up (tree value, int divisor)
+{
+ tree div, t;
+
+ if (divisor == 0)
+ abort ();
+ if (divisor == 1)
+ return value;
+
+ div = size_int_type (divisor, TREE_TYPE (value));
+
+ /* See if VALUE is already a multiple of DIVISOR. If so, we don't
+ have to do anything. */
+ if (multiple_of_p (TREE_TYPE (value), value, div))
+ return value;
+
+ /* If divisor is a power of two, simplify this to bit manipulation. */
+ if (divisor == (divisor & -divisor))
+ {
+ t = size_int_type (divisor - 1, TREE_TYPE (value));
+ value = size_binop (PLUS_EXPR, value, t);
+ t = size_int_type (-divisor, TREE_TYPE (value));
+ value = size_binop (BIT_AND_EXPR, value, t);
+ }
+ else
+ {
+ value = size_binop (CEIL_DIV_EXPR, value, div);
+ value = size_binop (MULT_EXPR, value, div);
+ }
+
+ return value;
+}
+
+/* Likewise, but round down. */
+
+tree
+round_down (tree value, int divisor)
+{
+ tree div, t;
+
+ if (divisor == 0)
+ abort ();
+ if (divisor == 1)
+ return value;
+
+ div = size_int_type (divisor, TREE_TYPE (value));
+
+ /* See if VALUE is already a multiple of DIVISOR. If so, we don't
+ have to do anything. */
+ if (multiple_of_p (TREE_TYPE (value), value, div))
+ return value;
+
+ /* If divisor is a power of two, simplify this to bit manipulation. */
+ if (divisor == (divisor & -divisor))
+ {
+ t = size_int_type (-divisor, TREE_TYPE (value));
+ value = size_binop (BIT_AND_EXPR, value, t);
+ }
+ else
+ {
+ value = size_binop (FLOOR_DIV_EXPR, value, div);
+ value = size_binop (MULT_EXPR, value, div);
+ }
+
+ return value;
+}
#include "gt-fold-const.h"