Skip to content

Commit 7ccf491

Browse files
authored
JIT: enable removal of try/catch if the try can't throw. (#110273)
If no tree in the try region of a try/catch can throw, then we can remove the try and delete the catch. If no tree in the try region of a try/finally can throw, we can remove the try and inline the finally. This slightly generalizes the empty-try/finally opt we have been doing for a long time. (We should do something similar for try/fault, but don't, yet). Since these optimization passes are cheap, and opportunities for them arise after other optimizations and unblock subsequent optimizations, run them early, middle, and late. Resolves #107191. I expect we'll see more of these cases in the future, say if we unblock cloning of loops with EH.
1 parent 5b9b8d3 commit 7ccf491

File tree

7 files changed

+501
-94
lines changed

7 files changed

+501
-94
lines changed

src/coreclr/jit/compiler.cpp

+27-2
Original file line numberDiff line numberDiff line change
@@ -4637,10 +4637,14 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
46374637
DoPhase(this, PHASE_SWIFT_ERROR_RET, &Compiler::fgAddSwiftErrorReturns);
46384638
#endif // SWIFT_SUPPORT
46394639

4640-
// Remove empty try regions
4640+
// Remove empty try regions (try/finally)
46414641
//
46424642
DoPhase(this, PHASE_EMPTY_TRY, &Compiler::fgRemoveEmptyTry);
46434643

4644+
// Remove empty try regions (try/catch)
4645+
//
4646+
DoPhase(this, PHASE_EMPTY_TRY_CATCH, &Compiler::fgRemoveEmptyTryCatch);
4647+
46444648
// Remove empty finally regions
46454649
//
46464650
DoPhase(this, PHASE_EMPTY_FINALLY, &Compiler::fgRemoveEmptyFinally);
@@ -4810,6 +4814,18 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
48104814
//
48114815
DoPhase(this, PHASE_UNROLL_LOOPS, &Compiler::optUnrollLoops);
48124816

4817+
// Try again to remove empty try finally/fault clauses
4818+
//
4819+
DoPhase(this, PHASE_EMPTY_FINALLY_2, &Compiler::fgRemoveEmptyFinally);
4820+
4821+
// Remove empty try regions (try/finally)
4822+
//
4823+
DoPhase(this, PHASE_EMPTY_TRY_2, &Compiler::fgRemoveEmptyTry);
4824+
4825+
// Remove empty try regions (try/catch)
4826+
//
4827+
DoPhase(this, PHASE_EMPTY_TRY_CATCH_2, &Compiler::fgRemoveEmptyTryCatch);
4828+
48134829
// Compute dominators and exceptional entry blocks
48144830
//
48154831
DoPhase(this, PHASE_COMPUTE_DOMINATORS, &Compiler::fgComputeDominators);
@@ -5039,7 +5055,16 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
50395055
#endif
50405056

50415057
// Try again to remove empty try finally/fault clauses
5042-
DoPhase(this, PHASE_EMPTY_FINALLY_2, &Compiler::fgRemoveEmptyFinally);
5058+
//
5059+
DoPhase(this, PHASE_EMPTY_FINALLY_3, &Compiler::fgRemoveEmptyFinally);
5060+
5061+
// Remove empty try regions (try/finally)
5062+
//
5063+
DoPhase(this, PHASE_EMPTY_TRY_3, &Compiler::fgRemoveEmptyTry);
5064+
5065+
// Remove empty try regions (try/catch)
5066+
//
5067+
DoPhase(this, PHASE_EMPTY_TRY_CATCH_3, &Compiler::fgRemoveEmptyTryCatch);
50435068

50445069
if (UsesFunclets())
50455070
{

src/coreclr/jit/compiler.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -5270,7 +5270,6 @@ class Compiler
52705270

52715271
bool fgModified = false; // True if the flow graph has been modified recently
52725272
bool fgPredsComputed = false; // Have we computed the bbPreds list
5273-
bool fgOptimizedFinally = false; // Did we optimize any try-finallys?
52745273

52755274
bool fgHasSwitch = false; // any BBJ_SWITCH jumps?
52765275

@@ -5352,12 +5351,16 @@ class Compiler
53525351

53535352
PhaseStatus fgRemoveEmptyTry();
53545353

5354+
PhaseStatus fgRemoveEmptyTryCatch();
5355+
53555356
PhaseStatus fgRemoveEmptyFinally();
53565357

53575358
PhaseStatus fgMergeFinallyChains();
53585359

53595360
PhaseStatus fgCloneFinally();
53605361

5362+
void fgUpdateACDsBeforeEHTableEntryRemoval(unsigned XTnum);
5363+
53615364
void fgCleanupContinuation(BasicBlock* continuation);
53625365

53635366
PhaseStatus fgTailMergeThrows();

src/coreclr/jit/compphases.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ CompPhaseNameMacro(PHASE_MORPH_ADD_INTERNAL, "Morph - Add internal block
3737
CompPhaseNameMacro(PHASE_SWIFT_ERROR_RET, "Add Swift error returns", false, -1, true)
3838
CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", false, -1, false)
3939
CompPhaseNameMacro(PHASE_EMPTY_TRY, "Remove empty try", false, -1, false)
40+
CompPhaseNameMacro(PHASE_EMPTY_TRY_CATCH, "Remove empty try/catch", false, -1, false)
4041
CompPhaseNameMacro(PHASE_EMPTY_FINALLY, "Remove empty finally", false, -1, false)
4142
CompPhaseNameMacro(PHASE_MERGE_FINALLY_CHAINS, "Merge callfinally chains", false, -1, false)
4243
CompPhaseNameMacro(PHASE_CLONE_FINALLY, "Clone finally", false, -1, false)
@@ -74,6 +75,9 @@ CompPhaseNameMacro(PHASE_FIND_LOOPS, "Find loops",
7475
CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", false, -1, false)
7576
CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", false, -1, false)
7677
CompPhaseNameMacro(PHASE_MORPH_MDARR, "Morph array ops", false, -1, false)
78+
CompPhaseNameMacro(PHASE_EMPTY_FINALLY_2, "Remove empty finally 2", false, -1, false)
79+
CompPhaseNameMacro(PHASE_EMPTY_TRY_2, "Remove empty try 2", false, -1, false)
80+
CompPhaseNameMacro(PHASE_EMPTY_TRY_CATCH_2, "Remove empty try-catch 2", false, -1, false)
7781
CompPhaseNameMacro(PHASE_HOIST_LOOP_CODE, "Hoist loop code", false, -1, false)
7882
CompPhaseNameMacro(PHASE_MARK_LOCAL_VARS, "Mark local vars", false, -1, false)
7983
CompPhaseNameMacro(PHASE_OPTIMIZE_BOOLS, "Optimize bools", false, -1, false)
@@ -96,7 +100,9 @@ CompPhaseNameMacro(PHASE_OPTIMIZE_BRANCHES, "Redundant branch opts",
96100
CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", false, -1, false)
97101
CompPhaseNameMacro(PHASE_IF_CONVERSION, "If conversion", false, -1, false)
98102
CompPhaseNameMacro(PHASE_VN_BASED_DEAD_STORE_REMOVAL,"VN-based dead store removal", false, -1, false)
99-
CompPhaseNameMacro(PHASE_EMPTY_FINALLY_2, "Remove empty finally 2", false, -1, false)
103+
CompPhaseNameMacro(PHASE_EMPTY_FINALLY_3, "Remove empty finally 3", false, -1, false)
104+
CompPhaseNameMacro(PHASE_EMPTY_TRY_3, "Remove empty try 3", false, -1, false)
105+
CompPhaseNameMacro(PHASE_EMPTY_TRY_CATCH_3, "Remove empty try-catch 3", false, -1, false)
100106
CompPhaseNameMacro(PHASE_OPT_UPDATE_FLOW_GRAPH, "Update flow graph opt pass", false, -1, false)
101107
CompPhaseNameMacro(PHASE_STRESS_SPLIT_TREE, "Stress gtSplitTree", false, -1, false)
102108
CompPhaseNameMacro(PHASE_EXPAND_RTLOOKUPS, "Expand runtime lookups", false, -1, true)

0 commit comments

Comments
 (0)