Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6058,29 +6058,26 @@ Statement* Compiler::optVNAssertionPropCurStmt(BasicBlock* block, Statement* stm
return nextStmt;
}

/*****************************************************************************
*
* The entry point for assertion propagation
*/

void Compiler::optAssertionPropMain()
//------------------------------------------------------------------------------
// optAssertionPropMain: assertion propagation phase
//
// Returns:
// Suitable phase status.
//
PhaseStatus Compiler::optAssertionPropMain()
{
if (fgSsaPassesCompleted == 0)
{
return;
}
#ifdef DEBUG
if (verbose)
{
printf("*************** In optAssertionPropMain()\n");
printf("Blocks/Trees at start of phase\n");
fgDispBasicBlocks(true);
return PhaseStatus::MODIFIED_NOTHING;
}
#endif

optAssertionInit(false);

noway_assert(optAssertionCount == 0);
bool madeChanges = false;

// Assertion prop can speculatively create trees.
INDEBUG(const unsigned baseTreeID = compGenTreeID);

// First discover all value assignments and record them in the table.
for (BasicBlock* const block : Blocks())
Expand All @@ -6096,13 +6093,16 @@ void Compiler::optAssertionPropMain()
if (fgRemoveRestOfBlock)
{
fgRemoveStmt(block, stmt);
stmt = stmt->GetNextStmt();
stmt = stmt->GetNextStmt();
madeChanges = true;
continue;
}
else
{
// Perform VN based assertion prop before assertion gen.
Statement* nextStmt = optVNAssertionPropCurStmt(block, stmt);
madeChanges |= optAssertionPropagatedCurrentStmt;
INDEBUG(madeChanges |= (baseTreeID != compGenTreeID));

// Propagation resulted in removal of the remaining stmts, perform it.
if (fgRemoveRestOfBlock)
Expand Down Expand Up @@ -6139,7 +6139,7 @@ void Compiler::optAssertionPropMain()
{
block->bbAssertionIn = BitVecOps::MakeEmpty(apTraits);
}
return;
return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING;
}

#ifdef DEBUG
Expand Down Expand Up @@ -6209,7 +6209,8 @@ void Compiler::optAssertionPropMain()
if (fgRemoveRestOfBlock)
{
fgRemoveStmt(block, stmt);
stmt = stmt->GetNextStmt();
stmt = stmt->GetNextStmt();
madeChanges = true;
continue;
}

Expand Down Expand Up @@ -6255,6 +6256,7 @@ void Compiler::optAssertionPropMain()
#endif
// Re-morph the statement.
fgMorphBlockStmt(block, stmt DEBUGARG("optAssertionPropMain"));
madeChanges = true;
}

// Check if propagation removed statements starting from current stmt.
Expand All @@ -6265,8 +6267,5 @@ void Compiler::optAssertionPropMain()
optAssertionPropagatedCurrentStmt = false; // clear it back as we are done with stmts.
}

#ifdef DEBUG
fgDebugCheckBBlist();
fgDebugCheckLinks();
#endif
return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING;
}
54 changes: 32 additions & 22 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1838,8 +1838,9 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
// Initialize this to the first phase to run.
mostRecentlyActivePhase = PHASE_PRE_IMPORT;

// Initially, no phase checks are active.
// Initially, no phase checks are active, and all dumps are enabled.
activePhaseChecks = PhaseChecks::CHECK_NONE;
activePhaseDumps = PhaseDumps::DUMP_ALL;

#ifdef FEATURE_TRACELOGGING
// Make sure JIT telemetry is initialized as soon as allocations can be made
Expand Down Expand Up @@ -4786,20 +4787,17 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl

if (doRangeAnalysis)
{
auto rangePhase = [this]() {
RangeCheck rc(this);
rc.OptimizeRangeChecks();
};

// Bounds check elimination via range analysis
//
DoPhase(this, PHASE_OPTIMIZE_INDEX_CHECKS, rangePhase);
DoPhase(this, PHASE_OPTIMIZE_INDEX_CHECKS, &Compiler::rangeCheckPhase);
}

if (fgModified)
{
// update the flowgraph if we modified it during the optimization phase
//
// Note: this invalidates loops, dominators and reachability
//
DoPhase(this, PHASE_OPT_UPDATE_FLOW_GRAPH, &Compiler::fgUpdateFlowGraphPhase);

// Recompute the edge weight if we have modified the flow graph
Expand All @@ -4817,11 +4815,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
}
}

#ifdef DEBUG
// Run this before we potentially tear down dominators.
fgDebugCheckLinks(compStressCompile(STRESS_REMORPH_TREES, 50));
#endif

// Dominator and reachability sets are no longer valid.
// The loop table is no longer valid.
fgDomsComputed = false;
Expand Down Expand Up @@ -4918,6 +4911,11 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
DoPhase(this, PHASE_ALIGN_LOOPS, &Compiler::placeLoopAlignInstructions);
#endif

// The common phase checks and dumps are no longer relevant past this point.
//
activePhaseChecks = PhaseChecks::CHECK_NONE;
activePhaseDumps = PhaseDumps::DUMP_NONE;

// Generate code
codeGen->genGenerateCode(methodCodePtr, methodCodeSize);

Expand Down Expand Up @@ -4977,25 +4975,32 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
#if FEATURE_LOOP_ALIGN

//------------------------------------------------------------------------
// placeLoopAlignInstructions: Iterate over all the blocks and determine
// the best position to place the 'align' instruction. Inserting 'align'
// instructions after an unconditional branch is preferred over inserting
// in the block before the loop. In case there are multiple blocks
// having 'jmp', the one that has lower weight is preferred.
// If the block having 'jmp' is hotter than the block before the loop,
// the align will still be placed after 'jmp' because the processor should
// be smart enough to not fetch extra instruction beyond jmp.
// placeLoopAlignInstructions: determine where to place alignment padding
//
// Returns:
// Suitable phase status
//
void Compiler::placeLoopAlignInstructions()
// Notes:
// Iterate over all the blocks and determine
// the best position to place the 'align' instruction. Inserting 'align'
// instructions after an unconditional branch is preferred over inserting
// in the block before the loop. In case there are multiple blocks
// having 'jmp', the one that has lower weight is preferred.
// If the block having 'jmp' is hotter than the block before the loop,
// the align will still be placed after 'jmp' because the processor should
// be smart enough to not fetch extra instruction beyond jmp.
//
PhaseStatus Compiler::placeLoopAlignInstructions()
{
if (loopAlignCandidates == 0)
{
return;
return PhaseStatus::MODIFIED_NOTHING;
}

JITDUMP("Inside placeLoopAlignInstructions for %d loops.\n", loopAlignCandidates);

// Add align only if there were any loops that needed alignment
bool madeChanges = false;
weight_t minBlockSoFar = BB_MAX_WEIGHT;
BasicBlock* bbHavingAlign = nullptr;
BasicBlock::loopNumber currentAlignedLoopNum = BasicBlock::NOT_IN_LOOP;
Expand All @@ -5005,6 +5010,7 @@ void Compiler::placeLoopAlignInstructions()
// Adding align instruction in prolog is not supported
// hence just remove that loop from our list.
fgFirstBB->unmarkLoopAlign(this DEBUG_ARG("prolog block"));
madeChanges = true;
}

int loopsToProcess = loopAlignCandidates;
Expand Down Expand Up @@ -5053,6 +5059,7 @@ void Compiler::placeLoopAlignInstructions()
if ((block->bbNatLoopNum != BasicBlock::NOT_IN_LOOP) && (block->bbNatLoopNum == loopTop->bbNatLoopNum))
{
loopTop->unmarkLoopAlign(this DEBUG_ARG("loop block appears before top of loop"));
madeChanges = true;
}
else
{
Expand All @@ -5070,6 +5077,7 @@ void Compiler::placeLoopAlignInstructions()

if (bbHavingAlign != nullptr)
{
madeChanges = true;
bbHavingAlign->bbFlags |= BBF_HAS_ALIGN;
}

Expand All @@ -5085,6 +5093,8 @@ void Compiler::placeLoopAlignInstructions()
}

assert(loopsToProcess == 0);

return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING;
}
#endif

Expand Down
45 changes: 29 additions & 16 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1377,11 +1377,20 @@ class TempDsc
}
};

// Specify compiler data that a phase might modify
enum class PhaseStatus : unsigned
{
MODIFIED_NOTHING, // Phase did not make any changes that warrant running post-phase checks or dumping
// the main jit data strutures.
MODIFIED_EVERYTHING, // Phase made changes that warrant running post-phase checks or dumping
// the main jit data strutures.
};

// interface to hide linearscan implementation from rest of compiler
class LinearScanInterface
{
public:
virtual void doLinearScan() = 0;
virtual PhaseStatus doLinearScan() = 0;
virtual void recordVarLocationsAtStartOfBB(BasicBlock* bb) = 0;
virtual bool willEnregisterLocalVars() const = 0;
#if TRACK_LSRA_STATS
Expand Down Expand Up @@ -1413,13 +1422,12 @@ enum class PhaseChecks
CHECK_ALL
};

// Specify compiler data that a phase might modify
enum class PhaseStatus : unsigned
// Specify which dumps should be run after each phase
//
enum class PhaseDumps
{
MODIFIED_NOTHING, // Phase did not make any changes that warrant running post-phase checks or dumping
// the main jit data strutures.
MODIFIED_EVERYTHING, // Phase made changes that warrant running post-phase checks or dumping
// the main jit data strutures.
DUMP_NONE,
DUMP_ALL
};

// The following enum provides a simple 1:1 mapping to CLR API's
Expand Down Expand Up @@ -2927,7 +2935,6 @@ class Compiler
#endif

BasicBlock* bbNewBasicBlock(BBjumpKinds jumpKind);
void placeLoopAlignInstructions();

/*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Expand Down Expand Up @@ -4635,7 +4642,11 @@ class Compiler

// Do "simple lowering." This functionality is (conceptually) part of "general"
// lowering that is distributed between fgMorph and the lowering phase of LSRA.
void fgSimpleLowering();
PhaseStatus fgSimpleLowering();

#if FEATURE_LOOP_ALIGN
PhaseStatus placeLoopAlignInstructions();
#endif

GenTree* fgInitThisClass();

Expand Down Expand Up @@ -5046,7 +5057,7 @@ class Compiler
template <typename CanRemoveBlockBody>
bool fgRemoveUnreachableBlocks(CanRemoveBlockBody canRemoveBlock);

void fgComputeReachability(); // Perform flow graph node reachability analysis.
PhaseStatus fgComputeReachability(); // Perform flow graph node reachability analysis.

bool fgRemoveDeadBlocks(); // Identify and remove dead blocks.

Expand Down Expand Up @@ -5960,6 +5971,7 @@ class Compiler
public:
void optInit();

PhaseStatus rangeCheckPhase();
GenTree* optRemoveRangeCheck(GenTreeBoundsChk* check, GenTree* comma, Statement* stmt);
GenTree* optRemoveStandaloneRangeCheck(GenTreeBoundsChk* check, Statement* stmt);
void optRemoveCommaBasedRangeCheck(GenTree* comma, Statement* stmt);
Expand Down Expand Up @@ -6695,7 +6707,7 @@ class Compiler
#define FMT_CSE "CSE #%02u"

public:
void optOptimizeValnumCSEs();
PhaseStatus optOptimizeValnumCSEs();

protected:
void optValnumCSE_Init();
Expand All @@ -6704,7 +6716,7 @@ class Compiler
void optValnumCSE_InitDataFlow();
void optValnumCSE_DataFlow();
void optValnumCSE_Availability();
void optValnumCSE_Heuristic();
bool optValnumCSE_Heuristic();

bool optDoCSE; // True when we have found a duplicate CSE tree
bool optValnumCSE_phase; // True when we are executing the optOptimizeValnumCSEs() phase
Expand Down Expand Up @@ -6777,16 +6789,16 @@ class Compiler
typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, CopyPropSsaDefStack*> LclNumToLiveDefsMap;

// Copy propagation functions.
void optCopyProp(Statement* stmt, GenTreeLclVarCommon* tree, unsigned lclNum, LclNumToLiveDefsMap* curSsaName);
bool optCopyProp(Statement* stmt, GenTreeLclVarCommon* tree, unsigned lclNum, LclNumToLiveDefsMap* curSsaName);
void optBlockCopyPropPopStacks(BasicBlock* block, LclNumToLiveDefsMap* curSsaName);
void optBlockCopyProp(BasicBlock* block, LclNumToLiveDefsMap* curSsaName);
bool optBlockCopyProp(BasicBlock* block, LclNumToLiveDefsMap* curSsaName);
void optCopyPropPushDef(GenTree* defNode,
GenTreeLclVarCommon* lclNode,
unsigned lclNum,
LclNumToLiveDefsMap* curSsaName);
unsigned optIsSsaLocal(GenTreeLclVarCommon* lclNode);
int optCopyProp_LclVarScore(const LclVarDsc* lclVarDsc, const LclVarDsc* copyVarDsc, bool preferOp2);
void optVnCopyProp();
PhaseStatus optVnCopyProp();
INDEBUG(void optDumpCopyPropStack(LclNumToLiveDefsMap* curSsaName));

/**************************************************************************
Expand Down Expand Up @@ -7289,7 +7301,7 @@ class Compiler
void optAssertionRemove(AssertionIndex index);

// Assertion prop data flow functions.
void optAssertionPropMain();
PhaseStatus optAssertionPropMain();
Statement* optVNAssertionPropCurStmt(BasicBlock* block, Statement* stmt);
bool optIsTreeKnownIntValue(bool vnBased, GenTree* tree, ssize_t* pConstant, GenTreeFlags* pIconFlags);
ASSERT_TP* optInitAssertionDataflowFlags();
Expand Down Expand Up @@ -9874,6 +9886,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Phases mostRecentlyActivePhase; // the most recently active phase
PhaseChecks activePhaseChecks; // the currently active phase checks
PhaseDumps activePhaseDumps; // the currently active phase dumps

//-------------------------------------------------------------------------
// The following keeps track of how many bytes of local frame space we've
Expand Down
Loading