diff options
author | Revital Eres <revital.eres@linaro.org> | 2011-05-11 07:08:44 +0000 |
---|---|---|
committer | Revital Eres <revital.eres@linaro.org> | 2011-05-11 07:08:44 +0000 |
commit | 102dc8a2d738ca3423b1b49e6dc7ed5df5a55148 (patch) | |
tree | 2ce89b08c7f88397801fe13872af4ffdb5a6a5a4 /gcc/loop-doloop.c | |
parent | 86b2821634193ee3ab24972404c7fad7e83f983e (diff) |
Doloop pattern for ARM
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@173645 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/loop-doloop.c')
-rw-r--r-- | gcc/loop-doloop.c | 74 |
1 files changed, 67 insertions, 7 deletions
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c index 1833954595f..1527c48500c 100644 --- a/gcc/loop-doloop.c +++ b/gcc/loop-doloop.c @@ -78,6 +78,8 @@ doloop_condition_get (rtx doloop_pat) rtx inc_src; rtx condition; rtx pattern; + rtx cc_reg = NULL_RTX; + rtx reg_orig = NULL_RTX; /* The canonical doloop pattern we expect has one of the following forms: @@ -96,7 +98,16 @@ doloop_condition_get (rtx doloop_pat) 2) (set (reg) (plus (reg) (const_int -1)) (set (pc) (if_then_else (reg != 0) (label_ref (label)) - (pc))). */ + (pc))). + + Some targets (ARM) do the comparison before the branch, as in the + following form: + + 3) (parallel [(set (cc) (compare ((plus (reg) (const_int -1), 0))) + (set (reg) (plus (reg) (const_int -1)))]) + (set (pc) (if_then_else (cc == NE) + (label_ref (label)) + (pc))) */ pattern = PATTERN (doloop_pat); @@ -104,19 +115,47 @@ doloop_condition_get (rtx doloop_pat) { rtx cond; rtx prev_insn = prev_nondebug_insn (doloop_pat); + rtx cmp_arg1, cmp_arg2; + rtx cmp_orig; - /* We expect the decrement to immediately precede the branch. */ + /* In case the pattern is not PARALLEL we expect two forms + of doloop which are cases 2) and 3) above: in case 2) the + decrement immediately precedes the branch, while in case 3) + the compare and decrement instructions immediately precede + the branch. */ if (prev_insn == NULL_RTX || !INSN_P (prev_insn)) return 0; cmp = pattern; - inc = PATTERN (PREV_INSN (doloop_pat)); + if (GET_CODE (PATTERN (prev_insn)) == PARALLEL) + { + /* The third case: the compare and decrement instructions + immediately precede the branch. */ + cmp_orig = XVECEXP (PATTERN (prev_insn), 0, 0); + if (GET_CODE (cmp_orig) != SET) + return 0; + if (GET_CODE (SET_SRC (cmp_orig)) != COMPARE) + return 0; + cmp_arg1 = XEXP (SET_SRC (cmp_orig), 0); + cmp_arg2 = XEXP (SET_SRC (cmp_orig), 1); + if (cmp_arg2 != const0_rtx + || GET_CODE (cmp_arg1) != PLUS) + return 0; + reg_orig = XEXP (cmp_arg1, 0); + if (XEXP (cmp_arg1, 1) != GEN_INT (-1) + || !REG_P (reg_orig)) + return 0; + cc_reg = SET_DEST (cmp_orig); + + inc = XVECEXP (PATTERN (prev_insn), 0, 1); + } + else + inc = PATTERN (PREV_INSN (doloop_pat)); /* We expect the condition to be of the form (reg != 0) */ cond = XEXP (SET_SRC (cmp), 0); if (GET_CODE (cond) != NE || XEXP (cond, 1) != const0_rtx) return 0; - } else { @@ -162,11 +201,15 @@ doloop_condition_get (rtx doloop_pat) return 0; if ((XEXP (condition, 0) == reg) + /* For the third case: */ + || ((cc_reg != NULL_RTX) + && (XEXP (condition, 0) == cc_reg) + && (reg_orig == reg)) || (GET_CODE (XEXP (condition, 0)) == PLUS - && XEXP (XEXP (condition, 0), 0) == reg)) + && XEXP (XEXP (condition, 0), 0) == reg)) { if (GET_CODE (pattern) != PARALLEL) - /* The second form we expect: + /* For the second form we expect: (set (reg) (plus (reg) (const_int -1)) (set (pc) (if_then_else (reg != 0) @@ -181,7 +224,24 @@ doloop_condition_get (rtx doloop_pat) (set (reg) (plus (reg) (const_int -1))) (additional clobbers and uses)]) - So we return that form instead. + For the third form we expect: + + (parallel [(set (cc) (compare ((plus (reg) (const_int -1)), 0)) + (set (reg) (plus (reg) (const_int -1)))]) + (set (pc) (if_then_else (cc == NE) + (label_ref (label)) + (pc))) + + which is equivalent to the following: + + (parallel [(set (cc) (compare (reg, 1)) + (set (reg) (plus (reg) (const_int -1))) + (set (pc) (if_then_else (NE == cc) + (label_ref (label)) + (pc))))]) + + So we return the second form instead for the two cases. + */ condition = gen_rtx_fmt_ee (NE, VOIDmode, inc_src, const1_rtx); |