summaryrefslogtreecommitdiff
path: root/gcc/loop-unroll.c
diff options
context:
space:
mode:
authorrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>2007-04-22 08:46:58 +0000
committerrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>2007-04-22 08:46:58 +0000
commit0def560a88d9ac13cd58e9401a973d91179c4a1c (patch)
treeaa0d038c63131fc361c9f428ff9dd8aaca536e40 /gcc/loop-unroll.c
parent4f80b75acee54e7747ab706ce5d402f5c7ecc773 (diff)
downloadgcc-0def560a88d9ac13cd58e9401a973d91179c4a1c.tar.gz
Extend MVE patterns
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@124037 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/loop-unroll.c')
-rw-r--r--gcc/loop-unroll.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 0ef434ce8bf..d1322d11e39 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -98,6 +98,10 @@ struct var_to_expand
the accumulator. If REUSE_EXPANSION is 0 reuse
the original accumulator. Else use
var_expansions[REUSE_EXPANSION - 1]. */
+ unsigned accum_pos; /* The position in which the accumulator is placed in
+ the insn src. For example in x = x + something
+ accum_pos is 0 while in x = something + x accum_pos
+ is 1. */
};
/* Information about optimization applied in
@@ -1565,10 +1569,11 @@ referenced_in_one_insn_in_loop_p (struct loop *loop, rtx reg)
static struct var_to_expand *
analyze_insn_to_expand_var (struct loop *loop, rtx insn)
{
- rtx set, dest, src, op1;
+ rtx set, dest, src, op1, op2, something;
struct var_to_expand *ves;
enum machine_mode mode1, mode2;
-
+ unsigned accum_pos;
+
set = single_set (insn);
if (!set)
return NULL;
@@ -1593,27 +1598,39 @@ analyze_insn_to_expand_var (struct loop *loop, rtx insn)
if (!have_insn_for (GET_CODE (src), GET_MODE (src)))
return NULL;
- if (!XEXP (src, 0))
- return NULL;
-
op1 = XEXP (src, 0);
+ op2 = XEXP (src, 1);
if (!REG_P (dest)
&& !(GET_CODE (dest) == SUBREG
&& REG_P (SUBREG_REG (dest))))
return NULL;
- if (!rtx_equal_p (dest, op1))
- return NULL;
-
+ if (rtx_equal_p (dest, op1))
+ accum_pos = 0;
+ else if (rtx_equal_p (dest, op2))
+ accum_pos = 1;
+ else
+ return NULL;
+
+ /* The method of expansion that we are using; which includes
+ the initialization of the expansions with zero and the summation of
+ the expansions at the end of the computation will yield wrong results
+ for (x = something - x) thus avoid using it in that case. */
+ if (accum_pos == 1
+ && GET_CODE (src) == MINUS)
+ return NULL;
+
+ something = (accum_pos == 0)? op2 : op1;
+
if (!referenced_in_one_insn_in_loop_p (loop, dest))
return NULL;
- if (rtx_referenced_p (dest, XEXP (src, 1)))
+ if (rtx_referenced_p (dest, something))
return NULL;
mode1 = GET_MODE (dest);
- mode2 = GET_MODE (XEXP (src, 1));
+ mode2 = GET_MODE (something);
if ((FLOAT_MODE_P (mode1)
|| FLOAT_MODE_P (mode2))
&& !flag_unsafe_math_optimizations)
@@ -1635,6 +1652,7 @@ analyze_insn_to_expand_var (struct loop *loop, rtx insn)
ves->op = GET_CODE (src);
ves->expansion_count = 0;
ves->reuse_expansion = 0;
+ ves->accum_pos = accum_pos;
return ves;
}
@@ -1983,7 +2001,7 @@ expand_var_during_unrolling (struct var_to_expand *ve, rtx insn)
new_reg = get_expansion (ve);
validate_change (insn, &SET_DEST (set), new_reg, 1);
- validate_change (insn, &XEXP (SET_SRC (set), 0), new_reg, 1);
+ validate_change (insn, &XEXP (SET_SRC (set), ve->accum_pos), new_reg, 1);
if (apply_change_group ())
if (really_new_expansion)