diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2008-09-10 13:28:34 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2008-09-10 13:28:34 +0000 |
commit | 90cbba020c11026300318186dddf251194e3bc53 (patch) | |
tree | a5adf4180e38242aff75f589555de75322e1c292 /gcc/config | |
parent | 06c7153ff1c52ab47808fc00b72b98894ec858b8 (diff) | |
download | gcc-90cbba020c11026300318186dddf251194e3bc53.zip gcc-90cbba020c11026300318186dddf251194e3bc53.tar.gz gcc-90cbba020c11026300318186dddf251194e3bc53.tar.bz2 |
bfin.c (workaround_speculation): Correct algorithm to not lose track of the number of NOPs needed.
* config/bfin/bfin.c (workaround_speculation): Correct algorithm to
not lose track of the number of NOPs needed. Number of NOPs needed
for sync vs. loads workaround was switched; corrected. Run second
pass for all workarounds. No NOPs needed after call insns. Change
second pass to use find_next_insn_start and find_load helpers in order
to properly detect parallel insns.
* config/bfin/bfin.md (cbranch_with_nops): Increase length.
From-SVN: r140230
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/bfin/bfin.c | 78 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.md | 2 |
2 files changed, 50 insertions, 30 deletions
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 7ff1379..9af7fab 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -4799,6 +4799,7 @@ workaround_speculation (void) rtx insn, next; rtx last_condjump = NULL_RTX; int cycles_since_jump = INT_MAX; + int delay_added = 0; if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS) return; @@ -4808,6 +4809,7 @@ workaround_speculation (void) for (insn = get_insns (); insn; insn = next) { rtx pat; + int delay_needed = 0; next = find_next_insn_start (insn); @@ -4826,6 +4828,7 @@ workaround_speculation (void) && ! cbranch_predicted_taken_p (insn)) { last_condjump = insn; + delay_added = 0; cycles_since_jump = 0; } else @@ -4835,49 +4838,56 @@ workaround_speculation (void) { rtx load_insn = find_load (insn); enum attr_type type = type_for_anomaly (insn); - int delay_needed = 0; + if (cycles_since_jump < INT_MAX) cycles_since_jump++; if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) { if (trapping_loads_p (load_insn)) - delay_needed = 3; + delay_needed = 4; } else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) - delay_needed = 4; + delay_needed = 3; + } - if (delay_needed > cycles_since_jump) - { - rtx pat; - int num_clobbers; - rtx *op = recog_data.operand; + if (delay_needed > cycles_since_jump + && (delay_needed - cycles_since_jump) > delay_added) + { + rtx pat1; + int num_clobbers; + rtx *op = recog_data.operand; - delay_needed -= cycles_since_jump; + delay_needed -= cycles_since_jump; - extract_insn (last_condjump); - if (optimize_size) - { - pat = gen_cbranch_predicted_taken (op[0], op[1], op[2], - op[3]); - cycles_since_jump = INT_MAX; - } - else - /* Do not adjust cycles_since_jump in this case, so that - we'll increase the number of NOPs for a subsequent insn - if necessary. */ - pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3], - GEN_INT (delay_needed)); - PATTERN (last_condjump) = pat; - INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers); + extract_insn (last_condjump); + if (optimize_size) + { + pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2], + op[3]); + cycles_since_jump = INT_MAX; + } + else + { + /* Do not adjust cycles_since_jump in this case, so that + we'll increase the number of NOPs for a subsequent insn + if necessary. */ + pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3], + GEN_INT (delay_needed)); + delay_added = delay_needed; } + PATTERN (last_condjump) = pat1; + INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers); + } + if (CALL_P (insn)) + { + cycles_since_jump = INT_MAX; + delay_added = 0; } } + /* Second pass: for predicted-true branches, see if anything at the branch destination needs extra nops. */ - if (! ENABLE_WA_SPECULATIVE_SYNCS) - return; - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { int cycles_since_jump; @@ -4888,11 +4898,15 @@ workaround_speculation (void) { rtx target = JUMP_LABEL (insn); rtx label = target; + rtx next_tgt; + cycles_since_jump = 0; - for (; target && cycles_since_jump < 3; target = NEXT_INSN (target)) + for (; target && cycles_since_jump < 3; target = next_tgt) { rtx pat; + next_tgt = find_next_insn_start (target); + if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target)) continue; @@ -4904,12 +4918,18 @@ workaround_speculation (void) if (INSN_P (target)) { + rtx load_insn = find_load (target); enum attr_type type = type_for_anomaly (target); int delay_needed = 0; if (cycles_since_jump < INT_MAX) cycles_since_jump++; - if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) + if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) + { + if (trapping_loads_p (load_insn)) + delay_needed = 2; + } + else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) delay_needed = 2; if (delay_needed > cycles_since_jump) diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 1388266..bd2d208 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -2588,7 +2588,7 @@ return ""; } [(set_attr "type" "brcc") - (set_attr "length" "6")]) + (set_attr "length" "8")]) ;; setcc insns. */ (define_expand "seq" |