diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index bbf30da0c728fa..93d515c4f92acf 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -9983,7 +9983,6 @@ void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callIn unsigned argStkCnt; S_UINT16 argRecCnt(0); // arg count for ESP, ptr-arg count for EBP - unsigned gcrefRegs, byrefRegs; #ifdef JIT32_GCENCODER // For the general encoder, we always need to record calls, so we make this call @@ -10025,26 +10024,19 @@ void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callIn return; #endif - // Do we have any interesting (i.e., callee-saved) registers live here? + // Do we have any interesting registers live here? - gcrefRegs = byrefRegs = 0; + unsigned gcrefRegs = emitThisGCrefRegs.GetIntRegSet() >> REG_INT_FIRST; + unsigned byrefRegs = emitThisByrefRegs.GetIntRegSet() >> REG_INT_FIRST; - // We make a bitmask whose bits correspond to callee-saved register indices (in the sequence - // of callee-saved registers only). - for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALL_GC_REGS; calleeSavedRegIdx++) - { - regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx]; - if (emitThisGCrefRegs & calleeSavedRbm) - { - gcrefRegs |= (1 << calleeSavedRegIdx); - } - if (emitThisByrefRegs & calleeSavedRbm) - { - byrefRegs |= (1 << calleeSavedRegIdx); - } - } + assert(regMaskTP::FromIntRegSet(SingleTypeRegSet(gcrefRegs << REG_INT_FIRST)) == emitThisGCrefRegs); + assert(regMaskTP::FromIntRegSet(SingleTypeRegSet(byrefRegs << REG_INT_FIRST)) == emitThisByrefRegs); #ifdef JIT32_GCENCODER + // x86 does not report GC refs/byrefs in return registers at call sites + gcrefRegs &= ~(1u << (REG_INTRET - REG_INT_FIRST)); + byrefRegs &= ~(1u << (REG_INTRET - REG_INT_FIRST)); + // For the general encoder, we always have to record calls, so we don't take this early return. /* Are there any // args to pop at this call site? diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp index b32dc60292dbbf..688f61f60923ed 100644 --- a/src/coreclr/jit/gcencode.cpp +++ b/src/coreclr/jit/gcencode.cpp @@ -3199,9 +3199,24 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un callArgCnt = genRegPtrTemp->rpdPtrArg; - unsigned gcrefRegMask = genRegPtrTemp->rpdCallGCrefRegs; + unsigned gcrefRegMask = 0; - byrefRegMask = genRegPtrTemp->rpdCallByrefRegs; + byrefRegMask = 0; + + // The order here is fixed: it must agree with the order assumed in eetwain. + // NB: x86 GC decoder does not report return registers at call sites. + static const regNumber calleeSaveOrder[] = {REG_EDI, REG_ESI, REG_EBX, REG_EBP}; + for (unsigned i = 0; i < ArrLen(calleeSaveOrder); i++) + { + if ((genRegPtrTemp->rpdCallGCrefRegs & (1 << (calleeSaveOrder[i] - REG_INT_FIRST))) != 0) + { + gcrefRegMask |= 1u << i; + } + if ((genRegPtrTemp->rpdCallByrefRegs & (1 << (calleeSaveOrder[i] - REG_INT_FIRST))) != 0) + { + byrefRegMask |= 1u << i; + } + } assert((gcrefRegMask & byrefRegMask) == 0); @@ -4465,8 +4480,8 @@ void GCInfo::gcMakeRegPtrTable( assert(call->u1.cdArgMask == 0 && call->cdArgCnt == 0); // Other than that, we just have to deal with the regmasks. - regMaskSmall gcrefRegMask = call->cdGCrefRegs & RBM_CALL_GC_REGS.GetIntRegSet(); - regMaskSmall byrefRegMask = call->cdByrefRegs & RBM_CALL_GC_REGS.GetIntRegSet(); + regMaskSmall gcrefRegMask = call->cdGCrefRegs; + regMaskSmall byrefRegMask = call->cdByrefRegs; assert((gcrefRegMask & byrefRegMask) == 0); @@ -4552,11 +4567,8 @@ void GCInfo::gcMakeRegPtrTable( { // This is a true call site. - regMaskSmall gcrefRegMask = - genRegMaskFromCalleeSavedMask(genRegPtrTemp->rpdCallGCrefRegs).GetIntRegSet(); - - regMaskSmall byrefRegMask = - genRegMaskFromCalleeSavedMask(genRegPtrTemp->rpdCallByrefRegs).GetIntRegSet(); + regMaskSmall gcrefRegMask = regMaskSmall(genRegPtrTemp->rpdCallGCrefRegs << REG_INT_FIRST); + regMaskSmall byrefRegMask = regMaskSmall(genRegPtrTemp->rpdCallByrefRegs << REG_INT_FIRST); assert((gcrefRegMask & byrefRegMask) == 0); diff --git a/src/coreclr/jit/jitgcinfo.h b/src/coreclr/jit/jitgcinfo.h index 6c62a0816113a5..6d04e3b22734b3 100644 --- a/src/coreclr/jit/jitgcinfo.h +++ b/src/coreclr/jit/jitgcinfo.h @@ -162,7 +162,13 @@ class GCInfo regMaskSmall rpdDel; // regptr bitset being removed } rpdCompiler; - unsigned short rpdPtrArg; // arg offset or popped arg count + struct + { + // Registers after call containing GC/byref (index 0 = REG_INT_FIRST) + unsigned int rpdCallGCrefRegs; + unsigned int rpdCallByrefRegs; + unsigned short rpdPtrArg; // arg offset or popped arg count + }; }; #ifndef JIT32_GCENCODER @@ -182,11 +188,8 @@ class GCInfo return (GCtype)rpdGCtype; } - unsigned short rpdIsThis : 1; // is it the 'this' pointer - unsigned short rpdCall : 1; // is this a true call site? - unsigned short : 1; // Padding bit, so next two start on a byte boundary - unsigned short rpdCallGCrefRegs : CNT_CALL_GC_REGS; // Callee-saved and return registers containing GC pointers. - unsigned short rpdCallByrefRegs : CNT_CALL_GC_REGS; // Callee-saved and return registers containing byrefs. + unsigned short rpdIsThis : 1; // is it the 'this' pointer + unsigned short rpdCall : 1; // is this a true call site? #ifndef JIT32_GCENCODER bool rpdIsCallInstr() diff --git a/src/coreclr/jit/regset.cpp b/src/coreclr/jit/regset.cpp index 06444fb31cf956..3d9354b040f48e 100644 --- a/src/coreclr/jit/regset.cpp +++ b/src/coreclr/jit/regset.cpp @@ -944,27 +944,6 @@ regNumber genRegArgNext(regNumber argReg) } } -/***************************************************************************** - * - * The following table determines the order in which callee registers - * are encoded in GC information at call sites. - */ - -const regMaskTP raRbmCalleeSaveOrder[] = {RBM_CALL_GC_REGS_ORDER}; - -regMaskTP genRegMaskFromCalleeSavedMask(unsigned short calleeSaveMask) -{ - regMaskTP res = 0; - for (int i = 0; i < CNT_CALL_GC_REGS; i++) - { - if ((calleeSaveMask & (1 << i)) != 0) - { - res |= raRbmCalleeSaveOrder[i]; - } - } - return res; -} - /***************************************************************************** * * Initializes the spill code. Should be called once per function compiled. diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index a9728857eb717f..cb4957a6b5f107 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -379,6 +379,11 @@ struct regMaskTP #endif } + static regMaskTP FromIntRegSet(SingleTypeRegSet intRegs) + { + return regMaskTP(intRegs); + } + void operator|=(const regMaskTP& second) { low |= second.getLow(); @@ -1066,16 +1071,6 @@ inline SingleTypeRegSet getSingleTypeRegMask(regNumber reg, var_types regType) return regMask; } -/***************************************************************************** - * - * These arrays list the callee-saved register numbers (and bitmaps, respectively) for - * the current architecture. - */ -extern const regMaskTP raRbmCalleeSaveOrder[CNT_CALL_GC_REGS]; - -// This method takes a "compact" bitset of the callee-saved registers, and "expands" it to a full register mask. -regMaskTP genRegMaskFromCalleeSavedMask(unsigned short); - /***************************************************************************** * * Assumes that "reg" is of the given "type". Return the next unused reg number after "reg" diff --git a/src/coreclr/jit/targetamd64.h b/src/coreclr/jit/targetamd64.h index 869bf1944ce5f0..eaaf6fc4ccbc9d 100644 --- a/src/coreclr/jit/targetamd64.h +++ b/src/coreclr/jit/targetamd64.h @@ -300,7 +300,6 @@ #ifdef UNIX_AMD64_ABI #define CNT_CALLEE_SAVED (5 + REG_ETW_FRAMED_EBP_COUNT) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) - #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED + 2) #define CNT_CALLEE_TRASH_INT_INIT (9) #define CNT_CALLEE_TRASH_HIGHINT (8) @@ -308,16 +307,12 @@ #define CNT_CALLEE_SAVED_FLOAT (0) #define CNT_CALLEE_TRASH_FLOAT_INIT (16) #define CNT_CALLEE_TRASH_HIGHFLOAT (16) - /* NOTE: Sync with variable name defined in compiler.h */ - #define RBM_CALL_GC_REGS_ORDER RBM_EBX,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15,RBM_INTRET,RBM_INTRET_1 - #define RBM_CALL_GC_REGS (RBM_EBX|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_INTRET|RBM_INTRET_1) // For SysV we have more volatile registers so we do not save any callee saves for EnC. #define RBM_ENC_CALLEE_SAVED 0 #else // !UNIX_AMD64_ABI #define CNT_CALLEE_SAVED (7 + REG_ETW_FRAMED_EBP_COUNT) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) - #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED + 1) #define CNT_CALLEE_TRASH_INT_INIT (7) #define CNT_CALLEE_TRASH_HIGHINT (8) @@ -326,9 +321,6 @@ #define CNT_CALLEE_SAVED_FLOAT (10) #define CNT_CALLEE_TRASH_FLOAT_INIT (6) #define CNT_CALLEE_TRASH_HIGHFLOAT (16) - /* NOTE: Sync with variable name defined in compiler.h */ - #define RBM_CALL_GC_REGS_ORDER RBM_EBX,RBM_ESI,RBM_EDI,RBM_ETW_FRAMED_EBP_LIST RBM_R12,RBM_R13,RBM_R14,RBM_R15,RBM_INTRET - #define RBM_CALL_GC_REGS (RBM_EBX|RBM_ESI|RBM_EDI|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_INTRET) // Callee-preserved registers we always save and allow use of for EnC code, since there are quite few volatile registers. #define RBM_ENC_CALLEE_SAVED (RBM_RSI | RBM_RDI) diff --git a/src/coreclr/jit/targetarm.h b/src/coreclr/jit/targetarm.h index 710187e70b0667..95cb19a2291a49 100644 --- a/src/coreclr/jit/targetarm.h +++ b/src/coreclr/jit/targetarm.h @@ -89,13 +89,9 @@ #define RBM_LOW_REGS (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7) #define RBM_HIGH_REGS (RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_SP|RBM_LR|RBM_PC) - #define RBM_CALL_GC_REGS_ORDER RBM_R4,RBM_R5,RBM_R6,RBM_R7,RBM_R8,RBM_R9,RBM_R10,RBM_R11,RBM_INTRET - #define RBM_CALL_GC_REGS (RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_INTRET) - #define CNT_CALLEE_SAVED (8) #define CNT_CALLEE_TRASH (6) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+1) #define CNT_CALLEE_SAVED_FLOAT (16) #define CNT_CALLEE_TRASH_FLOAT (16) diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h index f5b96a2bc6104a..3e1dec49b4778a 100644 --- a/src/coreclr/jit/targetarm64.h +++ b/src/coreclr/jit/targetarm64.h @@ -108,13 +108,9 @@ REG_V12, REG_V13, REG_V14, REG_V15, \ REG_V3, REG_V2, REG_V1, REG_V0 - #define RBM_CALL_GC_REGS_ORDER RBM_R19,RBM_R20,RBM_R21,RBM_R22,RBM_R23,RBM_R24,RBM_R25,RBM_R26,RBM_R27,RBM_R28,RBM_INTRET,RBM_INTRET_1 - #define RBM_CALL_GC_REGS (RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28|RBM_INTRET|RBM_INTRET_1) - #define CNT_CALLEE_SAVED (11) #define CNT_CALLEE_TRASH (17) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED+2) #define CNT_CALLEE_SAVED_FLOAT (8) #define CNT_CALLEE_TRASH_FLOAT (24) diff --git a/src/coreclr/jit/targetx86.h b/src/coreclr/jit/targetx86.h index 2e46478690e5cc..dd63766d631ac7 100644 --- a/src/coreclr/jit/targetx86.h +++ b/src/coreclr/jit/targetx86.h @@ -143,16 +143,9 @@ #define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX #define MAX_VAR_ORDER_SIZE 6 - // The order here is fixed: it must agree with an order assumed in eetwain... - // NB: x86 GC decoder does not report return registers at call sites. - #define RBM_CALL_GC_REGS_ORDER RBM_EDI,RBM_ESI,RBM_EBX,RBM_EBP - #define RBM_CALL_GC_REGS (RBM_EDI|RBM_ESI|RBM_EBX|RBM_EBP) - #define CNT_CALLEE_SAVED (4) #define CNT_CALLEE_TRASH (3) #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - // NB: x86 GC decoder does not report return registers at call sites. - #define CNT_CALL_GC_REGS (CNT_CALLEE_SAVED) #define CNT_CALLEE_SAVED_FLOAT (0) #define CNT_CALLEE_TRASH_FLOAT (6)