summaryrefslogtreecommitdiff
path: root/src/jit/regalloc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/regalloc.cpp')
-rw-r--r--src/jit/regalloc.cpp208
1 files changed, 93 insertions, 115 deletions
diff --git a/src/jit/regalloc.cpp b/src/jit/regalloc.cpp
index 9dd7299906..8a7ad5a163 100644
--- a/src/jit/regalloc.cpp
+++ b/src/jit/regalloc.cpp
@@ -53,8 +53,6 @@ regMaskTP Compiler::raConfigRestrictMaskFP()
return result;
}
-#ifdef LEGACY_BACKEND // We don't use any of the old register allocator functions when LSRA is used instead.
-
#if DOUBLE_ALIGN
DWORD Compiler::getCanDoubleAlign()
{
@@ -67,8 +65,84 @@ DWORD Compiler::getCanDoubleAlign()
return DEFAULT_DOUBLE_ALIGN;
#endif
}
+
+//------------------------------------------------------------------------
+// shouldDoubleAlign: Determine whether to double-align the frame
+//
+// Arguments:
+// refCntStk - sum of ref counts for all stack based variables
+// refCntEBP - sum of ref counts for EBP enregistered variables
+// refCntWtdEBP - sum of wtd ref counts for EBP enregistered variables
+// refCntStkParam - sum of ref counts for all stack based parameters
+// refCntWtdStkDbl - sum of wtd ref counts for stack based doubles (including structs
+// with double fields).
+//
+// Return Value:
+// Returns true if this method estimates that a double-aligned frame would be beneficial
+//
+// Notes:
+// The impact of a double-aligned frame is computed as follows:
+// - We save a byte of code for each parameter reference (they are frame-pointer relative)
+// - We pay a byte of code for each non-parameter stack reference.
+// - We save the misalignment penalty and possible cache-line crossing penalty.
+// This is estimated as 0 for SMALL_CODE, 16 for FAST_CODE and 4 otherwise.
+// - We pay 7 extra bytes for:
+// MOV EBP,ESP,
+// LEA ESP,[EBP-offset]
+// AND ESP,-8 to double align ESP
+// - We pay one extra memory reference for each variable that could have been enregistered in EBP (refCntWtdEBP).
+//
+// If the misalignment penalty is estimated to be less than the bytes used, we don't double align.
+// Otherwise, we compare the weighted ref count of ebp-enregistered variables aginst double the
+// ref count for double-aligned values.
+//
+bool Compiler::shouldDoubleAlign(
+ unsigned refCntStk, unsigned refCntEBP, unsigned refCntWtdEBP, unsigned refCntStkParam, unsigned refCntWtdStkDbl)
+{
+ bool doDoubleAlign = false;
+ const unsigned DBL_ALIGN_SETUP_SIZE = 7;
+
+ unsigned bytesUsed = refCntStk + refCntEBP - refCntStkParam + DBL_ALIGN_SETUP_SIZE;
+ unsigned misaligned_weight = 4;
+
+ if (compCodeOpt() == Compiler::SMALL_CODE)
+ misaligned_weight = 0;
+
+ if (compCodeOpt() == Compiler::FAST_CODE)
+ misaligned_weight *= 4;
+
+ JITDUMP("\nDouble alignment:\n");
+ JITDUMP(" Bytes that could be saved by not using EBP frame: %i\n", bytesUsed);
+ JITDUMP(" Sum of weighted ref counts for EBP enregistered variables: %i\n", refCntWtdEBP);
+ JITDUMP(" Sum of weighted ref counts for weighted stack based doubles: %i\n", refCntWtdStkDbl);
+
+ if (bytesUsed > ((refCntWtdStkDbl * misaligned_weight) / BB_UNITY_WEIGHT))
+ {
+ JITDUMP(" Predicting not to double-align ESP to save %d bytes of code.\n", bytesUsed);
+ }
+ else if (refCntWtdEBP > refCntWtdStkDbl * 2)
+ {
+ // TODO-CQ: On P4 2 Proc XEON's, SciMark.FFT degrades if SciMark.FFT.transform_internal is
+ // not double aligned.
+ // Here are the numbers that make this not double-aligned.
+ // refCntWtdStkDbl = 0x164
+ // refCntWtdEBP = 0x1a4
+ // We think we do need to change the heuristic to be in favor of double-align.
+
+ JITDUMP(" Predicting not to double-align ESP to allow EBP to be used to enregister variables.\n");
+ }
+ else
+ {
+ // OK we passed all of the benefit tests, so we'll predict a double aligned frame.
+ JITDUMP(" Predicting to create a double-aligned frame\n");
+ doDoubleAlign = true;
+ }
+ return doDoubleAlign;
+}
#endif // DOUBLE_ALIGN
+#ifdef LEGACY_BACKEND // We don't use any of the old register allocator functions when LSRA is used instead.
+
void Compiler::raInit()
{
#if FEATURE_STACK_FP_X87
@@ -2415,12 +2489,6 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree,
{
case GT_ASG:
- if (tree->OperIsBlkOp())
- {
- interferingRegs |= rpPredictBlkAsgRegUse(tree, predictReg, lockedRegs, rsvdRegs);
- regMask = 0;
- goto RETURN_CHECK;
- }
/* Is the value being assigned into a LCL_VAR? */
if (op1->gtOper == GT_LCL_VAR)
{
@@ -2486,6 +2554,12 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree,
}
}
}
+ else if (tree->OperIsBlkOp())
+ {
+ interferingRegs |= rpPredictBlkAsgRegUse(tree, predictReg, lockedRegs, rsvdRegs);
+ regMask = 0;
+ goto RETURN_CHECK;
+ }
__fallthrough;
case GT_CHS:
@@ -4384,6 +4458,13 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree,
case GT_ARR_LENGTH:
goto GENERIC_UNARY;
+ case GT_INIT_VAL:
+ // This unary operator simply passes through the value from its child (much like GT_NOP)
+ // and thus won't need a scratch register.
+ regMask = rpPredictTreeRegUse(op1, predictReg, lockedRegs, rsvdRegs);
+ tree->gtUsedRegs = op1->gtUsedRegs;
+ goto RETURN_CHECK;
+
default:
#ifdef DEBUG
gtDispTree(tree);
@@ -4525,7 +4606,7 @@ regMaskTP Compiler::rpPredictTreeRegUse(GenTreePtr tree,
curArgMask = RBM_NONE; // Set of argument registers that are going to be setup by this arg
tmpMask = RBM_NONE; // Set of additional temp registers that are need only to setup the current arg
- assert(list->IsList());
+ assert(list->OperIsList());
args = list->Current();
list = list->Rest();
@@ -5840,114 +5921,14 @@ regMaskTP Compiler::rpPredictAssignRegVars(regMaskTP regAvail)
if (getCanDoubleAlign() == CAN_DOUBLE_ALIGN && (refCntWtdStkDbl > 0))
{
- /* OK, there may be some benefit to double-aligning the frame */
- /* But let us compare the benefits vs. the costs of this */
-
- /*
- One cost to consider is the benefit of smaller code
- when using EBP as a frame pointer register
-
- Each stack variable reference is an extra byte of code
- if we use a double-aligned frame, parameters are
- accessed via EBP for a double-aligned frame so they
- don't use an extra byte of code.
-
- We pay one byte of code for each refCntStk and we pay
- one byte or more for each refCntEBP but we save one
- byte for each refCntStkParam.
-
- Our savings are the elimination of a possible misaligned
- access and a possible DCU spilt when an access crossed
- a cache-line boundry.
-
- We use the loop weighted value of
- refCntWtdStkDbl * misaligned_weight (0, 4, 16)
- to represent this savings.
- */
-
- // We also pay 7 extra bytes for the MOV EBP,ESP,
- // LEA ESP,[EBP-0x10] and the AND ESP,-8 to double align ESP
- const unsigned DBL_ALIGN_SETUP_SIZE = 7;
-
- unsigned bytesUsed = refCntStk + refCntEBP - refCntStkParam + DBL_ALIGN_SETUP_SIZE;
- unsigned misaligned_weight = 4;
-
- if (compCodeOpt() == SMALL_CODE)
- misaligned_weight = 0;
-
- if (compCodeOpt() == FAST_CODE)
- misaligned_weight *= 4;
-
-#ifdef DEBUG
- if (verbose)
- {
- printf("; Double alignment:\n");
- printf("; Bytes that could be save by not using EBP frame: %i\n", bytesUsed);
- printf("; Sum of weighted ref counts for EBP enregistered variables: %i\n", refCntWtdEBP);
- printf("; Sum of weighted ref counts for weighted stack based doubles: %i\n", refCntWtdStkDbl);
- }
-#endif
-
- if (bytesUsed > ((refCntWtdStkDbl * misaligned_weight) / BB_UNITY_WEIGHT))
- {
- /* It's probably better to use EBP as a frame pointer */
- CLANG_FORMAT_COMMENT_ANCHOR;
-
-#ifdef DEBUG
- if (verbose)
- printf("; Predicting not to double-align ESP to save %d bytes of code.\n", bytesUsed);
-#endif
- goto NO_DOUBLE_ALIGN;
- }
-
- /*
- Another cost to consider is the benefit of using EBP to enregister
- one or more integer variables
-
- We pay one extra memory reference for each refCntWtdEBP
-
- Our savings are the elimination of a possible misaligned
- access and a possible DCU spilt when an access crossed
- a cache-line boundry.
-
- */
-
- // <BUGNUM>
- // VSW 346717: On P4 2 Proc XEON's, SciMark.FFT degrades if SciMark.FFT.transform_internal is
- // not double aligned.
- // Here are the numbers that make this not double-aligned.
- // refCntWtdStkDbl = 0x164
- // refCntWtdEBP = 0x1a4
- // We think we do need to change the heuristic to be in favor of double-align.
- // </BUGNUM>
-
- if (refCntWtdEBP > refCntWtdStkDbl * 2)
+ if (shouldDoubleAlign(refCntStk, refCntEBP, refCntWtdEBP, refCntStkParam, refCntWtdStkDbl))
{
- /* It's probably better to use EBP to enregister integer variables */
- CLANG_FORMAT_COMMENT_ANCHOR;
-
-#ifdef DEBUG
- if (verbose)
- printf("; Predicting not to double-align ESP to allow EBP to be used to enregister variables\n");
-#endif
- goto NO_DOUBLE_ALIGN;
+ rpFrameType = FT_DOUBLE_ALIGN_FRAME;
+ goto REVERSE_EBP_ENREG;
}
-
-#ifdef DEBUG
- if (verbose)
- printf("; Predicting to create a double-aligned frame\n");
-#endif
- /*
- OK we passed all of the benefit tests
- so we'll predict a double aligned frame
- */
-
- rpFrameType = FT_DOUBLE_ALIGN_FRAME;
- goto REVERSE_EBP_ENREG;
}
}
-NO_DOUBLE_ALIGN:
#endif // DOUBLE_ALIGN
if (!codeGen->isFramePointerRequired() && !codeGen->isFrameRequired())
@@ -6673,8 +6654,6 @@ void Compiler::raMarkStkVars()
#endif // FEATURE_FIXED_OUT_ARGS
-#ifdef DEBUGGING_SUPPORT
-
#ifdef DEBUG
/* For debugging, note that we have to reserve space even for
unused variables if they are ever in scope. However, this is not
@@ -6709,7 +6688,6 @@ void Compiler::raMarkStkVars()
varDsc->lvMustInit = true;
}
}
-#endif // DEBUGGING_SUPPORT
#ifndef LEGACY_BACKEND
varDsc->lvOnFrame = needSlot;