> Likely, P550 doesn’t have another BTB level. If a branch misses the 32 entry BTB, the core simply calculates the branch’s destination address when it arrives at the frontend
That seems unwise. Might work well enough for direct branches, but it's going to preform very badly on indirect branches. I would love to see some tests for indirect branch performance (static and dynamic) in your suite.
> When return stack capacity is exceeded, P550 sees a sharp spike in latency. That contrasts with A75’s more gentle increase in latency.
That might be a direct consequence of the P550's limited BTB. Even when the return stack overflows, the A75 can probably still predict the return as if it was an indirect branch, utilising its massive 3072 entry L1 BTB.
Actually, are you sure the P550 even has a return stack? 16 correctly predicted call/ret pairs just so happens to be what you would get from a 32 entry BTB predicting 16 calls then 16 returns.
(author here) Just a 32 entry BTB is technically a possibility from microbenchmark results, but the EIC7700X datasheet straight up says:
"a branch prediction unit that is composed of a 32-entry Branch Target Buffer (BTB), a 9.1 KiB-entry Branch History Table (BHT), a 16-entry Return Address Stack (RAS), 512-entry Indirect Jump Target Predictor (IJTP), and a 16-entry Return Instruction Predictor"
You need to predict the target (with BTB) if want zero-bubble calls (1 cycle latency).
Otherwise it takes 3 cycles (on the P550) to take a direct call. Doesn't matter that it's unconditional, it can't see the call until after decoding. Sure, it's only two extra cycles, but that's a full six instructions on this small 3-wide core.
And an indirect call? Even if the target is known, it's going to need to fetch it from the register file, which requires going through rename. And unless you put a fast-path in with an extra register-file read-port, you need to go through dispatch and the scheduler too. Probably takes 6-10 cycles to take an indirect branch without a BTB.
On bigger designs it's even more essential to predict unconditional branches, as their instruction caches take multiple cycles, and then there are quite substantial queues between fetch and decode, and between predict and fetch.
Modern machines usually try to predict target addresses, not just the direction of conditional branches. You can implement it for unconditional calls and jumps too, even for direct/relative-addressed ones. That's pretty common nowadays.
When you calculate the target of a jump, you can cache it (that's what a BTB is). Next time you encounter it, you predict the target by accessing the cached value in the BTB and start fetching early instead of waiting for your jump/call to move all the way through the machine.
That seems unwise. Might work well enough for direct branches, but it's going to preform very badly on indirect branches. I would love to see some tests for indirect branch performance (static and dynamic) in your suite.
> When return stack capacity is exceeded, P550 sees a sharp spike in latency. That contrasts with A75’s more gentle increase in latency.
That might be a direct consequence of the P550's limited BTB. Even when the return stack overflows, the A75 can probably still predict the return as if it was an indirect branch, utilising its massive 3072 entry L1 BTB.
Actually, are you sure the P550 even has a return stack? 16 correctly predicted call/ret pairs just so happens to be what you would get from a 32 entry BTB predicting 16 calls then 16 returns.