From 03691023a58cad109be148ab6cb76d565291f5af 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 branch history table implementation have some defects which can't get maximum benefits from it. In this commit, we consider to access every history entries in the recent times and make good use of the cache property. --- 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); \ }