From 844db363911065a3b5f0c5e4601f89ee1d7360c5 Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Sat, 23 Jul 2022 16:00:43 +0900 Subject: [PATCH] RISC-V: Cache instruction support Calling riscv_subset_supports repeatedly harms the performance in a measurable way (about 3-13% in total on the most cases). As a simple solution, this commit now caches instruction class support (whether specific instruction class is supported) as a signed char array. It is expected to have 5-7% performance improvements when disassembling linked RISC-V ELF programs using objdump but this is particularly effective with programs with many CSR instructions (up to ~42% on the author's PC). include/ChangeLog: * opcode/riscv.h (enum riscv_insn_class): Add NUM_INSN_CLASSES. opcodes/ChangeLog: * riscv-dis.c (riscv_insn_support_cache) New. (init_riscv_dis_state_for_arch): Clear the instruction support cache. (riscv_disassemble_insn): Cache the instruction support. --- include/opcode/riscv.h | 2 ++ opcodes/riscv-dis.c | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index c3cbde600cb..6a029a1034e 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -422,6 +422,8 @@ enum riscv_insn_class INSN_CLASS_XTHEADMEMIDX, INSN_CLASS_XTHEADMEMPAIR, INSN_CLASS_XTHEADSYNC, + + NUM_INSN_CLASSES, }; /* This structure holds information for a particular instruction. */ diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 197f6a31d43..32e7b117443 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -107,6 +107,9 @@ static bool no_aliases = false; /* If set, disassemble with numeric register names. */ static bool is_numeric = false; + +/* Instruction support cache. */ +static signed char riscv_insn_support_cache[NUM_INSN_CLASSES]; /* Set current disassembler context (dis_arch_context_current). @@ -200,6 +203,9 @@ static void init_riscv_dis_state_for_arch (void) { is_arch_changed = true; + /* Clear instruction support cache. */ + for (size_t i = 0; i < NUM_INSN_CLASSES; i++) + riscv_insn_support_cache[i] = 0; } /* Initialization (for arch and options). */ @@ -955,7 +961,14 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info) if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen)) continue; /* Is this instruction supported by the current architecture? */ - if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class)) + if (riscv_insn_support_cache[op->insn_class] == 0) + { + riscv_insn_support_cache[op->insn_class] + = riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class) + ? +1 + : -1; + } + if (riscv_insn_support_cache[op->insn_class] < 0) continue; matched_op = op;