BP: Fix several Branch Predictor issues.
authorMrinmoy Ghosh <mrinmoy.ghosh@arm.com>
Mon, 13 Feb 2012 18:26:24 +0000 (12:26 -0600)
committerMrinmoy Ghosh <mrinmoy.ghosh@arm.com>
Mon, 13 Feb 2012 18:26:24 +0000 (12:26 -0600)
1. Updates the Branch Predictor correctly to the state
   just after a mispredicted branch, if a squash occurs.
2. If a BTB does not find an entry, the branch is predicted not taken.
   The global history is modified to correctly reflect this prediction.
3. Local history is now updated at the fetch stage instead of
   execute stage.
4. In the Update stage of the branch predictor the local predictors are
   now correctly updated according to the state of local history during
   fetch stage.

This patch also improves performance by as much as 17% on some benchmarks

src/cpu/inorder/resources/bpred_unit.cc
src/cpu/inorder/resources/bpred_unit.hh
src/cpu/o3/bpred_unit.hh
src/cpu/o3/bpred_unit_impl.hh
src/cpu/o3/commit_impl.hh
src/cpu/o3/decode_impl.hh
src/cpu/pred/2bit_local.cc
src/cpu/pred/2bit_local.hh
src/cpu/pred/tournament.cc
src/cpu/pred/tournament.hh

index 778366532f9359d89ca9e6750ece159b313bf155..1a458e1d6f192d2f3bc2500cf6c898498cd5669f 100644 (file)
@@ -284,7 +284,8 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
         // Update the branch predictor with the correct results.
         BPUpdate(predHist[tid].back().pc.instAddr(),
                  predHist[tid].back().predTaken,
-                 predHist[tid].back().bpHistory);
+                 predHist[tid].back().bpHistory,
+                 false);
 
         predHist[tid].pop_back();
     }
@@ -367,7 +368,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
         }
 
         BPUpdate((*hist_it).pc.instAddr(), actually_taken,
-                 pred_hist.front().bpHistory);
+                 pred_hist.front().bpHistory, true);
 
         // only update BTB on branch taken right???
         if (actually_taken)
@@ -425,12 +426,12 @@ BPredUnit::BPLookup(Addr inst_PC, void * &bp_history)
 
 
 void
-BPredUnit::BPUpdate(Addr inst_PC, bool taken, void *bp_history)
+BPredUnit::BPUpdate(Addr inst_PC, bool taken, void *bp_history, bool squashed)
 {
     if (predictor == Local) {
         localBP->update(inst_PC, taken, bp_history);
     } else if (predictor == Tournament) {
-        tournamentBP->update(inst_PC, taken, bp_history);
+        tournamentBP->update(inst_PC, taken, bp_history, squashed);
     } else {
         panic("Predictor type is unexpected value!");
     }
index 33ca4a0c695bc857346e894bcbd2878fb8791d00..b5d12d2dbb230545d9c7bf6e7cfde502eaa9fc9c 100644 (file)
@@ -160,9 +160,10 @@ class BPredUnit
      * @param taken Whether the branch was taken or not taken.
      * @param bp_history Pointer to the branch predictor state that is
      * associated with the branch lookup that is being updated.
+     * @param squashed if the branch in question was squashed or not
      * @todo Make this update flexible enough to handle a global predictor.
      */
-    void BPUpdate(Addr instPC, bool taken, void *bp_history);
+    void BPUpdate(Addr instPC, bool taken, void *bp_history, bool squashed);
 
     /**
      * Updates the BTB with the target of a branch.
index 8dbba9085b29d0447a7e2a684202fae4e43cf0a7..d3ae93b386eceb604d05c94616e8a5e14cd711f8 100644 (file)
@@ -137,6 +137,16 @@ class BPredUnit
      */
     bool BPLookup(Addr instPC, void * &bp_history);
 
+     /**
+     * If a branch is not taken, because the BTB address is invalid or missing,
+     * this function sets the appropriate counter in the global and local
+     * predictors to not taken.
+     * @param inst_PC The PC to look up the local predictor.
+     * @param bp_history Pointer that will be set to an object that
+     * has the branch predictor state associated with the lookup.
+     */
+    void BPBTBUpdate(Addr instPC, void * &bp_history);
+
     /**
      * Looks up a given PC in the BTB to see if a matching entry exists.
      * @param inst_PC The PC to look up.
@@ -159,9 +169,11 @@ class BPredUnit
      * @param taken Whether the branch was taken or not taken.
      * @param bp_history Pointer to the branch predictor state that is
      * associated with the branch lookup that is being updated.
+     * @param squashed Set to true when this function is called during a
+     * squash operation.
      * @todo Make this update flexible enough to handle a global predictor.
      */
-    void BPUpdate(Addr instPC, bool taken, void *bp_history);
+    void BPUpdate(Addr instPC, bool taken, void *bp_history, bool squashed);
 
     /**
      * Updates the BTB with the target of a branch.
index e0292e2322dfe52b93fe568c5b0cf4f5dc9eade1..8502f342c46dd1b5ef91aa03a2af3bc2709c98c6 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -166,12 +178,11 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid)
         BPUncond(bp_history);
     } else {
         ++condPredicted;
-
         pred_taken = BPLookup(pc.instAddr(), bp_history);
 
-        DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i "
-                "for PC %s\n",
-                tid, pred_taken, inst->pcState());
+        DPRINTF(Fetch, "BranchPred:[tid:%i]: [sn:%i] Branch predictor"
+                " predicted %i for PC %s\n",
+                tid, inst->seqNum,  pred_taken, inst->pcState());
     }
 
     DPRINTF(Fetch, "BranchPred: [tid:%i]: [sn:%i] Creating prediction history "
@@ -231,6 +242,15 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid)
                 DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a "
                         "valid entry.\n",tid);
                 pred_taken = false;
+                // The Direction of the branch predictor is altered because the
+                // BTB did not have an entry
+                // The predictor needs to be updated accordingly
+                if (!inst->isCall() && !inst->isReturn()) {
+                      BPBTBUpdate(pc.instAddr(), bp_history);
+                      DPRINTF(Fetch, "BranchPred: [tid:%i]:[sn:%i] BPBTBUpdate"
+                              " called for %s\n",
+                              tid, inst->seqNum, inst->pcState());
+                }
                 TheISA::advancePC(target, inst->staticInst);
             }
 
@@ -261,7 +281,7 @@ BPredUnit<Impl>::update(const InstSeqNum &done_sn, ThreadID tid)
         // Update the branch predictor with the correct results.
         BPUpdate(predHist[tid].back().pc,
                  predHist[tid].back().predTaken,
-                 predHist[tid].back().bpHistory);
+                 predHist[tid].back().bpHistory, false);
 
         predHist[tid].pop_back();
     }
@@ -356,12 +376,15 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
         }
 
         BPUpdate((*hist_it).pc, actually_taken,
-                 pred_hist.front().bpHistory);
-
-        BTB.update((*hist_it).pc, corrTarget, tid);
-
-        DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] "
-                "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc);
+                 pred_hist.front().bpHistory, true);
+        if (actually_taken){
+            DPRINTF(Fetch,"BranchPred: [tid: %i] BTB Update called for [sn:%i]"
+                           " PC: %s\n", tid,(*hist_it).seqNum, (*hist_it).pc);
+            BTB.update((*hist_it).pc, corrTarget, tid);
+        }
+        DPRINTF(Fetch, "BranchPred: [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);
 
@@ -407,12 +430,26 @@ BPredUnit<Impl>::BPLookup(Addr instPC, void * &bp_history)
 
 template <class Impl>
 void
-BPredUnit<Impl>::BPUpdate(Addr instPC, bool taken, void *bp_history)
+BPredUnit<Impl>::BPBTBUpdate(Addr instPC, void * &bp_history)
+{
+    if (predictor == Local) {
+        return localBP->BTBUpdate(instPC, bp_history);
+    } else if (predictor == Tournament) {
+        return tournamentBP->BTBUpdate(instPC, bp_history);
+    } else {
+        panic("Predictor type is unexpected value!");
+    }
+}
+
+template <class Impl>
+void
+BPredUnit<Impl>::BPUpdate(Addr instPC, bool taken, void *bp_history,
+                 bool squashed)
 {
     if (predictor == Local) {
         localBP->update(instPC, taken, bp_history);
     } else if (predictor == Tournament) {
-        tournamentBP->update(instPC, taken, bp_history);
+        tournamentBP->update(instPC, taken, bp_history, squashed);
     } else {
         panic("Predictor type is unexpected value!");
     }
index 7ca42ae5bef754bcb9c66a68831f40f9f87088b9..b4cc4b0173b4dec75abf53eec20811a53496da6c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -868,6 +868,11 @@ DefaultCommit<Impl>::commit()
                 fromIEW->branchTaken[tid];
             toIEW->commitInfo[tid].squashInst =
                                     rob->findInst(tid, squashed_inst);
+            if (toIEW->commitInfo[tid].mispredictInst) {
+                if (toIEW->commitInfo[tid].mispredictInst->isUncondCtrl()) {
+                     toIEW->commitInfo[tid].branchTaken = true;
+                }
+            }
 
             toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
 
index 60bca1041bdfaf77832b9d4ee2ec7c00e37f65b7..22b89f4a89a4dd844cc1a60de3035ddf0e65d628 100644 (file)
@@ -278,11 +278,15 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid)
     // Send back mispredict information.
     toFetch->decodeInfo[tid].branchMispredict = true;
     toFetch->decodeInfo[tid].predIncorrect = true;
+    toFetch->decodeInfo[tid].mispredictInst = inst;
     toFetch->decodeInfo[tid].squash = true;
     toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
     toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
     toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
     toFetch->decodeInfo[tid].squashInst = inst;
+    if (toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) {
+            toFetch->decodeInfo[tid].branchTaken = true;
+    }
 
     InstSeqNum squash_seq_num = inst->seqNum;
 
index dc8cf50b770fc2d8703363b0beab3b8190fb0a18..4d18c419bfda24f492d1a49c47cd083460420a8d 100644 (file)
@@ -79,6 +79,14 @@ LocalBP::reset()
     }
 }
 
+void
+LocalBP::BTBUpdate(Addr &branch_addr, void * &bp_history)
+{
+// Place holder for a function that is called to update predictor history when
+// a BTB entry is invalid or not found.
+}
+
+
 bool
 LocalBP::lookup(Addr &branch_addr, void * &bp_history)
 {
index 8b7bb8463d1c2d1820d836c8264febc3bea0a40c..01a0b64db7089c604156efa4fc35120f6bb1a7da 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -64,6 +76,15 @@ class LocalBP
      */
     bool lookup(Addr &branch_addr, void * &bp_history);
 
+    /**
+     * Updates the branch predictor to Not Taken if a BTB entry is
+     * invalid or not found.
+     * @param branch_addr The address of the branch to look up.
+     * @param bp_history Pointer to any bp history state.
+     * @return Whether or not the branch is taken.
+     */
+    void BTBUpdate(Addr &branch_addr, void * &bp_history);
+
     /**
      * Updates the branch predictor with the actual result of a branch.
      * @param branch_addr The address of the branch to update.
index 9608dc01155357757489e0f8408ac4139ee3bb24..3adafb608f96bbe725e989371937843141ab975a 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -146,6 +158,18 @@ TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx)
         (localHistoryTable[local_history_idx] << 1);
 }
 
+
+void
+TournamentBP::BTBUpdate(Addr &branch_addr, void * &bp_history)
+{
+    unsigned local_history_idx = calcLocHistIdx(branch_addr);
+    //Update Global History to Not Taken
+    globalHistory = globalHistory & (globalHistoryMask - 1);
+    //Update Local History to Not Taken
+    localHistoryTable[local_history_idx] =
+       localHistoryTable[local_history_idx] & (localPredictorMask - 1);
+}
+
 bool
 TournamentBP::lookup(Addr &branch_addr, void * &bp_history)
 {
@@ -174,6 +198,7 @@ TournamentBP::lookup(Addr &branch_addr, void * &bp_history)
     history->localPredTaken = local_prediction;
     history->globalPredTaken = global_prediction;
     history->globalUsed = choice_prediction;
+    history->localHistory = local_predictor_idx;
     bp_history = (void *)history;
 
     assert(globalHistory < globalPredictorSize &&
@@ -184,30 +209,22 @@ TournamentBP::lookup(Addr &branch_addr, void * &bp_history)
     // all histories.
     if (choice_prediction) {
         if (global_prediction) {
-//            updateHistoriesTaken(local_history_idx);
-//            globalCtrs[globalHistory].increment();
-//            localCtrs[local_history_idx].increment();
             updateGlobalHistTaken();
+            updateLocalHistTaken(local_history_idx);
             return true;
         } else {
-//            updateHistoriesNotTaken(local_history_idx);
-//            globalCtrs[globalHistory].decrement();
-//            localCtrs[local_history_idx].decrement();
             updateGlobalHistNotTaken();
+            updateLocalHistNotTaken(local_history_idx);
             return false;
         }
     } else {
         if (local_prediction) {
-//            updateHistoriesTaken(local_history_idx);
-//            globalCtrs[globalHistory].increment();
-//            localCtrs[local_history_idx].increment();
             updateGlobalHistTaken();
+            updateLocalHistTaken(local_history_idx);
             return true;
         } else {
-//            updateHistoriesNotTaken(local_history_idx);
-//            globalCtrs[globalHistory].decrement();
-//            localCtrs[local_history_idx].decrement();
             updateGlobalHistNotTaken();
+            updateLocalHistNotTaken(local_history_idx);
             return false;
         }
     }
@@ -222,16 +239,18 @@ TournamentBP::uncondBr(void * &bp_history)
     history->localPredTaken = true;
     history->globalPredTaken = true;
     history->globalUsed = true;
+    history->localHistory = invalidPredictorIndex;
     bp_history = static_cast<void *>(history);
 
     updateGlobalHistTaken();
 }
 
 void
-TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history)
+TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history,
+                     bool squashed)
 {
     unsigned local_history_idx;
-    unsigned local_predictor_idx;
+    unsigned local_predictor_idx M5_VAR_USED;
     unsigned local_predictor_hist;
 
     // Get the local predictor's current prediction
@@ -259,33 +278,34 @@ TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history)
         // resolution of the branch.  Global history is updated
         // speculatively and restored upon squash() calls, so it does not
         // need to be updated.
+        unsigned old_local_pred_index = history->localHistory
+                 & localPredictorMask;
         if (taken) {
-               localCtrs[local_predictor_idx].increment();
                globalCtrs[history->globalHistory].increment();
-
-               updateLocalHistTaken(local_history_idx);
+               if (old_local_pred_index != invalidPredictorIndex) {
+                      localCtrs[old_local_pred_index].increment();
+               }
         } else {
-               localCtrs[local_predictor_idx].decrement();
                globalCtrs[history->globalHistory].decrement();
-
-               updateLocalHistNotTaken(local_history_idx);
+               if (old_local_pred_index != invalidPredictorIndex) {
+                      localCtrs[old_local_pred_index].decrement();
+               }
        }
 
-       bool mispredict = false;
-
-       //global predictor used and mispredicted
-       if (history->globalUsed && history->globalPredTaken != taken)
-           mispredict = true;
-       //local predictor used and mispredicted
-       else if (!history->globalUsed && history->localPredTaken != taken)
-           mispredict = true;
-
-       if (mispredict) {
+       if (squashed) {
            if (taken) {
-              globalHistory = globalHistory | 1;
+              globalHistory = (history->globalHistory << 1) | 1;
+              globalHistory = globalHistory & globalHistoryMask;
+              if (history->localHistory != invalidPredictorIndex)
+                  localHistoryTable[local_history_idx] =
+                     (history->localHistory << 1) | 1;
            } else {
-              unsigned mask = globalHistoryMask - 1;
-              globalHistory = globalHistory & mask;
+              globalHistory = (history->globalHistory << 1);
+              globalHistory = globalHistory & globalHistoryMask;
+              if (history->localHistory != invalidPredictorIndex) {
+                  localHistoryTable[local_history_idx] =
+                     history->localHistory << 1;
+              }
            }
 
         }
index 96bd43ed6b985960794fa2848003e326d06f9a99..f9df2a61d6c2eb2f797786f09b5c287154343505 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -79,15 +91,24 @@ class TournamentBP
      * @param bp_history Pointer that will be set to the BPHistory object.
      */
     void uncondBr(void * &bp_history);
-
+    /**
+     * Updates the branch predictor to Not Taken if a BTB entry is
+     * invalid or not found.
+     * @param branch_addr The address of the branch to look up.
+     * @param bp_history Pointer to any bp history state.
+     * @return Whether or not the branch is taken.
+     */
+    void BTBUpdate(Addr &branch_addr, void * &bp_history);
     /**
      * Updates the branch predictor with the actual result of a branch.
      * @param branch_addr The address of the branch to update.
      * @param taken Whether or not the branch was taken.
      * @param bp_history Pointer to the BPHistory object that was created
      * when the branch was predicted.
+     * @param squashed is set when this function is called during a squash
+     * operation.
      */
-    void update(Addr &branch_addr, bool taken, void *bp_history);
+    void update(Addr &branch_addr, bool taken, void *bp_history, bool squashed);
 
     /**
      * Restores the global branch history on a squash.
@@ -149,11 +170,14 @@ class TournamentBP
         static int newCount;
 #endif
         unsigned globalHistory;
+        unsigned localHistory;
         bool localPredTaken;
         bool globalPredTaken;
         bool globalUsed;
     };
 
+    /** Flag for invalid predictor index */
+    static const int invalidPredictorIndex = -1;
     /** Local counters. */
     std::vector<SatCounter> localCtrs;