Repository: llvm/llvm-project
File: llvm/lib/Analysis/LoopInfo.cpp (C++)

Code before:
    BasicBlock *Preheader = getLoopPreheader();
    // Without a preheader, hoisting is not feasible.
    if (!Preheader)
      return false;
    InsertPt = Preheader->getTerminator();
  }
  // Don't hoist instructions with loop-variant operands.
  for (Value *Operand : I->operands())
    if (!makeLoopInvariant(Operand, Changed, InsertPt, MSSAU, SE))
      return false;

  // Hoist.
  I->moveBefore(InsertPt->getIterator());
  if (MSSAU)
    if (auto *MUD = MSSAU->getMemorySSA()->getMemoryAccess(I))
      MSSAU->moveToPlace(MUD, InsertPt->getParent(),
                         MemorySSA::BeforeTerminator);

  // We want to preserve profile metadata if possible. However, we need to
  // ensure that profile metadata would remain the same outside of the loop.
  // Given at this point we know the conditional is loop-invariant, we just
  // need to worry about other control flow in the loop conditioned on values
  // that are potentially not independent of the condition of the instruction
  // we are interested in hoisting. Given this is not knowable in the general
  // case, we only hoist from a loop header or unique latch (constitutes the
  // majority of cases), where we are guaranteed to not run into problems.
  SmallVector<unsigned, 1> ProfileMetadataToPreserve;
  if (!ProfcheckDisableMetadataFixes)
    if (OriginalParent == getHeader() || OriginalParent == getLoopLatch())
      ProfileMetadataToPreserve.push_back(LLVMContext::MD_prof);

  // There is possibility of hoisting this instruction above some arbitrary
  // condition. Any metadata defined on it can be control dependent on this
  // condition. Conservatively strip it here so that we don't give any wrong
  // information to the optimizer.
  I->dropUnknownNonDebugMetadata(ProfileMetadataToPreserve);

  if (ProfileMetadataToPreserve.empty() && isa<SelectInst>(I))
    setExplicitlyUnknownBranchWeightsIfProfiled(*I, "LoopInfo");

  if (SE)
    SE->forgetBlockAndLoopDispositions(I);

  Changed = true;
  return true;
}

bool Loop::getIncomingAndBackEdge(BasicBlock *&Incoming,
                                  BasicBlock *&Backedge) const {
  BasicBlock *H = getHeader();


Review comment (suggestion):
This is right for the header, but I'm not sure I understand why it's right for a unique latch.

A variation on my previous example would be:
```
loop {
  if (c) {
    break;
  }
  c ? x : a;
}
```
Here the select is in a unique latch block, but the condition is correlated with an early exit.

Code after:
    BasicBlock *Preheader = getLoopPreheader();
    // Without a preheader, hoisting is not feasible.
    if (!Preheader)
      return false;
    InsertPt = Preheader->getTerminator();
  }
  // Don't hoist instructions with loop-variant operands.
  for (Value *Operand : I->operands())
    if (!makeLoopInvariant(Operand, Changed, InsertPt, MSSAU, SE))
      return false;

  // Hoist.
  I->moveBefore(InsertPt->getIterator());
  if (MSSAU)
    if (auto *MUD = MSSAU->getMemorySSA()->getMemoryAccess(I))
      MSSAU->moveToPlace(MUD, InsertPt->getParent(),
                         MemorySSA::BeforeTerminator);

  // We want to preserve profile metadata if possible. However, we need to
  // ensure that profile metadata would remain the same outside of the loop.
  // Given at this point we know the conditional is loop-invariant, we just
  // need to worry about other control flow in the loop conditioned on values
  // that are potentially not independent of the condition of the instruction
  // we are interested in hoisting. Given this is not knowable in the general
  // case, we only hoist from a loop header (which covers a reasonable number
  // of cases) where we are guaranteed to not run into problems.
  SmallVector<unsigned, 1> ProfileMetadataToPreserve;
  if (!ProfcheckDisableMetadataFixes)
    if (OriginalParent == getHeader())
      ProfileMetadataToPreserve.push_back(LLVMContext::MD_prof);

  // There is possibility of hoisting this instruction above some arbitrary
  // condition. Any metadata defined on it can be control dependent on this
  // condition. Conservatively strip it here so that we don't give any wrong
  // information to the optimizer.
  I->dropUnknownNonDebugMetadata(ProfileMetadataToPreserve);

  if (ProfileMetadataToPreserve.empty() && isa<SelectInst>(I))
    setExplicitlyUnknownBranchWeightsIfProfiled(*I, "LoopInfo");

  if (SE)
    SE->forgetBlockAndLoopDispositions(I);

  Changed = true;
  return true;
}

bool Loop::getIncomingAndBackEdge(BasicBlock *&Incoming,
                                  BasicBlock *&Backedge) const {
  BasicBlock *H = getHeader();