From 95abd7c09b5abaad3d8b2d3fc32f2dfc64e6943f Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 24 May 2024 14:24:08 -0700 Subject: [PATCH 1/6] Add high field --- src/coreclr/jit/compiler.hpp | 42 ++++++++++++++++++++++++------ src/coreclr/jit/lsra.cpp | 8 +++--- src/coreclr/jit/lsrabuild.cpp | 4 +++ src/coreclr/jit/regset.h | 2 +- src/coreclr/jit/target.h | 49 +++++++++++++++++++++++------------ 5 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 648e2acc65acdc..975422682d70c8 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -933,7 +933,7 @@ inline unsigned Compiler::funGetFuncIdx(BasicBlock* block) // Assumptions: // The mask contains one and only one register. -inline regNumber genRegNumFromMask(regMaskTP mask) +inline regNumber genRegNumFromMask(const regMaskTP& mask) { assert(mask.IsNonEmpty()); // Must have one bit set, so can't have a mask of zero @@ -947,6 +947,27 @@ inline regNumber genRegNumFromMask(regMaskTP mask) return regNum; } +//------------------------------------------------------------------------------ +// genFirstRegNumFromMask : Maps first bit set in the register mask to a register number. +// +// Arguments: +// mask - the register mask +// +// Return Value: +// The number of the first register contained in the mask. +// + +inline regNumber genFirstRegNumFromMask(const regMaskTP& mask) +{ + assert(mask.IsNonEmpty()); // Must have one bit set, so can't have a mask of zero + + /* Convert the mask to a register number */ + + regNumber regNum = (regNumber)BitScanForward(mask); + + return regNum; +} + //------------------------------------------------------------------------------ // genFirstRegNumFromMaskAndToggle : Maps first bit set in the register mask to a // register number and also toggle the bit in the `mask`. @@ -964,34 +985,39 @@ inline regNumber genFirstRegNumFromMaskAndToggle(regMaskTP& mask) /* Convert the mask to a register number */ - regNumber regNum = (regNumber)BitScanForward(mask); + regNumber regNum = (regNumber)genFirstRegNumFromMask(mask); - mask ^= genRegMask(regNum); + mask ^= regNum; return regNum; } //------------------------------------------------------------------------------ -// genFirstRegNumFromMask : Maps first bit set in the register mask to a register number. -// +// genFirstRegNumFromMaskAndToggle : Maps first bit set in the register mask to a +// register number and also toggle the bit in the `mask`. // Arguments: // mask - the register mask // // Return Value: -// The number of the first register contained in the mask. +// The number of the first register contained in the mask and updates the `mask` to toggle +// the bit. // -inline regNumber genFirstRegNumFromMask(regMaskTP mask) +inline regNumber genFirstRegNumFromMaskAndToggle(SingleTypeRegSet& mask) { - assert(mask.IsNonEmpty()); // Must have one bit set, so can't have a mask of zero + assert(mask != RBM_NONE); // Must have one bit set, so can't have a mask of zero /* Convert the mask to a register number */ regNumber regNum = (regNumber)BitScanForward(mask); + mask ^= genRegMask(regNum); + return regNum; } + + /***************************************************************************** * * Return the size in bytes of the given type. diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index b642d59bca05a2..82357f2007bb2d 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -4022,7 +4022,7 @@ void LinearScan::processKills(RefPosition* killRefPosition) { RefPosition* nextKill = killRefPosition->nextRefPosition; - regMaskTP killedRegs = killRefPosition->registerAssignment; + SingleTypeRegSet killedRegs = killRefPosition->registerAssignment; while (killedRegs != RBM_NONE) { regNumber killedReg = genFirstRegNumFromMaskAndToggle(killedRegs); @@ -4064,7 +4064,7 @@ void LinearScan::spillGCRefs(RefPosition* killRefPosition) { // For each physical register that can hold a GC type, // if it is occupied by an interval of a GC type, spill that interval. - regMaskTP candidateRegs = killRefPosition->registerAssignment; + SingleTypeRegSet candidateRegs = killRefPosition->registerAssignment; INDEBUG(bool killedRegs = false); while (candidateRegs != RBM_NONE) { @@ -4157,7 +4157,7 @@ regNumber LinearScan::rotateBlockStartLocation(Interval* interval, regNumber tar { // If we're rotating the register locations at block boundaries, try to use // the next higher register number of the appropriate register type. - regMaskTP candidateRegs = allRegs(interval->registerType) & availableRegs; + SingleTypeRegSet candidateRegs = allRegs(interval->registerType) & availableRegs.GetRegSetForType(interval->registerType); regNumber firstReg = REG_NA; regNumber newReg = REG_NA; while (candidateRegs != RBM_NONE) @@ -12182,7 +12182,7 @@ void LinearScan::verifyFinalAllocation() // However, we will assert that, at resolution time, no registers contain GC refs. { DBEXEC(VERBOSE, printf(" ")); - regMaskTP candidateRegs = currentRefPosition.registerAssignment; + SingleTypeRegSet candidateRegs = currentRefPosition.registerAssignment; while (candidateRegs != RBM_NONE) { regNumber nextReg = genFirstRegNumFromMaskAndToggle(candidateRegs); diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 3be436c53b0187..565f70a3e11c56 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2825,6 +2825,9 @@ void LinearScan::buildIntervals() availableRegCount = REG_INT_COUNT; } +#ifdef HAS_MORE_THAN_64_REGISTERS + actualRegistersMask = regMaskTP(~RBM_NONE); +#else if (availableRegCount < (sizeof(regMaskTP) * 8)) { // Mask out the bits that are between 64 ~ availableRegCount @@ -2834,6 +2837,7 @@ void LinearScan::buildIntervals() { actualRegistersMask = ~RBM_NONE; } +#endif #ifdef DEBUG // Make sure we don't have any blocks that were not visited diff --git a/src/coreclr/jit/regset.h b/src/coreclr/jit/regset.h index 99c7f8be6bc556..49cd4dd2e6ecda 100644 --- a/src/coreclr/jit/regset.h +++ b/src/coreclr/jit/regset.h @@ -119,7 +119,7 @@ class RegSet bool rsRegsModified(regMaskTP mask) const { assert(rsModifiedRegsMaskInitialized); - return (rsModifiedRegsMask & mask) != 0; + return (rsModifiedRegsMask & mask).IsNonEmpty(); } void verifyRegUsed(regNumber reg); diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index 7e144eb9c5b213..c0d211f7cc1ead 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -229,16 +229,28 @@ typedef uint64_t regMaskSmall; #define REG_MASK_ALL_FMT "%016llX" #endif +#ifdef TARGET_ARM64 +#define HAS_MORE_THAN_64_REGISTERS 1 +#define MORE_THAN_64_REGISTERS(x) x +#else +#define MORE_THAN_64_REGISTERS(x) +#endif // TARGET_ARM64 + typedef regMaskSmall SingleTypeRegSet; +inline SingleTypeRegSet genRegMask(regNumber reg); +inline SingleTypeRegSet genRegMaskFloat(regNumber reg ARM_ARG(var_types type = TYP_DOUBLE)); struct regMaskTP { private: regMaskSmall low; + MORE_THAN_64_REGISTERS(regMaskSmall high); + public: - constexpr regMaskTP(regMaskSmall regMask) + regMaskTP(regMaskSmall regMask) : low(regMask) { + } regMaskTP() @@ -278,12 +290,12 @@ struct regMaskTP return low; } - bool IsEmpty() + bool IsEmpty() const { return low == RBM_NONE; } - bool IsNonEmpty() + bool IsNonEmpty() const { return !IsEmpty(); } @@ -298,48 +310,54 @@ struct regMaskTP bool IsRegNumInMask(regNumber reg); }; -static regMaskTP operator^(regMaskTP first, regMaskTP second) +static regMaskTP operator^(const regMaskTP& first, const regMaskTP& second) { regMaskTP result(first.getLow() ^ second.getLow()); return result; } -static regMaskTP operator&(regMaskTP first, regMaskTP second) +static regMaskTP operator&(const regMaskTP& first, const regMaskTP& second) { regMaskTP result(first.getLow() & second.getLow()); return result; } -static regMaskTP operator|(regMaskTP first, regMaskTP second) +static regMaskTP operator|(const regMaskTP& first, const regMaskTP& second) { regMaskTP result(first.getLow() | second.getLow()); return result; } -static regMaskTP& operator|=(regMaskTP& first, regMaskTP second) +static regMaskTP& operator|=(regMaskTP& first, const regMaskTP& second) { first = first | second; return first; } -static regMaskTP& operator^=(regMaskTP& first, regMaskTP second) +static regMaskTP& operator^=(regMaskTP& first, const regMaskTP& second) { first = first ^ second; return first; } -static regMaskTP& operator&=(regMaskTP& first, regMaskTP second) +static regMaskTP& operator^=(regMaskTP& first, const regNumber reg) +{ + first = first ^ genRegMask(reg); + return first; +} + +static regMaskTP& operator&=(regMaskTP& first, const regMaskTP& second) { first = first & second; return first; } -static bool operator==(regMaskTP first, regMaskTP second) +static bool operator==(const regMaskTP& first, const regMaskTP& second) { return (first.getLow() == second.getLow()); } -static bool operator!=(regMaskTP first, regMaskTP second) +static bool operator!=(const regMaskTP& first, const regMaskTP& second) { return !(first == second); } @@ -375,18 +393,18 @@ static regMaskTP& operator<<=(regMaskTP& first, const int b) } #endif -static regMaskTP operator~(regMaskTP first) +static regMaskTP operator~(const regMaskTP& first) { regMaskTP result(~first.getLow()); return result; } -static uint32_t PopCount(regMaskTP value) +static uint32_t PopCount(const regMaskTP& value) { return BitOperations::PopCount(value.getLow()); } -static uint32_t BitScanForward(regMaskTP mask) +static uint32_t BitScanForward(const regMaskTP& mask) { return BitOperations::BitScanForward(mask.getLow()); } @@ -508,9 +526,6 @@ inline bool isByteReg(regNumber reg) } #endif -inline SingleTypeRegSet genRegMask(regNumber reg); -inline SingleTypeRegSet genRegMaskFloat(regNumber reg ARM_ARG(var_types type = TYP_DOUBLE)); - /***************************************************************************** * Return true if the register number is valid */ From d53b62053d2abe4e0f82050aabb09328c740e667 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 24 May 2024 14:34:28 -0700 Subject: [PATCH 2/6] Do not use `const regMaskTP&` as parameter --- src/coreclr/jit/target.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index c0d211f7cc1ead..368052ca6342b1 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -310,31 +310,31 @@ struct regMaskTP bool IsRegNumInMask(regNumber reg); }; -static regMaskTP operator^(const regMaskTP& first, const regMaskTP& second) +static regMaskTP operator^(regMaskTP first, regMaskTP second) { regMaskTP result(first.getLow() ^ second.getLow()); return result; } -static regMaskTP operator&(const regMaskTP& first, const regMaskTP& second) +static regMaskTP operator&(regMaskTP first, regMaskTP second) { regMaskTP result(first.getLow() & second.getLow()); return result; } -static regMaskTP operator|(const regMaskTP& first, const regMaskTP& second) +static regMaskTP operator|(regMaskTP first, regMaskTP second) { regMaskTP result(first.getLow() | second.getLow()); return result; } -static regMaskTP& operator|=(regMaskTP& first, const regMaskTP& second) +static regMaskTP& operator|=(regMaskTP& first, regMaskTP second) { first = first | second; return first; } -static regMaskTP& operator^=(regMaskTP& first, const regMaskTP& second) +static regMaskTP& operator^=(regMaskTP& first, regMaskTP second) { first = first ^ second; return first; @@ -346,18 +346,18 @@ static regMaskTP& operator^=(regMaskTP& first, const regNumber reg) return first; } -static regMaskTP& operator&=(regMaskTP& first, const regMaskTP& second) +static regMaskTP& operator&=(regMaskTP& first, regMaskTP second) { first = first & second; return first; } -static bool operator==(const regMaskTP& first, const regMaskTP& second) +static bool operator==(regMaskTP first, regMaskTP second) { return (first.getLow() == second.getLow()); } -static bool operator!=(const regMaskTP& first, const regMaskTP& second) +static bool operator!=(regMaskTP first, regMaskTP second) { return !(first == second); } @@ -393,18 +393,18 @@ static regMaskTP& operator<<=(regMaskTP& first, const int b) } #endif -static regMaskTP operator~(const regMaskTP& first) +static regMaskTP operator~(regMaskTP first) { regMaskTP result(~first.getLow()); return result; } -static uint32_t PopCount(const regMaskTP& value) +static uint32_t PopCount(regMaskTP value) { return BitOperations::PopCount(value.getLow()); } -static uint32_t BitScanForward(const regMaskTP& mask) +static uint32_t BitScanForward(regMaskTP mask) { return BitOperations::BitScanForward(mask.getLow()); } From e2c0f038cab12b6dca2cf88eb7e5ae5a59f5836c Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 24 May 2024 14:34:33 -0700 Subject: [PATCH 3/6] Revert "Do not use `const regMaskTP&` as parameter" This reverts commit d53b62053d2abe4e0f82050aabb09328c740e667. By not passing `regMaskTP` using constant reference, there is a small cost we have to pay: Without constant reference: Overall: 1.80% MinOpts: 2.05% FullOpts: 1.62% With constant reference: Overall: 1.74% MinOpts: 1.94% FullOpts: 1.6% --- src/coreclr/jit/target.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index 368052ca6342b1..c0d211f7cc1ead 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -310,31 +310,31 @@ struct regMaskTP bool IsRegNumInMask(regNumber reg); }; -static regMaskTP operator^(regMaskTP first, regMaskTP second) +static regMaskTP operator^(const regMaskTP& first, const regMaskTP& second) { regMaskTP result(first.getLow() ^ second.getLow()); return result; } -static regMaskTP operator&(regMaskTP first, regMaskTP second) +static regMaskTP operator&(const regMaskTP& first, const regMaskTP& second) { regMaskTP result(first.getLow() & second.getLow()); return result; } -static regMaskTP operator|(regMaskTP first, regMaskTP second) +static regMaskTP operator|(const regMaskTP& first, const regMaskTP& second) { regMaskTP result(first.getLow() | second.getLow()); return result; } -static regMaskTP& operator|=(regMaskTP& first, regMaskTP second) +static regMaskTP& operator|=(regMaskTP& first, const regMaskTP& second) { first = first | second; return first; } -static regMaskTP& operator^=(regMaskTP& first, regMaskTP second) +static regMaskTP& operator^=(regMaskTP& first, const regMaskTP& second) { first = first ^ second; return first; @@ -346,18 +346,18 @@ static regMaskTP& operator^=(regMaskTP& first, const regNumber reg) return first; } -static regMaskTP& operator&=(regMaskTP& first, regMaskTP second) +static regMaskTP& operator&=(regMaskTP& first, const regMaskTP& second) { first = first & second; return first; } -static bool operator==(regMaskTP first, regMaskTP second) +static bool operator==(const regMaskTP& first, const regMaskTP& second) { return (first.getLow() == second.getLow()); } -static bool operator!=(regMaskTP first, regMaskTP second) +static bool operator!=(const regMaskTP& first, const regMaskTP& second) { return !(first == second); } @@ -393,18 +393,18 @@ static regMaskTP& operator<<=(regMaskTP& first, const int b) } #endif -static regMaskTP operator~(regMaskTP first) +static regMaskTP operator~(const regMaskTP& first) { regMaskTP result(~first.getLow()); return result; } -static uint32_t PopCount(regMaskTP value) +static uint32_t PopCount(const regMaskTP& value) { return BitOperations::PopCount(value.getLow()); } -static uint32_t BitScanForward(regMaskTP mask) +static uint32_t BitScanForward(const regMaskTP& mask) { return BitOperations::BitScanForward(mask.getLow()); } From 9086ad85b9f03d4ab8930b69481db2735626c6b3 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 24 May 2024 14:57:47 -0700 Subject: [PATCH 4/6] Furture reduce the TP cost Moved the *= operators as instance of `regMaskTP` so the `.low` private field can directly be manipulated instead of converting the `64-bit` value in `regMaskTP` before doing any operation. Overall: 0.74% MinOpts: 0.82% FullOpts: 0.68% --- src/coreclr/jit/compiler.hpp | 2 +- src/coreclr/jit/target.h | 48 +++++++++++++++++------------------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 975422682d70c8..b4d79335bb2eb9 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1009,7 +1009,7 @@ inline regNumber genFirstRegNumFromMaskAndToggle(SingleTypeRegSet& mask) /* Convert the mask to a register number */ - regNumber regNum = (regNumber)BitScanForward(mask); + regNumber regNum = (regNumber)BitOperations::BitScanForward(mask); mask ^= genRegMask(regNum); diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index c0d211f7cc1ead..c73d948210aa74 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -249,8 +249,7 @@ struct regMaskTP public: regMaskTP(regMaskSmall regMask) : low(regMask) - { - + { } regMaskTP() @@ -308,6 +307,27 @@ struct regMaskTP void RemoveRegNumFromMask(regNumber reg); bool IsRegNumInMask(regNumber reg); + + + void operator|=(const regMaskTP& second) + { + low |= second.getLow(); + } + + void operator^=(const regMaskTP& second) + { + low ^= second.getLow(); + } + + void operator^=(const regNumber reg) + { + low ^= genRegMask(reg); + } + + void operator&=(const regMaskTP& second) + { + low &= second.getLow(); + } }; static regMaskTP operator^(const regMaskTP& first, const regMaskTP& second) @@ -328,30 +348,6 @@ static regMaskTP operator|(const regMaskTP& first, const regMaskTP& second) return result; } -static regMaskTP& operator|=(regMaskTP& first, const regMaskTP& second) -{ - first = first | second; - return first; -} - -static regMaskTP& operator^=(regMaskTP& first, const regMaskTP& second) -{ - first = first ^ second; - return first; -} - -static regMaskTP& operator^=(regMaskTP& first, const regNumber reg) -{ - first = first ^ genRegMask(reg); - return first; -} - -static regMaskTP& operator&=(regMaskTP& first, const regMaskTP& second) -{ - first = first & second; - return first; -} - static bool operator==(const regMaskTP& first, const regMaskTP& second) { return (first.getLow() == second.getLow()); From aff022f1a6034b0022808ef3f1f8b7a670bcbe87 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 24 May 2024 15:09:58 -0700 Subject: [PATCH 5/6] jit fornat --- src/coreclr/jit/compiler.hpp | 2 -- src/coreclr/jit/lsra.cpp | 7 ++++--- src/coreclr/jit/target.h | 7 +++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index b4d79335bb2eb9..be01a5095bc33b 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1016,8 +1016,6 @@ inline regNumber genFirstRegNumFromMaskAndToggle(SingleTypeRegSet& mask) return regNum; } - - /***************************************************************************** * * Return the size in bytes of the given type. diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 82357f2007bb2d..b437c34dac874f 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -4157,9 +4157,10 @@ regNumber LinearScan::rotateBlockStartLocation(Interval* interval, regNumber tar { // If we're rotating the register locations at block boundaries, try to use // the next higher register number of the appropriate register type. - SingleTypeRegSet candidateRegs = allRegs(interval->registerType) & availableRegs.GetRegSetForType(interval->registerType); - regNumber firstReg = REG_NA; - regNumber newReg = REG_NA; + SingleTypeRegSet candidateRegs = + allRegs(interval->registerType) & availableRegs.GetRegSetForType(interval->registerType); + regNumber firstReg = REG_NA; + regNumber newReg = REG_NA; while (candidateRegs != RBM_NONE) { regNumber nextReg = genFirstRegNumFromMaskAndToggle(candidateRegs); diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index c73d948210aa74..a0de3339a99e7a 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -231,12 +231,12 @@ typedef uint64_t regMaskSmall; #ifdef TARGET_ARM64 #define HAS_MORE_THAN_64_REGISTERS 1 -#define MORE_THAN_64_REGISTERS(x) x +#define MORE_THAN_64_REGISTERS(x) x #else #define MORE_THAN_64_REGISTERS(x) #endif // TARGET_ARM64 -typedef regMaskSmall SingleTypeRegSet; +typedef regMaskSmall SingleTypeRegSet; inline SingleTypeRegSet genRegMask(regNumber reg); inline SingleTypeRegSet genRegMaskFloat(regNumber reg ARM_ARG(var_types type = TYP_DOUBLE)); @@ -249,7 +249,7 @@ struct regMaskTP public: regMaskTP(regMaskSmall regMask) : low(regMask) - { + { } regMaskTP() @@ -308,7 +308,6 @@ struct regMaskTP bool IsRegNumInMask(regNumber reg); - void operator|=(const regMaskTP& second) { low |= second.getLow(); From 2d2e4573a9c1867289132fee54c07bc207397564 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 24 May 2024 15:52:13 -0700 Subject: [PATCH 6/6] Add high to all platforms --- src/coreclr/jit/lsrabuild.cpp | 21 +++++++++++++-------- src/coreclr/jit/target.h | 16 ++++++++-------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 565f70a3e11c56..e416f5e40c98aa 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2825,19 +2825,24 @@ void LinearScan::buildIntervals() availableRegCount = REG_INT_COUNT; } -#ifdef HAS_MORE_THAN_64_REGISTERS - actualRegistersMask = regMaskTP(~RBM_NONE); -#else - if (availableRegCount < (sizeof(regMaskTP) * 8)) + static_assert(sizeof(regMaskTP) == 2 * sizeof(regMaskSmall)); + + if (availableRegCount < (sizeof(regMaskSmall) * 8)) { - // Mask out the bits that are between 64 ~ availableRegCount - actualRegistersMask = (1ULL << availableRegCount) - 1; + // Mask out the bits that are between (8 * regMaskSmall) ~ availableRegCount + actualRegistersMask = regMaskTP((1ULL << availableRegCount) - 1); + } + else if (availableRegCount < (sizeof(regMaskTP) * 8)) + { + // Mask out the bits that are between (8 * regMaskTP) ~ availableRegCount + // Subtract one extra for stack. + unsigned topRegCount = availableRegCount - sizeof(regMaskSmall) * 8 - 1; + actualRegistersMask = regMaskTP(~RBM_NONE, (1ULL << topRegCount) - 1); } else { - actualRegistersMask = ~RBM_NONE; + actualRegistersMask = regMaskTP(~RBM_NONE, ~RBM_NONE); } -#endif #ifdef DEBUG // Make sure we don't have any blocks that were not visited diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index a0de3339a99e7a..3e3e4591281372 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -229,13 +229,6 @@ typedef uint64_t regMaskSmall; #define REG_MASK_ALL_FMT "%016llX" #endif -#ifdef TARGET_ARM64 -#define HAS_MORE_THAN_64_REGISTERS 1 -#define MORE_THAN_64_REGISTERS(x) x -#else -#define MORE_THAN_64_REGISTERS(x) -#endif // TARGET_ARM64 - typedef regMaskSmall SingleTypeRegSet; inline SingleTypeRegSet genRegMask(regNumber reg); inline SingleTypeRegSet genRegMaskFloat(regNumber reg ARM_ARG(var_types type = TYP_DOUBLE)); @@ -244,9 +237,16 @@ struct regMaskTP { private: regMaskSmall low; - MORE_THAN_64_REGISTERS(regMaskSmall high); + regMaskSmall high; public: + + regMaskTP(regMaskSmall lowMask, regMaskSmall highMask) + : low(lowMask) + , high(highMask) + { + } + regMaskTP(regMaskSmall regMask) : low(regMask) {