diff options
author | Mrinmoy Ghosh <mrinmoy.ghosh@arm.com> | 2012-02-13 12:26:25 -0600 |
---|---|---|
committer | Mrinmoy Ghosh <mrinmoy.ghosh@arm.com> | 2012-02-13 12:26:25 -0600 |
commit | 9b05e96b9efdb9cdcc4e40ef9c96b1228df7a175 (patch) | |
tree | 54471a114f0d7bc09853bb48e8161fe5fec79d12 /src/cpu/pred | |
parent | fd90c3676d94520b98a9af29af09c1f8a2858465 (diff) | |
download | gem5-9b05e96b9efdb9cdcc4e40ef9c96b1228df7a175.tar.xz |
BPred: Fix RAS to handle predicated call/return instructions.
Change RAS to fix issues with predicated call/return instructions.
Handled all cases in the life of a predicated call and return instruction.
Diffstat (limited to 'src/cpu/pred')
-rw-r--r-- | src/cpu/pred/tournament.cc | 97 |
1 files changed, 54 insertions, 43 deletions
diff --git a/src/cpu/pred/tournament.cc b/src/cpu/pred/tournament.cc index 3adafb608..b6320ca8a 100644 --- a/src/cpu/pred/tournament.cc +++ b/src/cpu/pred/tournament.cc @@ -258,59 +258,70 @@ TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history, local_predictor_hist = localHistoryTable[local_history_idx]; local_predictor_idx = local_predictor_hist & localPredictorMask; - // Update the choice predictor to tell it which one was correct if - // there was a prediction. if (bp_history) { BPHistory *history = static_cast<BPHistory *>(bp_history); - if (history->localPredTaken != history->globalPredTaken) { - // If the local prediction matches the actual outcome, - // decerement the counter. Otherwise increment the - // counter. - if (history->localPredTaken == taken) { - choiceCtrs[history->globalHistory].decrement(); - } else if (history->globalPredTaken == taken){ - choiceCtrs[history->globalHistory].increment(); - } - - } - - // Update the counters and local history with the proper - // resolution of the branch. Global history is updated - // speculatively and restored upon squash() calls, so it does not - // need to be updated. + // Update may also be called if the Branch target is incorrect even if + // the prediction is correct. In that case do not update the counters. + bool historyPred = false; unsigned old_local_pred_index = history->localHistory - & localPredictorMask; - if (taken) { - globalCtrs[history->globalHistory].increment(); - if (old_local_pred_index != invalidPredictorIndex) { - localCtrs[old_local_pred_index].increment(); - } + & localPredictorMask; + if (history->globalUsed) { + historyPred = history->globalPredTaken; } else { - globalCtrs[history->globalHistory].decrement(); - if (old_local_pred_index != invalidPredictorIndex) { - localCtrs[old_local_pred_index].decrement(); - } - } - - if (squashed) { - if (taken) { - globalHistory = (history->globalHistory << 1) | 1; - globalHistory = globalHistory & globalHistoryMask; - if (history->localHistory != invalidPredictorIndex) - localHistoryTable[local_history_idx] = + historyPred = history->localPredTaken; + } + if (historyPred != taken || !squashed) { + // Update the choice predictor to tell it which one was correct if + // there was a prediction. + if (history->localPredTaken != history->globalPredTaken) { + // If the local prediction matches the actual outcome, + // decerement the counter. Otherwise increment the + // counter. + if (history->localPredTaken == taken) { + choiceCtrs[history->globalHistory].decrement(); + } else if (history->globalPredTaken == taken) { + choiceCtrs[history->globalHistory].increment(); + } + + } + + // Update the counters and local history with the proper + // resolution of the branch. Global history is updated + // speculatively and restored upon squash() calls, so it does not + // need to be updated. + if (taken) { + globalCtrs[history->globalHistory].increment(); + if (old_local_pred_index != invalidPredictorIndex) { + localCtrs[old_local_pred_index].increment(); + } + } else { + globalCtrs[history->globalHistory].decrement(); + if (old_local_pred_index != invalidPredictorIndex) { + localCtrs[old_local_pred_index].decrement(); + } + } + } + if (squashed) { + if (taken) { + globalHistory = (history->globalHistory << 1) | 1; + globalHistory = globalHistory & globalHistoryMask; + if (old_local_pred_index != invalidPredictorIndex) { + localHistoryTable[old_local_pred_index] = (history->localHistory << 1) | 1; - } else { - globalHistory = (history->globalHistory << 1); - globalHistory = globalHistory & globalHistoryMask; - if (history->localHistory != invalidPredictorIndex) { - localHistoryTable[local_history_idx] = + } + } else { + globalHistory = (history->globalHistory << 1); + globalHistory = globalHistory & globalHistoryMask; + if (old_local_pred_index != invalidPredictorIndex) { + localHistoryTable[old_local_pred_index] = history->localHistory << 1; - } - } + } + } } // We're done with this history, now delete it. delete history; + } assert(globalHistory < globalPredictorSize && |