diff --git a/src/cpu/pred/2bit_local.hh b/src/cpu/pred/2bit_local.hh index 23683cc67..e008c6232 100644 --- a/src/cpu/pred/2bit_local.hh +++ b/src/cpu/pred/2bit_local.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011, 2014 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -92,6 +92,9 @@ class LocalBP : public BPredUnit */ void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); + void retireSquashed(void *bp_history) + { assert(bp_history == NULL); } + void squash(void *bp_history) { assert(bp_history == NULL); } diff --git a/src/cpu/pred/bpred_unit.hh b/src/cpu/pred/bpred_unit.hh index 61b375f9b..f75ab79d5 100644 --- a/src/cpu/pred/bpred_unit.hh +++ b/src/cpu/pred/bpred_unit.hh @@ -178,6 +178,13 @@ class BPredUnit : public SimObject */ virtual void update(Addr instPC, bool taken, void *bp_history, bool squashed) = 0; + /** + * Deletes the associated history with a branch, performs no predictor + * updates. Used for branches that mispredict and update tables but + * are still speculative and later retire. + * @param bp_history History to delete associated with this predictor + */ + virtual void retireSquashed(void *bp_history) = 0; /** * Updates the BTB with the target of a branch. @@ -200,7 +207,7 @@ class BPredUnit : public SimObject ThreadID _tid) : seqNum(seq_num), pc(instPC), bpHistory(bp_history), RASTarget(0), RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0), pushedRAS(0), - wasCall(0), wasReturn(0) + wasCall(0), wasReturn(0), wasSquashed(0) {} bool operator==(const PredictorHistory &entry) const { @@ -234,7 +241,7 @@ class BPredUnit : public SimObject /** Whether or not the RAS was used. */ bool usedRAS; - /* Wether or not the RAS was pushed */ + /* Whether or not the RAS was pushed */ bool pushedRAS; /** Whether or not the instruction was a call. */ @@ -242,6 +249,9 @@ class BPredUnit : public SimObject /** Whether or not the instruction was a return. */ bool wasReturn; + + /** Whether this instruction has already mispredicted/updated bp */ + bool wasSquashed; }; typedef std::deque History; diff --git a/src/cpu/pred/bpred_unit_impl.hh b/src/cpu/pred/bpred_unit_impl.hh index 18e221775..eaffb7ea1 100644 --- a/src/cpu/pred/bpred_unit_impl.hh +++ b/src/cpu/pred/bpred_unit_impl.hh @@ -372,8 +372,12 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) while (!predHist[tid].empty() && predHist[tid].back().seqNum <= done_sn) { // Update the branch predictor with the correct results. - update(predHist[tid].back().pc, predHist[tid].back().predTaken, - predHist[tid].back().bpHistory, false); + if (!predHist[tid].back().wasSquashed) { + update(predHist[tid].back().pc, predHist[tid].back().predTaken, + predHist[tid].back().bpHistory, false); + } else { + retireSquashed(predHist[tid].back().bpHistory); + } predHist[tid].pop_back(); } @@ -465,12 +469,15 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, update((*hist_it).pc, actually_taken, pred_hist.front().bpHistory, true); + hist_it->wasSquashed = true; + if (actually_taken) { if (hist_it->wasReturn && !hist_it->usedRAS) { DPRINTF(Branch, "[tid: %i] Incorrectly predicted" " return [sn:%i] PC: %s\n", tid, hist_it->seqNum, hist_it->pc); RAS[tid].pop(); + hist_it->usedRAS = true; } DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]" @@ -488,23 +495,16 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, " to: %i, target: %s.\n", tid, hist_it->RASIndex, hist_it->RASTarget); RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget); - + hist_it->usedRAS = false; } else if (hist_it->wasCall && hist_it->pushedRAS) { //Was a Call but predicated false. Pop RAS here DPRINTF(Branch, "[tid: %i] Incorrectly predicted" " Call [sn:%i] PC: %s Popping RAS\n", tid, hist_it->seqNum, hist_it->pc); RAS[tid].pop(); + hist_it->pushedRAS = false; } } - DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i]" - " PC %s Actually Taken: %i\n", tid, hist_it->seqNum, - hist_it->pc, actually_taken); - - pred_hist.erase(hist_it); - - DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n", tid, - predHist[tid].size()); } else { DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't " "update.\n", tid, squashed_sn); diff --git a/src/cpu/pred/tournament.cc b/src/cpu/pred/tournament.cc index e471d08f5..c6514b6ad 100644 --- a/src/cpu/pred/tournament.cc +++ b/src/cpu/pred/tournament.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011, 2014 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -346,10 +346,10 @@ TournamentBP::update(Addr branch_addr, bool taken, void *bp_history, } } + } else { + // We're done with this history, now delete it. + delete history; } - // We're done with this history, now delete it. - delete history; - } assert(local_history_idx < localHistoryTableSize); @@ -357,6 +357,13 @@ TournamentBP::update(Addr branch_addr, bool taken, void *bp_history, } +void +TournamentBP::retireSquashed(void *bp_history) +{ + BPHistory *history = static_cast(bp_history); + delete history; +} + void TournamentBP::squash(void *bp_history) { diff --git a/src/cpu/pred/tournament.hh b/src/cpu/pred/tournament.hh index 39fff5bfb..88334a8c0 100644 --- a/src/cpu/pred/tournament.hh +++ b/src/cpu/pred/tournament.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011, 2014 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -104,6 +104,8 @@ class TournamentBP : public BPredUnit */ void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); + void retireSquashed(void *bp_history); + /** * Restores the global branch history on a squash. * @param bp_history Pointer to the BPHistory object that has the