summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-05-30 21:33:32 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-05-30 21:33:32 +0000
commit9ae13cc6f4a8b8e94ee762813b673191a94280b1 (patch)
treedd32c83a5ab688b1765c9c952a826e5e04b594de /gcc
parentcb59f96973826a295b4f864bcda38b240ba33e44 (diff)
downloadgcc-9ae13cc6f4a8b8e94ee762813b673191a94280b1.tar.gz
* expmed.c (const_mult_add_overflow_p): New.
* expr.h: Declare it. * loop.c (maybe_eliminate_biv_1) [COMPARE]: Use it. Don't eliminate the biv if the giv has a constant multiplier and the rhs argument of the comparison does satisfy the predicate. Use expand_mult_add to compute the replacement constant. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54075 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/expmed.c38
-rw-r--r--gcc/expr.h1
-rw-r--r--gcc/loop.c27
4 files changed, 69 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4890db352f2..07443b6363b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2002-05-30 Eric Botcazou <ebotcazou@multimania.com>
+
+ * expmed.c (const_mult_add_overflow_p): New.
+ * expr.h: Declare it.
+ * loop.c (maybe_eliminate_biv_1) [COMPARE]: Use it.
+ Don't eliminate the biv if the giv has a constant multiplier and
+ the rhs argument of the comparison does satisfy the predicate.
+ Use expand_mult_add to compute the replacement constant.
+
2002-05-30 Osku Salerma <osku@iki.fi>
* c-common.c (c_common_attribute_table): Add "may_alias" entry.
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 5a4c24ea68a..9419681dcae 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -4156,6 +4156,44 @@ make_tree (type, x)
}
}
+/* Check whether the multiplication X * MULT + ADD overflows.
+ X, MULT and ADD must be CONST_*.
+ MODE is the machine mode for the computation.
+ X and MULT must have mode MODE. ADD may have a different mode.
+ So can X (defaults to same as MODE).
+ UNSIGNEDP is non-zero to do unsigned multiplication. */
+
+bool
+const_mult_add_overflow_p (x, mult, add, mode, unsignedp)
+ rtx x, mult, add;
+ enum machine_mode mode;
+ int unsignedp;
+{
+ tree type, mult_type, add_type, result;
+
+ type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
+
+ /* In order to get a proper overflow indication from an unsigned
+ type, we have to pretend that it's a sizetype. */
+ mult_type = type;
+ if (unsignedp)
+ {
+ mult_type = copy_node (type);
+ TYPE_IS_SIZETYPE (mult_type) = 1;
+ }
+
+ add_type = (GET_MODE (add) == VOIDmode ? mult_type
+ : (*lang_hooks.types.type_for_mode) (GET_MODE (add), unsignedp));
+
+ result = fold (build (PLUS_EXPR, mult_type,
+ fold (build (MULT_EXPR, mult_type,
+ make_tree (mult_type, x),
+ make_tree (mult_type, mult))),
+ make_tree (add_type, add)));
+
+ return TREE_CONSTANT_OVERFLOW (result);
+}
+
/* Return an rtx representing the value of X * MULT + ADD.
TARGET is a suggestion for where to store the result (an rtx).
MODE is the machine mode for the computation.
diff --git a/gcc/expr.h b/gcc/expr.h
index 91ffa3f0507..fa51a8a3191 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -758,6 +758,7 @@ extern rtx extract_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
enum machine_mode, enum machine_mode,
HOST_WIDE_INT));
extern rtx expand_mult PARAMS ((enum machine_mode, rtx, rtx, rtx, int));
+extern bool const_mult_add_overflow_p PARAMS ((rtx, rtx, rtx, enum machine_mode, int));
extern rtx expand_mult_add PARAMS ((rtx, rtx, rtx, rtx,enum machine_mode, int));
extern rtx expand_mult_highpart_adjust PARAMS ((enum machine_mode, rtx, rtx, rtx, rtx, int));
diff --git a/gcc/loop.c b/gcc/loop.c
index 8581af2746e..20c5f1dab0a 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -8863,6 +8863,22 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
+ /* Don't eliminate if the linear combination that makes up
+ the giv overflows when it is applied to ARG. */
+ if (GET_CODE (arg) == CONST_INT)
+ {
+ rtx add_val;
+
+ if (GET_CODE (v->add_val) == CONST_INT)
+ add_val = v->add_val;
+ else
+ add_val = const0_rtx;
+
+ if (const_mult_add_overflow_p (arg, v->mult_val,
+ add_val, mode, 1))
+ continue;
+ }
+
if (! eliminate_p)
return 1;
@@ -8873,13 +8889,10 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
the derived constant can be directly placed in the COMPARE,
do so. */
if (GET_CODE (arg) == CONST_INT
- && GET_CODE (v->mult_val) == CONST_INT
&& GET_CODE (v->add_val) == CONST_INT)
{
- validate_change (insn, &XEXP (x, arg_operand),
- GEN_INT (INTVAL (arg)
- * INTVAL (v->mult_val)
- + INTVAL (v->add_val)), 1);
+ tem = expand_mult_add (arg, NULL_RTX, v->mult_val,
+ v->add_val, mode, 1);
}
else
{
@@ -8888,8 +8901,10 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
loop_iv_add_mult_emit_before (loop, arg,
v->mult_val, v->add_val,
tem, where_bb, where_insn);
- validate_change (insn, &XEXP (x, arg_operand), tem, 1);
}
+
+ validate_change (insn, &XEXP (x, arg_operand), tem, 1);
+
if (apply_change_group ())
return 1;
}