Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions src/coreclr/jit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ set( JIT_SOURCES
promotiondecomposition.cpp
promotionliveness.cpp
rangecheck.cpp
rangecheckcloning.cpp
rationalize.cpp
redundantbranchopts.cpp
regalloc.cpp
Expand Down Expand Up @@ -356,6 +357,7 @@ set( JIT_HEADERS
priorityqueue.h
promotion.h
rangecheck.h
rangecheckcloning.h
rationalize.h
regalloc.h
registerargconvention.h
Expand Down
7 changes: 4 additions & 3 deletions src/coreclr/jit/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -464,13 +464,14 @@ enum BasicBlockFlags : uint64_t
BBF_HAS_VALUE_PROFILE = MAKE_BBFLAG(39), // Block has a node that needs a value probing

BBF_HAS_NEWARR = MAKE_BBFLAG(40), // BB contains 'new' of an array type.
BBF_MAY_HAVE_BOUNDS_CHECKS = MAKE_BBFLAG(41), // BB *likely* has a bounds check (after rangecheck phase).

// The following are sets of flags.

// Flags to update when two blocks are compacted

BBF_COMPACT_UPD = BBF_GC_SAFE_POINT | BBF_NEEDS_GCPOLL | BBF_HAS_JMP | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_BACKWARD_JUMP | \
BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_MDARRAYREF | BBF_LOOP_HEAD,
BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_MDARRAYREF | BBF_LOOP_HEAD | BBF_MAY_HAVE_BOUNDS_CHECKS,

// Flags a block should not have had before it is split.

Expand All @@ -489,14 +490,14 @@ enum BasicBlockFlags : uint64_t
// TODO: Should BBF_RUN_RARELY be added to BBF_SPLIT_GAINED ?

BBF_SPLIT_GAINED = BBF_DONT_REMOVE | BBF_HAS_JMP | BBF_BACKWARD_JUMP | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_PROF_WEIGHT | BBF_HAS_NEWARR | \
BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_NULLCHECK | BBF_HAS_HISTOGRAM_PROFILE | BBF_HAS_VALUE_PROFILE | BBF_HAS_MDARRAYREF | BBF_NEEDS_GCPOLL,
BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_NULLCHECK | BBF_HAS_HISTOGRAM_PROFILE | BBF_HAS_VALUE_PROFILE | BBF_HAS_MDARRAYREF | BBF_NEEDS_GCPOLL | BBF_MAY_HAVE_BOUNDS_CHECKS,

// Flags that must be propagated to a new block if code is copied from a block to a new block. These are flags that
// limit processing of a block if the code in question doesn't exist. This is conservative; we might not
// have actually copied one of these type of tree nodes, but if we only copy a portion of the block's statements,
// we don't know (unless we actually pay close attention during the copy).

BBF_COPY_PROPAGATE = BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_HAS_MDARRAYREF,
BBF_COPY_PROPAGATE = BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS,
};

FORCEINLINE
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4929,6 +4929,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
bool doAssertionProp = true;
bool doVNBasedIntrinExpansion = true;
bool doRangeAnalysis = true;
bool doRangeCheckCloning = true;
bool doVNBasedDeadStoreRemoval = true;

#if defined(OPT_CONFIG)
Expand All @@ -4941,6 +4942,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
doCse = doValueNum;
doAssertionProp = doValueNum && (JitConfig.JitDoAssertionProp() != 0);
doRangeAnalysis = doAssertionProp && (JitConfig.JitDoRangeAnalysis() != 0);
doRangeCheckCloning = doValueNum && doRangeAnalysis;
doOptimizeIVs = doAssertionProp && (JitConfig.JitDoOptimizeIVs() != 0);
doVNBasedDeadStoreRemoval = doValueNum && (JitConfig.JitDoVNBasedDeadStoreRemoval() != 0);
doVNBasedIntrinExpansion = doValueNum;
Expand Down Expand Up @@ -5053,6 +5055,13 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
DoPhase(this, PHASE_VN_BASED_DEAD_STORE_REMOVAL, &Compiler::optVNBasedDeadStoreRemoval);
}

if (doRangeCheckCloning)
{
// Clone blocks with subsequent bounds checks
//
DoPhase(this, PHASE_RANGE_CHECK_CLONING, &Compiler::optRangeCheckCloning);
}

if (doVNBasedIntrinExpansion)
{
// Expand some intrinsics based on VN data
Expand Down
10 changes: 6 additions & 4 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ void* operator new[](size_t n, Compiler* context, CompMemKind cmk);

// Requires the definitions of "operator new" so including "LoopCloning.h" after the definitions.
#include "loopcloning.h"
#include "rangecheckcloning.h"

/*****************************************************************************/

Expand Down Expand Up @@ -3809,7 +3810,7 @@ class Compiler
bool gtStoreDefinesField(
LclVarDsc* fieldVarDsc, ssize_t offset, unsigned size, ssize_t* pFieldStoreOffset, unsigned* pFieldStoreSize);

void gtPeelOffsets(GenTree** addr, target_ssize_t* offset, FieldSeq** fldSeq = nullptr);
void gtPeelOffsets(GenTree** addr, target_ssize_t* offset, FieldSeq** fldSeq = nullptr) const;

// Return true if call is a recursive call; return false otherwise.
// Note when inlining, this looks for calls back to the root method.
Expand Down Expand Up @@ -6669,12 +6670,12 @@ class Compiler
void fgInsertStmtAfter(BasicBlock* block, Statement* insertionPoint, Statement* stmt);
void fgInsertStmtBefore(BasicBlock* block, Statement* insertionPoint, Statement* stmt);

private:
Statement* fgInsertStmtListAfter(BasicBlock* block, Statement* stmtAfter, Statement* stmtList);

// Create a new temporary variable to hold the result of *ppTree,
// and transform the graph accordingly.
GenTree* fgInsertCommaFormTemp(GenTree** ppTree);

private:
Statement* fgInsertStmtListAfter(BasicBlock* block, Statement* stmtAfter, Statement* stmtList);
TempInfo fgMakeTemp(GenTree* value);
GenTree* fgMakeMultiUse(GenTree** ppTree);

Expand Down Expand Up @@ -7219,6 +7220,7 @@ class Compiler
bool optCanonicalizeExit(FlowGraphNaturalLoop* loop, BasicBlock* exit);

PhaseStatus optCloneLoops();
PhaseStatus optRangeCheckCloning();
bool optShouldCloneLoop(FlowGraphNaturalLoop* loop, LoopCloneContext* context);
void optCloneLoop(FlowGraphNaturalLoop* loop, LoopCloneContext* context);
PhaseStatus optUnrollLoops(); // Unrolls loops (needs to have cost info)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compmemkind.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ CompMemKindMacro(ZeroInit)
CompMemKindMacro(Pgo)
CompMemKindMacro(MaskConversionOpt)
CompMemKindMacro(TryRegionClone)
CompMemKindMacro(RangeCheckCloning)
//clang-format on

#undef CompMemKindMacro
1 change: 1 addition & 0 deletions src/coreclr/jit/compphases.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ CompPhaseNameMacro(PHASE_VN_COPY_PROP, "VN based copy prop",
CompPhaseNameMacro(PHASE_VN_BASED_INTRINSIC_EXPAND, "VN based intrinsic expansion", false, -1, false)
CompPhaseNameMacro(PHASE_OPTIMIZE_BRANCHES, "Redundant branch opts", false, -1, false)
CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", false, -1, false)
CompPhaseNameMacro(PHASE_RANGE_CHECK_CLONING, "Clone blocks with range checks", false, -1, false)
CompPhaseNameMacro(PHASE_IF_CONVERSION, "If conversion", false, -1, false)
CompPhaseNameMacro(PHASE_VN_BASED_DEAD_STORE_REMOVAL,"VN-based dead store removal", false, -1, false)
CompPhaseNameMacro(PHASE_EMPTY_FINALLY_3, "Remove empty finally 3", false, -1, false)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/promotiondecomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ class DecompositionPlan
// offset - [out] The sum of offset peeled such that ADD(addr, offset) is equivalent to the original addr.
// fldSeq - [out, optional] The combined field sequence for all the peeled offsets.
//
void Compiler::gtPeelOffsets(GenTree** addr, target_ssize_t* offset, FieldSeq** fldSeq)
void Compiler::gtPeelOffsets(GenTree** addr, target_ssize_t* offset, FieldSeq** fldSeq) const
{
assert((*addr)->TypeIs(TYP_I_IMPL, TYP_BYREF, TYP_REF));
*offset = 0;
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/jit/rangecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,14 @@ bool RangeCheck::OptimizeRangeChecks()
return madeChanges;
}

if (tree->OperIs(GT_BOUNDS_CHECK))
{
// Leave a hint for optRangeCheckCloning to improve the JIT TP.
// NOTE: it doesn't have to be precise and being properly maintained
// during transformations, it's just a hint.
block->SetFlags(BBF_MAY_HAVE_BOUNDS_CHECKS);
}

OptimizeRangeCheck(block, stmt, tree);
}

Expand Down
Loading