Skip to content

Commit

Permalink
Merge pull request eclipse-omr#7427 from gita-omr/snippets_after_warm
Browse files Browse the repository at this point in the history
Move snippets to warm code
  • Loading branch information
0xdaryl authored Aug 23, 2024
2 parents 32daf17 + b9cc9ab commit dc1ec39
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 59 deletions.
15 changes: 14 additions & 1 deletion compiler/codegen/OMRCodeGenPhase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,20 @@ OMR::CodeGenPhase::performEmitSnippetsPhase(TR::CodeGenerator * cg, TR::CodeGenP
TR::LexicalMemProfiler mp("Emit Snippets", comp->phaseMemProfiler());
LexicalTimer pt("Emit Snippets", comp->phaseTimer());

cg->emitSnippets();
if (cg->getLastWarmInstruction() &&
comp->getOption(TR_MoveSnippetsToWarmCode))
{
// Snippets will follow warm blocks
uint8_t * oldCursor = cg->getBinaryBufferCursor();
cg->setBinaryBufferCursor(cg->getWarmCodeEnd());
cg->emitSnippets();
cg->setWarmCodeEnd(cg->getBinaryBufferCursor());
cg->setBinaryBufferCursor(oldCursor);
}
else
{
cg->emitSnippets();
}

if (comp->getOption(TR_EnableOSR))
{
Expand Down
138 changes: 83 additions & 55 deletions compiler/codegen/OMRCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,79 @@ OMR::CodeGenerator::generateCodeFromIL()
return false;
}

void OMR::CodeGenerator::findLastWarmBlock()
void
OMR::CodeGenerator::insertGotoIntoLastBlock(TR::Block *lastBlock)
{
// If the last tree in the last block is not a TR_goto, insert a goto tree
// at the end of the block.
// If there is a following block the goto will branch to it so that when the
// code is split any fall-through will go to the right place.
// If there is no following block the goto will branch to the first block; in
// this case the goto should never be reached, it is there only to
// make sure that the instruction following the last real treetop will be in
// method's code, so if it is a helper call (e.g. for a throw) the return address
// is in this method's code.
//
TR::Compilation *comp = self()->comp();
TR::TreeTop * tt;
TR::Node * node;

if (lastBlock->getNumberOfRealTreeTops() == 0)
tt = lastBlock->getEntry();
else
tt = lastBlock->getLastRealTreeTop();

node = tt->getNode();

if (!(node->getOpCode().isGoto() ||
node->getOpCode().isJumpWithMultipleTargets() ||
node->getOpCode().isReturn()))
{

if (comp->getOption(TR_TraceCG))
{
traceMsg(comp, "%s Inserting goto at the end of block_%d\n", SPLIT_WARM_COLD_STRING, lastBlock->getNumber());
}

// Find the block to be branched to
//
TR::TreeTop * targetTreeTop = lastBlock->getExit()->getNextTreeTop();

if (targetTreeTop)
// Branch to following block. Make sure it is not marked as an
// extension block so that it will get a label generated.
//
targetTreeTop->getNode()->getBlock()->setIsExtensionOfPreviousBlock(false);
else
// Branch to the first block. This will not be marked as an extension
// block.
//
targetTreeTop = comp->getStartBlock()->getEntry();

// Generate the goto and insert it into the end of the last warm block.
//
TR::TreeTop *gotoTreeTop = TR::TreeTop::create(comp, TR::Node::create(node, TR::Goto, 0, targetTreeTop));

// Move reg deps from BBEnd to goto
//
TR::Node *bbEnd = lastBlock->getExit()->getNode();

if (bbEnd->getNumChildren() > 0)
{
TR::Node *glRegDeps = bbEnd->getChild(0);

gotoTreeTop->getNode()->setNumChildren(1);
gotoTreeTop->getNode()->setChild(0, glRegDeps);

bbEnd->setChild(0,NULL);
bbEnd->setNumChildren(0);
}

tt->insertAfter(gotoTreeTop);
}
}

void OMR::CodeGenerator::prepareLastWarmBlockForCodeSplitting()
{
TR::Compilation *comp = self()->comp();
TR::TreeTop * tt;
Expand Down Expand Up @@ -457,62 +529,18 @@ void OMR::CodeGenerator::findLastWarmBlock()
(numColdBlocks - numNonOutlinedColdBlocks)*100/numColdBlocks);
}

// If the last tree in the last warm block is not a TR_goto, insert a goto tree
// at the end of the block.
// If there is a following block the goto will branch to it so that when the
// code is split any fall-through will go to the right place.
// If there is no following block the goto will branch to the first block; in
// this case the goto should never be reached, it is there only to
// make sure that the instruction following the last real treetop will be in
// warm code, so if it is a helper call (e.g. for a throw) the return address
// is in this method's code.
//
if (lastWarmBlock->getNumberOfRealTreeTops() == 0)
tt = lastWarmBlock->getEntry();
else
tt = lastWarmBlock->getLastRealTreeTop();

node = tt->getNode();
insertGotoIntoLastBlock(lastWarmBlock);
TR::Block *lastBlock = comp->findLastTree()->getNode()->getBlock();

if (!(node->getOpCode().isGoto() ||
node->getOpCode().isJumpWithMultipleTargets() ||
node->getOpCode().isReturn()))
// If disclaim is enabled, it may happen that nothing follows mainline code
// (no snippets or OOL). Then, we need to insert a goto at the end for the
// reasons described in insertGotoIntoLastBlock()
//
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableCodeCacheDisclaiming) &&
lastBlock != lastWarmBlock)
{
// Find the block to be branched to
//
TR::TreeTop * targetTreeTop = lastWarmBlock->getExit()->getNextTreeTop();

if (targetTreeTop)
// Branch to following block. Make sure it is not marked as an
// extension block so that it will get a label generated.
//
targetTreeTop->getNode()->getBlock()->setIsExtensionOfPreviousBlock(false);
else
// Branch to the first block. This will not be marked as an extension
// block.
//
targetTreeTop = comp->getStartBlock()->getEntry();

// Generate the goto and insert it into the end of the last warm block.
//
TR::TreeTop *gotoTreeTop = TR::TreeTop::create(comp, TR::Node::create(node, TR::Goto, 0, targetTreeTop));

// Move reg deps from BBEnd to goto
//
TR::Node *bbEnd = lastWarmBlock->getExit()->getNode();

if (bbEnd->getNumChildren() > 0)
{
TR::Node *glRegDeps = bbEnd->getChild(0);

gotoTreeTop->getNode()->setNumChildren(1);
gotoTreeTop->getNode()->setChild(0, glRegDeps);

bbEnd->setChild(0,NULL);
bbEnd->setNumChildren(0);
}

tt->insertAfter(gotoTreeTop);
insertGotoIntoLastBlock(lastBlock);
}
}

Expand Down Expand Up @@ -570,7 +598,7 @@ void OMR::CodeGenerator::postLowerTrees()
if (comp()->getOption(TR_SplitWarmAndColdBlocks) &&
!comp()->compileRelocatableCode())
{
self()->findLastWarmBlock();
self()->prepareLastWarmBlockForCodeSplitting();
}
}

Expand Down
11 changes: 10 additions & 1 deletion compiler/codegen/OMRCodeGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,16 @@ class OMR_EXTENSIBLE CodeGenerator

void lowerTreesPropagateBlockToNode(TR::Node *node);

void findLastWarmBlock();
/**
* @brief Inserts goto into the last block if necessary
*/
void insertGotoIntoLastBlock(TR::Block *lastBlock);

/**
* @brief Finds last warm block and inserts necessary gotos
* for splitting code into warm and cold
*/
void prepareLastWarmBlockForCodeSplitting();

void setUpForInstructionSelection();
void doInstructionSelection();
Expand Down
2 changes: 2 additions & 0 deletions compiler/control/OMROptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,9 @@ TR::OptionTable OMR::Options::_jitOptions[] = {
{"minSleepTimeMsForCompThrottling=", "M<nnn>\tLower bound for sleep time during compilation throttling (ms)",
TR::Options::setStaticNumeric, (intptr_t)&OMR::Options::_minSleepTimeMsForCompThrottling, 0, "F%d", NOT_IN_SUBSET },
{"moveOOLInstructionsToWarmCode", "M\tmove out-of-line instructions to after last warm instruction", SET_OPTION_BIT(TR_MoveOOLInstructionsToWarmCode), "F"},
{"moveSnippetsToWarmCode", "M\tmove snippets to after last warm instruction", SET_OPTION_BIT(TR_MoveSnippetsToWarmCode), "F"},
{"noAotSecondRunDetection", "M\tdo not do second run detection for AOT", SET_OPTION_BIT(TR_NoAotSecondRunDetection), "F", NOT_IN_SUBSET },

#ifdef DEBUG
{"noExceptions", "C\tfail compilation for methods with exceptions",
TR::Options::setDebug, (intptr_t)"noExceptions"},
Expand Down
2 changes: 1 addition & 1 deletion compiler/control/OMROptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ enum TR_CompilationOptions
TR_DisableInliningUnrecognizedIntrinsics = 0x10000000 + 9,
TR_EnableVectorAPIExpansion = 0x20000000 + 9,
TR_MoveOOLInstructionsToWarmCode = 0x40000000 + 9,
// Available = 0x80000000 + 9,
TR_MoveSnippetsToWarmCode = 0x80000000 + 9,

// Option word 10
//
Expand Down
18 changes: 17 additions & 1 deletion compiler/x/codegen/OMRCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2059,6 +2059,8 @@ void OMR::X86::CodeGenerator::doBinaryEncoding()
//
bool skipOneReturn = false;
int32_t estimatedPrologueStartOffset = estimate;
bool snippetsAfterWarm = self()->comp()->getOption(TR_MoveSnippetsToWarmCode);

while (estimateCursor)
{
// Update the info bits on the register mask.
Expand Down Expand Up @@ -2152,6 +2154,9 @@ void OMR::X86::CodeGenerator::doBinaryEncoding()
//
if (estimateCursor->isLastWarmInstruction())
{
if (snippetsAfterWarm)
estimate = setEstimatedLocationsForSnippetLabels(estimate);

warmEstimate = (estimate+7) & ~7;
estimate = warmEstimate + MIN_DISTANCE_BETWEEN_WARM_AND_COLD_CODE;
}
Expand All @@ -2165,7 +2170,8 @@ void OMR::X86::CodeGenerator::doBinaryEncoding()
if (self()->comp()->getOption(TR_TraceCG))
traceMsg(self()->comp(), "\n</instructions>\n");

estimate = self()->setEstimatedLocationsForSnippetLabels(estimate);
if (!snippetsAfterWarm || !warmEstimate)
estimate = self()->setEstimatedLocationsForSnippetLabels(estimate);

// When using copyBinaryToBuffer() to copy the encoding of an instruction we
// indiscriminatelly copy a whole integer, even if the size of the encoding
Expand Down Expand Up @@ -2240,6 +2246,8 @@ void OMR::X86::CodeGenerator::doBinaryEncoding()

// Generate binary for the rest of the instructions
//
int32_t accumulatedErrorBeforeSnippets = 0;

while (cursorInstruction)
{
uint8_t * const instructionStart = self()->getBinaryBufferCursor();
Expand Down Expand Up @@ -2279,6 +2287,8 @@ void OMR::X86::CodeGenerator::doBinaryEncoding()
self()->getWarmCodeEnd(), cursorInstruction, coldCode);
}

accumulatedErrorBeforeSnippets = getAccumulatedInstructionLengthError();

// Adjust the accumulated length error so that distances within the cold
// code are calculated properly using the estimated code locations.
//
Expand Down Expand Up @@ -2328,6 +2338,12 @@ void OMR::X86::CodeGenerator::doBinaryEncoding()
traceMsg(self()->comp(), "</encode>\n");
}

if (self()->comp()->getOption(TR_SplitWarmAndColdBlocks))
{
if (snippetsAfterWarm) // snippets will follow the warm code
setAccumulatedInstructionLengthError(accumulatedErrorBeforeSnippets);
}

}

// different from evaluate in that it returns a clobberable register
Expand Down

0 comments on commit dc1ec39

Please sign in to comment.