-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support static analysis of registers #192
Conversation
I am hesitant to embrace the proposed changes due to the alteration in the instruction decoding structure. I require some numerical data to illustrate that the impact on overall performance is negligible. |
By the way, could you verify the percentage displayed in
Having |
Are there any integrated benchmarks can provide the numerical data? |
Check prebuilt CoreMark, Dhrystone, nqueens, SciMar2, and richards in |
Sorry, I forgot convert to percentage |
Decouple the percentage fix in another pull request since this pull request is blocked for the sake of further measurements. |
I have run 10 times of CoreMark and Dhrystone respectively and calculated their average. The performance lost is around 0.6% on CoreMark and 0.5% on Dhrystone. Before changes average:
After changes average:
|
Issue reproducer
IssueThe table number begin from 106 |
fixed it |
Consider the following changes: diff --git a/src/common.h b/src/common.h
index faa2f6d..5634734 100644
--- a/src/common.h
+++ b/src/common.h
@@ -67,6 +67,20 @@
/* run the 1st parameter */
#define IIF_1(t, ...) t
+/* Accept any number of args >= N, but expand to just the Nth one. The macro
+ * that calls the function still only supports 4 args, but the set of values
+ * that might need to be returned is 1 larger, so N is increased to 6.
+ */
+#define _GET_NTH_ARG(_1, _2, _3, _4, _5, N, ...) N
+
+/* Count how many args are in a variadic macro. The GCC/Clang extension is used
+ * to handle the case where ... expands to nothing. A placeholder arg is added
+ * before ##VA_ARGS (its value is irrelevant but necessary to preserve the
+ * shifting offset).
+ * Additionally, 0 is added as a valid value in the N position.
+ */
+#define COUNT_VARARGS(...) _GET_NTH_ARG("ignored", ##__VA_ARGS__, 4, 3, 2, 1, 0)
+
#if defined(__GNUC__) || defined(__clang__)
#define __HAVE_TYPEOF 1
#endif
diff --git a/src/decode.h b/src/decode.h
index c895166..070d3fb 100644
--- a/src/decode.h
+++ b/src/decode.h
@@ -10,12 +10,28 @@
#include "riscv.h"
+enum op_field {
+ F_rs1 = 1,
+ F_rs2 = 2,
+ F_rs3 = 4,
+ F_rd = 8,
+};
+
+#define ENC4(a, b, c, d, ...) F_##a | F_##b | F_##c | F_##d
+#define ENC3(a, b, c, ...) F_##a | F_##b | F_##c
+#define ENC2(a, b, ...) F_##a | F_##b
+#define ENC1(a, ...) F_##a
+
+#define ENCN(X, A) X##A
+#define ENC_GEN(X, A) ENCN(X, A)
+#define ENC(...) ENC_GEN(ENC, COUNT_VARARGS(__VA_ARGS__))(__VA_ARGS__)
+
/* RISC-V instruction list in format _(instruction-name, can-branch) */
/* clang-format off */
#define RISCV_INSN_LIST \
- _(nop, 0, 0x1|0x8) \
+ _(nop, 0, ENC(rs1, rd)) \
/* RV32I Base Instruction Set */ \
- _(lui, 0, 0x8) \
+ _(lui, 0, ENC(rd)) \
...
|
Nice macro manipulation! I added |
C macros can be powerful. I always learn from metalang99, which provides a solid foundation for writing reliable and maintainable metaprograms in pure C99." |
Thank @ChinYikMing for contributing! |
Introduce
reg_used_mask
inrv_insn_t
structure, so that we can know which registers are used during the static analysis of the instruction.Also, refactor the initialization of enumeration of registers with X-macro for reusing the macro in the tool