Skip to content

Commit abf85ff

Browse files
authored
cpu-o3: fix path target resolution and add regression tests (#814)
- Refactor FullBTBPrediction to share taken-target resolution between getTarget() and getPHistInfo() - keeping path history consistent with the final predicted target for indirect and return branches - Add TAGE and MGSC tests for indirect and return target overrides in path-history updates. Change-Id: I7c111611d19a759b34199c9aa6ab823325ac7578
1 parent 7a9783c commit abf85ff

File tree

3 files changed

+125
-39
lines changed

3 files changed

+125
-39
lines changed

src/cpu/pred/btb/common.hh

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -516,24 +516,29 @@ struct FullBTBPrediction
516516
return (bbStart + predictWidth) & ~mask(floorLog2(predictWidth) - 1);
517517
}
518518

519+
Addr getEntryTarget(const BTBEntry &entry) {
520+
Addr target = entry.target;
521+
// indirect target should come from ipred or ras,
522+
// or btb itself when ipred miss
523+
if (entry.isIndirect) {
524+
if (!entry.isReturn) { // normal indirect, see ittage
525+
auto& pc = entry.pc;
526+
auto it = IndirectTakens_find(indirectTargets, pc);
527+
if (it != indirectTargets.end()) { // found in ittage, use it
528+
target = it->second;
529+
}
530+
} else { // indirect return, use RAS target
531+
target = returnTarget;
532+
}
533+
} // else: normal taken, use btb target
534+
return target;
535+
}
536+
519537
Addr getTarget(Addr predictWidth) {
520538
Addr target;
521539
const auto &entry = getTakenEntry();
522540
if (entry.valid) { // found a taken entry
523-
target = entry.target;
524-
// indirect target should come from ipred or ras,
525-
// or btb itself when ipred miss
526-
if (entry.isIndirect) {
527-
if (!entry.isReturn) { // normal indirect, see ittage
528-
auto& pc = entry.pc;
529-
auto it = IndirectTakens_find(indirectTargets, pc);
530-
if (it != indirectTargets.end()) { // found in ittage, use it
531-
target = it->second;
532-
}
533-
} else { // indirect return, use RAS target
534-
target = returnTarget;
535-
}
536-
} // else: normal taken, use btb target
541+
target = getEntryTarget(entry);
537542
} else {
538543
target = getFallThrough(predictWidth);
539544
}
@@ -631,32 +636,11 @@ struct FullBTBPrediction
631636

632637
std::tuple<Addr, Addr, bool> getPHistInfo() //path
633638
{
634-
bool taken = false;
635-
Addr pc = 0;
636-
Addr target = 0;
637-
for (auto &entry : btbEntries) {
638-
if (entry.valid) {
639-
if (entry.isCond) {
640-
auto& _pc = entry.pc;
641-
auto it = CondTakens_find(condTakens, _pc);
642-
if (it != condTakens.end()) {
643-
if (it->second) {
644-
taken = true;
645-
pc = entry.pc; // get the pc of the cond branch
646-
target = entry.target;
647-
break;
648-
}
649-
}
650-
} else {
651-
// uncond
652-
taken = true;
653-
pc = entry.pc; // get the pc of the cond branch
654-
target = entry.target;
655-
break;
656-
}
657-
}
639+
const auto &entry = getTakenEntry();
640+
if (entry.valid) {
641+
return std::make_tuple(entry.pc, getEntryTarget(entry), true);
658642
}
659-
return std::make_tuple(pc, target, taken);
643+
return std::make_tuple(0, 0, false);
660644
}
661645

662646
};

src/cpu/pred/btb/test/btb_mgsc.test.cc

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,55 @@ TEST(BTBMGSCTest, PTableLearnsOutcomeFromPreviousTakenBranchTarget)
846846
EXPECT_GE(acc, 0.80) << "Accuracy too low for PTable path-target learning: " << acc;
847847
}
848848

849+
TEST(BTBMGSCTest, SpecUpdatePHistUsesIndirectTargetOverride)
850+
{
851+
MgscHarness h;
852+
853+
BTBEntry entry = makeCondBTBEntry(0x1000);
854+
entry.isIndirect = true;
855+
entry.target = 0x2000;
856+
const Addr indirectTarget = 0x3000;
857+
858+
ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, indirectTarget));
859+
860+
FullBTBPrediction pred;
861+
pred.btbEntries = {entry};
862+
pred.condTakens.push_back({entry.pc, true});
863+
pred.indirectTargets.push_back({entry.pc, indirectTarget});
864+
865+
boost::dynamic_bitset<> expected_phr = h.phr;
866+
pHistShiftIn(2, true, expected_phr, entry.pc, indirectTarget);
867+
868+
h.mgsc.specUpdatePHist(h.phr, pred);
869+
h.mgsc.checkFoldedHist(h.ghr, expected_phr, h.lhr,
870+
"indirect target override");
871+
}
872+
873+
TEST(BTBMGSCTest, SpecUpdatePHistUsesReturnTargetOverride)
874+
{
875+
MgscHarness h;
876+
877+
BTBEntry entry = makeCondBTBEntry(0x1000);
878+
entry.isIndirect = true;
879+
entry.isReturn = true;
880+
entry.target = 0x2000;
881+
const Addr returnTarget = 0x3400;
882+
883+
ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, returnTarget));
884+
885+
FullBTBPrediction pred;
886+
pred.btbEntries = {entry};
887+
pred.condTakens.push_back({entry.pc, true});
888+
pred.returnTarget = returnTarget;
889+
890+
boost::dynamic_bitset<> expected_phr = h.phr;
891+
pHistShiftIn(2, true, expected_phr, entry.pc, returnTarget);
892+
893+
h.mgsc.specUpdatePHist(h.phr, pred);
894+
h.mgsc.checkFoldedHist(h.ghr, expected_phr, h.lhr,
895+
"return target override");
896+
}
897+
849898
} // namespace test
850899
} // namespace btb_pred
851900
} // namespace branch_prediction

src/cpu/pred/btb/test/btb_tage.test.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,59 @@ TEST_F(BTBTAGEUpperBoundPathHashTest, PredictionUsesPathHashHistorySnapshot) {
11021102
EXPECT_TRUE(predicted);
11031103
}
11041104

1105+
TEST_F(BTBTAGEUpperBoundPathHashTest, PredictionUsesIndirectOverridePathHashSnapshot) {
1106+
BTBEntry entry = createBTBEntry(0x1000, true, true, false, -1, 0x2000);
1107+
entry.isIndirect = true;
1108+
const Addr indirectTarget = 0x3000;
1109+
1110+
ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, indirectTarget));
1111+
1112+
boost::dynamic_bitset<> pathHistoryA(128, 0);
1113+
boost::dynamic_bitset<> pathHistoryB(128, 0);
1114+
applyPathHistoryTaken(pathHistoryB, entry.pc, indirectTarget);
1115+
1116+
ASSERT_TRUE(tage->insertExactEntry(2, entry.pc, pathHistoryB, 2));
1117+
1118+
FullBTBPrediction pred;
1119+
pred.btbEntries.push_back(entry);
1120+
pred.condTakens.push_back({entry.pc, true});
1121+
pred.indirectTargets.push_back({entry.pc, indirectTarget});
1122+
1123+
tage->specUpdatePHist(pathHistoryA, pred);
1124+
tage->checkFoldedHist(pathHistoryB, "indirect target override");
1125+
1126+
bool predicted = predictTAGE(tage, 0x1000, {entry}, outcomeHistory, stagePreds);
1127+
1128+
EXPECT_TRUE(predicted);
1129+
}
1130+
1131+
TEST_F(BTBTAGEUpperBoundPathHashTest, PredictionUsesReturnOverridePathHashSnapshot) {
1132+
BTBEntry entry = createBTBEntry(0x1000, true, true, false, -1, 0x2000);
1133+
entry.isIndirect = true;
1134+
entry.isReturn = true;
1135+
const Addr returnTarget = 0x3400;
1136+
1137+
ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, returnTarget));
1138+
1139+
boost::dynamic_bitset<> pathHistoryA(128, 0);
1140+
boost::dynamic_bitset<> pathHistoryB(128, 0);
1141+
applyPathHistoryTaken(pathHistoryB, entry.pc, returnTarget);
1142+
1143+
ASSERT_TRUE(tage->insertExactEntry(2, entry.pc, pathHistoryB, 2));
1144+
1145+
FullBTBPrediction pred;
1146+
pred.btbEntries.push_back(entry);
1147+
pred.condTakens.push_back({entry.pc, true});
1148+
pred.returnTarget = returnTarget;
1149+
1150+
tage->specUpdatePHist(pathHistoryA, pred);
1151+
tage->checkFoldedHist(pathHistoryB, "return target override");
1152+
1153+
bool predicted = predictTAGE(tage, 0x1000, {entry}, outcomeHistory, stagePreds);
1154+
1155+
EXPECT_TRUE(predicted);
1156+
}
1157+
11051158

11061159
} // namespace test
11071160

0 commit comments

Comments
 (0)