bool fgComputePredsDone; // Have we computed the bbPreds list
bool fgCheapPredsValid; // Is the bbCheapPreds list valid?
bool fgDomsComputed; // Have we computed the dominator sets?
+ bool fgOptimizedFinally; // Did we optimize any try-finallys?
bool fgHasSwitch; // any BBJ_SWITCH jumps?
bool fgHasPostfix; // any postfix ++/-- found?
void fgCleanupContinuation(BasicBlock* continuation);
+ void fgUpdateFinallyTargetFlags();
+
GenTreePtr fgGetCritSectOfStaticMethod();
#if !defined(_TARGET_X86_)
if (emptyCount > 0)
{
JITDUMP("fgRemoveEmptyFinally() removed %u try-finally clauses from %u finallys\n", emptyCount, finallyCount);
+ fgOptimizedFinally = true;
#ifdef DEBUG
if (verbose)
if (emptyCount > 0)
{
JITDUMP("fgRemoveEmptyTry() optimized %u empty-try try-finally clauses\n", emptyCount);
+ fgOptimizedFinally = true;
#ifdef DEBUG
if (verbose)
if (cloneCount > 0)
{
JITDUMP("fgCloneFinally() cloned %u finally handlers\n", cloneCount);
+ fgOptimizedFinally = true;
#ifdef DEBUG
if (verbose)
// a callfinally/always pair.
//
// Used by finally cloning, empty try removal, and empty
-// finally removal. Resets flags and removes finally artifacts.
+// finally removal.
+//
+// BBF_FINALLY_TARGET bbFlag is left unchanged by this method
+// since it cannot be incrementally updated. Proper updates happen
+// when fgUpdateFinallyTargetFlags runs after all finally optimizations.
void Compiler::fgCleanupContinuation(BasicBlock* continuation)
{
// always flag.
continuation->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS;
-#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
- // Also, clear the finally target bit for arm
- fgClearFinallyTargetBit(continuation);
-#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
-
#if !FEATURE_EH_FUNCLETS
// Remove the GT_END_LFIN from the continuation,
// Note we only expect to see one such statement.
assert(foundEndLFin);
#endif // !FEATURE_EH_FUNCLETS
}
+
+//------------------------------------------------------------------------
+// fgUpdateFinallyTargetFlags: recompute BBF_FINALLY_TARGET bits for all blocks
+// after finally optimizations have run.
+
+void Compiler::fgUpdateFinallyTargetFlags()
+{
+#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
+
+ // Any fixup required?
+ if (!fgOptimizedFinally)
+ {
+ JITDUMP("In fgUpdateFinallyTargetFlags - no finally opts, no fixup required\n");
+ return;
+ }
+
+ JITDUMP("In fgUpdateFinallyTargetFlags, updating finally target flag bits\n");
+
+ // Walk all blocks, and reset the target bits.
+ for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
+ {
+ block->bbFlags &= ~BBF_FINALLY_TARGET;
+ }
+
+ // Walk all blocks again, and set the target bits.
+ for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
+ {
+ if (block->isBBCallAlwaysPair())
+ {
+ BasicBlock* const leave = block->bbNext;
+ BasicBlock* const continuation = leave->bbJumpDest;
+
+ if ((continuation->bbFlags & BBF_FINALLY_TARGET) == 0)
+ {
+ JITDUMP("Found callfinally BB%02u; setting finally target bit on BB%02u\n", block->bbNum,
+ continuation->bbNum);
+
+ continuation->bbFlags |= BBF_FINALLY_TARGET;
+ }
+ }
+ }
+
+#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
+}