From f82f13391a8da4b5aec40b271d4e7f1b16e6d3a7 Mon Sep 17 00:00:00 2001 From: Yiwei Lin Date: Wed, 22 Nov 2023 21:37:52 +0800 Subject: [PATCH] Improve efficiency of branch history table The previous implementation of the branch history table had some limitations that prevented us from fully leveraging its capabilities. This commit aims to improve access to recent history entries and make it more cache-friendly. --- src/decode.h | 10 +++++----- src/emulate.c | 3 +-- src/rv32_template.c | 15 +++++++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/decode.h b/src/decode.h index 159e36e2..2d552730 100644 --- a/src/decode.h +++ b/src/decode.h @@ -254,9 +254,10 @@ typedef struct { #define HISTORY_SIZE 16 typedef struct { - uint32_t PC; - struct rv_insn *branch_target; -} branch_history_entry_t; + uint8_t idx; + uint32_t PC[HISTORY_SIZE]; + struct rv_insn *target[HISTORY_SIZE]; +} branch_history_table_t; typedef struct rv_insn { union { @@ -300,8 +301,7 @@ typedef struct rv_insn { * specific IR array without the need for additional copying. */ struct rv_insn *branch_taken, *branch_untaken; - uint8_t branch_table_count; - branch_history_entry_t *branch_table; + branch_history_table_t *branch_table; } rv_insn_t; /* decode the RISC-V instruction */ diff --git a/src/emulate.c b/src/emulate.c index 197b88c3..c8d790c5 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -639,8 +639,7 @@ static void block_translate(riscv_t *rv, block_t *block) || ir->opcode == rv_insn_cjalr || ir->opcode == rv_insn_cjr #endif ) - ir->branch_table = - calloc(1, HISTORY_SIZE * sizeof(branch_history_entry_t)); + ir->branch_table = calloc(1, sizeof(branch_history_table_t)); break; } diff --git a/src/rv32_template.c b/src/rv32_template.c index 8d08f044..4c5c5472 100644 --- a/src/rv32_template.c +++ b/src/rv32_template.c @@ -49,19 +49,18 @@ RVOP(jal, { */ #define LOOKUP_OR_UPDATE_BRANCH_HISTORY_TABLE() \ /* lookup branch history table */ \ - for (int i = 0; i < ir->branch_table_count; i++) { \ - if (ir->branch_table[i].PC == PC) { \ - MUST_TAIL return ir->branch_table[i].branch_target->impl( \ - rv, ir->branch_table[i].branch_target, cycle, PC); \ + for (int i = 0; i < HISTORY_SIZE; i++) { \ + if (ir->branch_table->PC[i] == PC) { \ + MUST_TAIL return ir->branch_table->target[i]->impl( \ + rv, ir->branch_table->target[i], cycle, PC); \ } \ } \ block_t *block = block_find(&rv->block_map, PC); \ if (block) { \ /* update branch history table */ \ - ir->branch_table_count = (ir->branch_table_count + 1) % HISTORY_SIZE; \ - ir->branch_table[ir->branch_table_count].PC = PC; \ - ir->branch_table[ir->branch_table_count].branch_target = \ - block->ir_head; \ + ir->branch_table->PC[ir->branch_table->idx] = PC; \ + ir->branch_table->target[ir->branch_table->idx] = block->ir_head; \ + ir->branch_table->idx = (ir->branch_table->idx + 1) % HISTORY_SIZE; \ MUST_TAIL return block->ir_head->impl(rv, block->ir_head, cycle, PC); \ }