@@ -3126,36 +3126,49 @@ class IfConversion
31263126 m_falseBlock = m_block->bbNext ;
31273127 m_trueBlock = m_block->bbJumpDest ;
31283128
3129- BasicBlock* joinBlock = SingleSuccessorBlock (m_falseBlock);
3129+ assert (m_falseBlock != m_block); // m_block can't fall through to itself
31303130
3131- if (joinBlock == m_block-> bbJumpDest )
3131+ if (m_trueBlock == m_falseBlock )
31323132 {
3133- if (LastInstruction (m_falseBlock) == nullptr )
3133+ // Reject degenerate full hammocks, fg optimizations should have taken care of this.
3134+ // They may end up passing as genuine full hammocks and cause various problems
3135+ // (e.g. decrement the ref count of a lclvar twice).
3136+ return HammockKind::None;
3137+ }
3138+
3139+ if (((m_trueBlock->bbFlags & BBF_RUN_RARELY) == 0 ) && ((m_block->bbFlags & BBF_RUN_RARELY) != 0 ))
3140+ {
3141+ // fall through from not-run-rarerly to run-rarely
3142+ return HammockKind::None;
3143+ }
3144+
3145+ if (m_trueBlock == m_block)
3146+ {
3147+ // Reject some back edges. A half hammock may be formed if "falseBlock" jumps back to
3148+ // "block" but that would be an infinite loop and it's not exactly common (and likely
3149+ // there's no test coverage for).
3150+ return HammockKind::None;
3151+ }
3152+
3153+ m_joinBlock = SingleSuccessorBlock (m_falseBlock);
3154+
3155+ if (m_joinBlock == m_trueBlock)
3156+ {
3157+ if (m_comp->fgInDifferentRegions (m_block, m_falseBlock))
31343158 {
3135- // The block is empty, fg optimizations should have taken care of this.
31363159 return HammockKind::None;
31373160 }
31383161
3139- if (m_comp-> fgInDifferentRegions (m_block, m_falseBlock) || !BasicBlock::sameEHRegion (m_block, m_falseBlock))
3162+ if (!BasicBlock::sameEHRegion (m_block, m_falseBlock))
31403163 {
31413164 return HammockKind::None;
31423165 }
31433166
31443167 // We have something like "if (cond) { falseBlock: ... } joinBlock: ..."
3145-
3146- m_joinBlock = joinBlock;
31473168 return HammockKind::Half;
31483169 }
31493170 else
31503171 {
3151- if ((LastInstruction (m_falseBlock) == nullptr ) || (LastInstruction (m_trueBlock) == nullptr ))
3152- {
3153- // Either or both blocks are empty, fg optimizations should have taken care of this.
3154- // If only one block is empty we actually have a half hammock but to keep things
3155- // simple this special case is not handled.
3156- return HammockKind::None;
3157- }
3158-
31593172 if ((m_falseBlock->bbJumpKind == BBJ_RETURN) && (m_trueBlock->bbJumpKind == BBJ_RETURN))
31603173 {
31613174#ifdef JIT32_GCENCODER
@@ -3165,14 +3178,26 @@ class IfConversion
31653178 // limit imposed by the x86 GC encoding.
31663179 return HammockKind::None;
31673180#endif
3168- m_joinBlock = nullptr ;
3181+ // SingleSuccessorBlock should have returned null for a BBJ_RETURN block
3182+ assert (m_joinBlock == nullptr );
31693183 }
3170- else if ((joinBlock != nullptr ) && (joinBlock = = SingleSuccessorBlock (m_trueBlock)))
3184+ else if ((m_joinBlock == nullptr ) || (m_joinBlock ! = SingleSuccessorBlock (m_trueBlock)))
31713185 {
3172- m_joinBlock = joinBlock ;
3186+ return HammockKind::None ;
31733187 }
3174- else
3188+ else if (m_joinBlock == m_block)
3189+ {
3190+ // Reject full hammocks where both "false" and "true" blocks jump back to "block".
3191+ // That would be an infinite infinite loop and it's not exactly common (and likely
3192+ // there's no test coverage for).
3193+ return HammockKind::None;
3194+ }
3195+
3196+ if (!m_block->isRunRarely () && m_trueBlock->isRunRarely ())
31753197 {
3198+ // If we're jumping from a normal block to a rarely run block then it means we have
3199+ // a rarely taken branch and it's likely not beneficial to convert it.
3200+ // TODO What about fall through?
31763201 return HammockKind::None;
31773202 }
31783203
@@ -3188,7 +3213,6 @@ class IfConversion
31883213 }
31893214
31903215 // We have something like "if (cond) { falseBlock: ... } else { trueBlock: ... } joinBlock: ..."
3191-
31923216 return HammockKind::Full;
31933217 }
31943218 }
@@ -3221,12 +3245,18 @@ class IfConversion
32213245
32223246 GenTree* op = LastInstruction (m_block);
32233247
3248+ if (op == nullptr )
3249+ {
3250+ // The block is empty, fg optimizations should have taken care of this.
3251+ return false ;
3252+ }
3253+
32243254 if ((kind == HammockKind::Half) && op->OperIs (GT_RETURN))
32253255 {
32263256 return false ;
32273257 }
32283258
3229- if ((op == nullptr ) || !op->OperIs (GT_STORE_LCL_VAR, GT_RETURN))
3259+ if (!op->OperIs (GT_STORE_LCL_VAR, GT_RETURN))
32303260 {
32313261 // TODO Indirs would also work provided that both blocks store to the same address.
32323262 // How to detect that?
0 commit comments