From b7ec323c2e42a9ff8df844e5a95665733abb4bc1 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 29 Nov 2021 00:03:20 +0200 Subject: [PATCH] drc: prefer callee-saved regs on alloc reduces amount of saved/restored regs (random game): arm32: ~45% arm64: ~80% --- libpcsxcore/new_dynarec/assem_arm.c | 6 ----- libpcsxcore/new_dynarec/assem_arm.h | 21 ++++++++++----- libpcsxcore/new_dynarec/assem_arm64.c | 3 --- libpcsxcore/new_dynarec/assem_arm64.h | 12 ++++++--- libpcsxcore/new_dynarec/new_dynarec.c | 39 ++++++++++++++++++++------- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/libpcsxcore/new_dynarec/assem_arm.c b/libpcsxcore/new_dynarec/assem_arm.c index 87490c61..23d3b7f7 100644 --- a/libpcsxcore/new_dynarec/assem_arm.c +++ b/libpcsxcore/new_dynarec/assem_arm.c @@ -27,12 +27,6 @@ #include "pcnt.h" #include "arm_features.h" -#ifndef __MACH__ -#define CALLER_SAVE_REGS 0x100f -#else -#define CALLER_SAVE_REGS 0x120f -#endif - #define unused __attribute__((unused)) #ifdef DRC_DBG diff --git a/libpcsxcore/new_dynarec/assem_arm.h b/libpcsxcore/new_dynarec/assem_arm.h index 9b3a1e10..75273aa8 100644 --- a/libpcsxcore/new_dynarec/assem_arm.h +++ b/libpcsxcore/new_dynarec/assem_arm.h @@ -1,8 +1,3 @@ -#define HOST_REGS 13 -#define HOST_CCREG 10 -#define HOST_BTREG 8 -#define EXCLUDE_REG 11 - #define HOST_IMM8 1 #define HAVE_CMOV_IMM 1 #define HAVE_CONDITIONAL_CALL 1 @@ -19,12 +14,24 @@ r14 = lr (link register) r15 = pc (program counter) */ +#define HOST_REGS 13 +#define HOST_CCREG 10 +#define HOST_BTREG 8 +#define EXCLUDE_REG 11 + +// Note: FP is set to &dynarec_local when executing generated code. +// Thus the local variables are actually global and not on the stack. #define FP 11 #define LR 14 #define HOST_TEMPREG 14 -// Note: FP is set to &dynarec_local when executing generated code. -// Thus the local variables are actually global and not on the stack. +#ifndef __MACH__ +#define CALLER_SAVE_REGS 0x100f +#else +#define CALLER_SAVE_REGS 0x120f +#endif +#define PREFERRED_REG_FIRST 4 +#define PREFERRED_REG_LAST 9 extern char *invc_ptr; diff --git a/libpcsxcore/new_dynarec/assem_arm64.c b/libpcsxcore/new_dynarec/assem_arm64.c index 431805d4..1c52c3e6 100644 --- a/libpcsxcore/new_dynarec/assem_arm64.c +++ b/libpcsxcore/new_dynarec/assem_arm64.c @@ -23,8 +23,6 @@ #include "pcnt.h" #include "arm_features.h" -#define CALLER_SAVE_REGS 0x0007ffff - #define unused __attribute__((unused)) void do_memhandler_pre(); @@ -1599,7 +1597,6 @@ static void do_writestub(int n) emit_jmp(stubs[n].retaddr); // return address (invcode check) set_jump_target(handler_jump, out); - // TODO FIXME: regalloc should prefer callee-saved regs if(!regs_saved) save_regs(reglist); void *handler=NULL; diff --git a/libpcsxcore/new_dynarec/assem_arm64.h b/libpcsxcore/new_dynarec/assem_arm64.h index 1aeee0b9..c5fcadf3 100644 --- a/libpcsxcore/new_dynarec/assem_arm64.h +++ b/libpcsxcore/new_dynarec/assem_arm64.h @@ -1,13 +1,13 @@ -#define HOST_REGS 29 -#define HOST_BTREG 27 -#define EXCLUDE_REG -1 - #define HOST_IMM8 1 /* calling convention: r0 -r17: caller-save r19-r29: callee-save */ +#define HOST_REGS 29 +#define HOST_BTREG 27 +#define EXCLUDE_REG -1 + #define SP 31 #define WZR SP #define XZR SP @@ -23,6 +23,10 @@ #define HOST_CCREG 28 #define rCC w28 +#define CALLER_SAVE_REGS 0x0007ffff +#define PREFERRED_REG_FIRST 19 +#define PREFERRED_REG_LAST 27 + // stack space #define SSP_CALLEE_REGS (8*12) #define SSP_CALLER_REGS (8*20) diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 921a2ed1..50410665 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -1364,9 +1364,11 @@ void clean_blocks(u_int page) static void alloc_reg(struct regstat *cur,int i,signed char reg) { int r,hr; - int preferred_reg = (reg&7); - if(reg==CCREG) preferred_reg=HOST_CCREG; - if(reg==PTEMP||reg==FTEMP) preferred_reg=12; + int preferred_reg = PREFERRED_REG_FIRST + + reg % (PREFERRED_REG_LAST - PREFERRED_REG_FIRST + 1); + if (reg == CCREG) preferred_reg = HOST_CCREG; + if (reg == PTEMP || reg == FTEMP) preferred_reg = 12; + assert(PREFERRED_REG_FIRST != EXCLUDE_REG && EXCLUDE_REG != HOST_REGS); // Don't allocate unused registers if((cur->u>>reg)&1) return; @@ -1410,28 +1412,47 @@ static void alloc_reg(struct regstat *cur,int i,signed char reg) if((cur->u>>r)&1) {cur->regmap[hr]=-1;break;} } } + // Try to allocate any available register, but prefer // registers that have not been used recently. - if(i>0) { - for(hr=0;hrregmap[hr]==-1) { - if(regs[i-1].regmap[hr]!=dops[i-1].rs1&®s[i-1].regmap[hr]!=dops[i-1].rs2&®s[i-1].regmap[hr]!=dops[i-1].rt1&®s[i-1].regmap[hr]!=dops[i-1].rt2) { + if (i > 0) { + for (hr = PREFERRED_REG_FIRST; ; ) { + if (cur->regmap[hr] < 0) { + int oldreg = regs[i-1].regmap[hr]; + if (oldreg < 0 || (oldreg != dops[i-1].rs1 && oldreg != dops[i-1].rs2 + && oldreg != dops[i-1].rt1 && oldreg != dops[i-1].rt2)) + { cur->regmap[hr]=reg; cur->dirty&=~(1<isconst&=~(1<regmap[hr]==-1) { + for (hr = PREFERRED_REG_FIRST; ; ) { + if (cur->regmap[hr] < 0) { cur->regmap[hr]=reg; cur->dirty&=~(1<isconst&=~(1<