<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>Ack. Working on it. <br>
    </p>
    <p>Sameer.<br>
    </p>
    <div class="moz-cite-prefix">On Mon 20 Apr 11:19 PM +0530, Galina
      Kistanova wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAJ8eiNw=nqDzm1ebSy=WtiwGR4ndtYL_hXRC0GUdKppKh3zWKg@mail.gmail.com">
      
      [CAUTION: External Email]
      <div>
        <div dir="ltr">Hello Sameer,<br>
          <br>
          This commit added broken test to the builder:<br>
          <a href="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23139" originalsrc="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23139" shash="ZzdlUgkJ9Ry/go9/2Tp7RZsNSIqw9hdOCthyLDo3K1vItFzOjLnfZtAq446u/Ez9JqSnZPcSSQYwGlHbUQfTd4fqaqJejSkt/wImGOPmzkgxtCsiueNTwhzwldg8P7iFgVdiTmcTYIjWz119rkS1O/Y/7ivY28axZV8XjEk5l+s=" moz-do-not-send="true" title="Outlook Unmangled from:
https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Flab.llvm.org%3A8011%2Fbuilders%2Fllvm-clang-x86_64-expensive-checks-win%2Fbuilds%2F23139&data=02%7C01%7Csameer.sahasrabuddhe%40amd.com%7C6a1c7b47cf6245f08ceb08d7e5533972%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637230017944332883&sdata=XC5iGB7LlB2YcRspExGA51P%2FcuQodvZ6JhucakgBxoM%3D&reserved=0">http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23139</a><br>
          . . .<br>
          FAIL: LLVM::nested.ll<br>
          <br>
          The builder was already red and did not send notification.<br>
          <br>
          Please have a look ASAP?<br>
          <br>
          Thanks<br>
          <br>
          Galina</div>
        <br>
        <div class="gmail_quote">
          <div dir="ltr" class="gmail_attr">On Wed, Apr 15, 2020 at 2:38
            AM Sameer Sahasrabuddhe via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" moz-do-not-send="true">llvm-commits@lists.llvm.org</a>>
            wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">
            <br>
            Author: Sameer Sahasrabuddhe<br>
            Date: 2020-04-15T15:05:51+05:30<br>
            New Revision: 8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6<br>
            <br>
            URL: <a href="https://github.com/llvm/llvm-project/commit/8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6" originalsrc="https://github.com/llvm/llvm-project/commit/8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6" shash="hu81xBZrJrueMR+E6AtzTVodTQW19a1W8a9x8Zf6z6/tTRlXEKevFnH8oDwC3xLFZeYrfmN9K8nxTFNb24zs1CtA6zVZKMnLucTPHQrEYdBwbxv7fYb8fFPLyeuwqjLctYtcT4bfQdUkn4laHy+XSluesVVMG6q8yAhnoBd6zuY=" rel="noreferrer" target="_blank" moz-do-not-send="true" title="Outlook Unmangled from:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fllvm%2Fllvm-project%2Fcommit%2F8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6&data=02%7C01%7Csameer.sahasrabuddhe%40amd.com%7C6a1c7b47cf6245f08ceb08d7e5533972%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637230017944342886&sdata=mmqst2rwMdIQ3jc3fe0w7kgMFofS7AD9uZZZsVfEiF0%3D&reserved=0">https://github.com/llvm/llvm-project/commit/8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6</a><br>
            DIFF: <a href="https://github.com/llvm/llvm-project/commit/8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6.diff" originalsrc="https://github.com/llvm/llvm-project/commit/8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6.diff" shash="gBDyXSo2um9mxrMEqzDpu8sSxj+4cOwHlWp5D6CrnWgcbpriWfLseUreHVXDBPHD1DdGZz6oJVk2DeSJ/wpG1x3uMYMvlh2RhSVMxUxp2C9rx7W07Yx6r4EVnArQgAgl/rE5G+hjsZcyNPLwLkgX6t6qPBm6onNAoDP+UAO9jcQ=" rel="noreferrer" target="_blank" moz-do-not-send="true" title="Outlook Unmangled from:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fllvm%2Fllvm-project%2Fcommit%2F8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6.diff&data=02%7C01%7Csameer.sahasrabuddhe%40amd.com%7C6a1c7b47cf6245f08ceb08d7e5533972%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637230017944342886&sdata=HMdxUvYQJ61sdnFMuXwwkVe%2FwcB9vyqFr9vMZW0OcH4%3D&reserved=0">https://github.com/llvm/llvm-project/commit/8c11bc0cd06ffc18786a1a51ee5ce5b1cc4923f6.diff</a><br>
            <br>
            LOG: Introduce fix-irreducible pass<br>
            <br>
            An irreducible SCC is one which has multiple "header"
            blocks, i.e., blocks<br>
            with control-flow edges incident from outside the SCC. This
            pass converts an<br>
            irreducible SCC into a natural loop by introducing a single
            new header<br>
            block and redirecting all the edges on the original headers
            to this<br>
            new block.<br>
            <br>
            This is a useful workaround for a limitation in the
            structurizer<br>
            which, which produces incorrect control flow in the presence
            of<br>
            irreducible regions. The AMDGPU backend provides an option
            to<br>
            enable this pass before the structurizer, which may
            eventually be<br>
            enabled by default.<br>
            <br>
            Reviewed By: nhaehnle<br>
            <br>
            Differential Revision: <a href="https://reviews.llvm.org/D77198" originalsrc="https://reviews.llvm.org/D77198" shash="YU91IQ5XLnIA9YsrMlvicEqRMSmKR1ztfTJjUmUOnyaVnJwXs1WrkOihtPXmTOix0TJJsHdabXv6BfIld3IgWm6uGdyoxa4xPJdUZu05ePk+ZYVi4y6t/R7WfkvgItfV71uarN/MZBsy4Clk8qAoMaZdCpLw/Hm3a0mBfXIx7BQ=" rel="noreferrer" target="_blank" moz-do-not-send="true" title="Outlook Unmangled from:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Freviews.llvm.org%2FD77198&data=02%7C01%7Csameer.sahasrabuddhe%40amd.com%7C6a1c7b47cf6245f08ceb08d7e5533972%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637230017944352879&sdata=uS5%2BYS08qwxYIv8NdrzWcJsEk2fO7lEFA4Ik%2BlKriTY%3D&reserved=0">https://reviews.llvm.org/D77198</a><br>
            <br>
            This restores commit
            2ada8e2525dd2653f30c8696a27162a3b1647d66.<br>
            <br>
            Originally reverted with commit
            44e09b59b869a91bf47d76e8bc569d9ee91ad145.<br>
            <br>
            Added: <br>
                llvm/lib/Transforms/Utils/FixIrreducible.cpp<br>
                llvm/test/Transforms/FixIrreducible/basic.ll<br>
                llvm/test/Transforms/FixIrreducible/nested.ll<br>
                llvm/test/Transforms/FixIrreducible/switch.ll<br>
               
            llvm/test/Transforms/StructurizeCFG/workarounds/needs-fix-reducible.ll<br>
               
            llvm/test/Transforms/StructurizeCFG/workarounds/needs-fr-ule.ll<br>
            <br>
            Modified: <br>
                llvm/include/llvm/Analysis/LoopInfo.h<br>
                llvm/include/llvm/InitializePasses.h<br>
                llvm/include/llvm/LinkAllPasses.h<br>
                llvm/include/llvm/Transforms/Utils.h<br>
                llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp<br>
                llvm/lib/Transforms/Utils/BasicBlockUtils.cpp<br>
                llvm/lib/Transforms/Utils/CMakeLists.txt<br>
                llvm/lib/Transforms/Utils/Utils.cpp<br>
            <br>
            Removed: <br>
            <br>
            <br>
            <br>
################################################################################<br>
            diff  --git a/llvm/include/llvm/Analysis/LoopInfo.h
            b/llvm/include/llvm/Analysis/LoopInfo.h<br>
            index 824488e9ead8..6228505db6be 100644<br>
            --- a/llvm/include/llvm/Analysis/LoopInfo.h<br>
            +++ b/llvm/include/llvm/Analysis/LoopInfo.h<br>
            @@ -962,6 +962,12 @@ template <class BlockT, class
            LoopT> class LoopInfoBase {<br>
                 return L && L->getHeader() == BB;<br>
               }<br>
            <br>
            +  /// Return the top-level loops.<br>
            +  const std::vector<LoopT *> &getTopLevelLoops()
            const { return TopLevelLoops; }<br>
            +<br>
            +  /// Return the top-level loops.<br>
            +  std::vector<LoopT *> &getTopLevelLoopsVector()
            { return TopLevelLoops; }<br>
            +<br>
               /// This removes the specified top-level loop from this
            loop info object.<br>
               /// The loop is not deleted, as it will presumably be
            inserted into<br>
               /// another loop.<br>
            <br>
            diff  --git a/llvm/include/llvm/InitializePasses.h
            b/llvm/include/llvm/InitializePasses.h<br>
            index b39a497522d1..f35815a898d4 100644<br>
            --- a/llvm/include/llvm/InitializePasses.h<br>
            +++ b/llvm/include/llvm/InitializePasses.h<br>
            @@ -152,6 +152,7 @@ void
            initializeExternalAAWrapperPassPass(PassRegistry&);<br>
             void initializeFEntryInserterPass(PassRegistry&);<br>
             void initializeFinalizeISelPass(PassRegistry&);<br>
             void
            initializeFinalizeMachineBundlesPass(PassRegistry&);<br>
            +void initializeFixIrreduciblePass(PassRegistry &);<br>
             void
            initializeFixupStatepointCallerSavedPass(PassRegistry&);<br>
             void initializeFlattenCFGPassPass(PassRegistry&);<br>
             void initializeFloat2IntLegacyPassPass(PassRegistry&);<br>
            <br>
            diff  --git a/llvm/include/llvm/LinkAllPasses.h
            b/llvm/include/llvm/LinkAllPasses.h<br>
            index d5e9ffc1f80c..90e2e24294d4 100644<br>
            --- a/llvm/include/llvm/LinkAllPasses.h<br>
            +++ b/llvm/include/llvm/LinkAllPasses.h<br>
            @@ -231,6 +231,7 @@ namespace {<br>
                   (void) llvm::createHardwareLoopsPass();<br>
                   (void) llvm::createInjectTLIMappingsLegacyPass();<br>
                   (void) llvm::createUnifyLoopExitsPass();<br>
            +      (void) llvm::createFixIrreduciblePass();<br>
            <br>
                   (void)new llvm::IntervalPartition();<br>
                   (void)new llvm::ScalarEvolutionWrapperPass();<br>
            <br>
            diff  --git a/llvm/include/llvm/Transforms/Utils.h
            b/llvm/include/llvm/Transforms/Utils.h<br>
            index 402caf7a7d3d..59beb0caab1d 100644<br>
            --- a/llvm/include/llvm/Transforms/Utils.h<br>
            +++ b/llvm/include/llvm/Transforms/Utils.h<br>
            @@ -134,6 +134,13 @@ FunctionPass
            *createInjectTLIMappingsLegacyPass();<br>
             // exit blocks.<br>
             //<br>
             FunctionPass *createUnifyLoopExitsPass();<br>
            +<br>
+//===----------------------------------------------------------------------===//<br>
            +//<br>
            +// FixIrreducible - Convert each SCC with irreducible
            control-flow<br>
            +// into a natural loop.<br>
            +//<br>
            +FunctionPass *createFixIrreduciblePass();<br>
             }<br>
            <br>
             #endif<br>
            <br>
            diff  --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
            b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp<br>
            index 96788ea48344..e71721bd2722 100644<br>
            --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp<br>
            +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp<br>
            @@ -864,6 +864,7 @@ bool GCNPassConfig::addPreISel() {<br>
               addPass(&AMDGPUUnifyDivergentExitNodesID);<br>
               if (!LateCFGStructurize) {<br>
                 if (EnableStructurizerWorkarounds) {<br>
            +      addPass(createFixIrreduciblePass());<br>
                   addPass(createUnifyLoopExitsPass());<br>
                 }<br>
                 addPass(createStructurizeCFGPass(false)); // true ->
            SkipUniformRegions<br>
            <br>
            diff  --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
            b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp<br>
            index d72279316b88..95e2b26e98d5 100644<br>
            --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp<br>
            +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp<br>
            @@ -1144,18 +1144,62 @@ static void reconnectPhis(BasicBlock
            *Out, BasicBlock *GuardBlock,<br>
             using BBPredicates = DenseMap<BasicBlock *, PHINode
            *>;<br>
             using BBSetVector = SetVector<BasicBlock *>;<br>
            <br>
            -// Collect predicates for each outgoing block. If control
            reaches the<br>
            -// Hub from an incoming block InBB, then the predicate for
            each<br>
            -// outgoing block OutBB decides whether control is
            forwarded to OutBB.<br>
            +// Redirects the terminator of the incoming block to the
            first guard<br>
            +// block in the hub. The condition of the original
            terminator (if it<br>
            +// was conditional) and its original successors are
            returned as a<br>
            +// tuple <condition, succ0, succ1>. The function
            additionally filters<br>
            +// out successors that are not in the set of outgoing
            blocks.<br>
             //<br>
            -// These predicates are not orthogonal. The Hub evaluates
            them in the<br>
            -// same order as the Outgoing set-vector, and control
            branches to the<br>
            -// first outgoing block whose predicate evaluates to true.<br>
            -static void createGuardPredicates(BasicBlock
            *FirstGuardBlock,<br>
            -                                  BBPredicates
            &GuardPredicates,<br>
            -                                 
            SmallVectorImpl<WeakVH> &DeletionCandidates,<br>
            -                                  const BBSetVector
            &Incoming,<br>
            -                                  const BBSetVector
            &Outgoing) {<br>
            +// - condition is non-null iff the branch is conditional.<br>
            +// - Succ1 is non-null iff the sole/taken target is an
            outgoing block.<br>
            +// - Succ2 is non-null iff condition is non-null and the
            fallthrough<br>
            +//         target is an outgoing block.<br>
            +static std::tuple<Value *, BasicBlock *, BasicBlock
            *><br>
            +redirectToHub(BasicBlock *BB, BasicBlock *FirstGuardBlock,<br>
            +              const BBSetVector &Outgoing) {<br>
            +  auto Branch =
            cast<BranchInst>(BB->getTerminator());<br>
            +  auto Condition = Branch->isConditional() ?
            Branch->getCondition() : nullptr;<br>
            +<br>
            +  BasicBlock *Succ0 = Branch->getSuccessor(0);<br>
            +  BasicBlock *Succ1 = nullptr;<br>
            +  Succ0 = Outgoing.count(Succ0) ? Succ0 : nullptr;<br>
            +<br>
            +  if (Branch->isUnconditional()) {<br>
            +    Branch->setSuccessor(0, FirstGuardBlock);<br>
            +    assert(Succ0);<br>
            +  } else {<br>
            +    Succ1 = Branch->getSuccessor(1);<br>
            +    Succ1 = Outgoing.count(Succ1) ? Succ1 : nullptr;<br>
            +    assert(Succ0 || Succ1);<br>
            +    if (Succ0 && !Succ1) {<br>
            +      Branch->setSuccessor(0, FirstGuardBlock);<br>
            +    } else if (Succ1 && !Succ0) {<br>
            +      Branch->setSuccessor(1, FirstGuardBlock);<br>
            +    } else {<br>
            +      Branch->eraseFromParent();<br>
            +      BranchInst::Create(FirstGuardBlock, BB);<br>
            +    }<br>
            +  }<br>
            +<br>
            +  assert(Succ0 || Succ1);<br>
            +  return std::make_tuple(Condition, Succ0, Succ1);<br>
            +}<br>
            +<br>
            +// Capture the existing control flow as guard predicates,
            and redirect<br>
            +// control flow from every incoming block to the first
            guard block in<br>
            +// the hub.<br>
            +//<br>
            +// There is one guard predicate for each outgoing block
            OutBB. The<br>
            +// predicate is a PHINode with one input for each InBB
            which<br>
            +// represents whether the hub should transfer control flow
            to OutBB if<br>
            +// it arrived from InBB. These predicates are NOT
            ORTHOGONAL. The Hub<br>
            +// evaluates them in the same order as the Outgoing
            set-vector, and<br>
            +// control branches to the first outgoing block whose
            predicate<br>
            +// evaluates to true.<br>
            +static void convertToGuardPredicates(<br>
            +    BasicBlock *FirstGuardBlock, BBPredicates
            &GuardPredicates,<br>
            +    SmallVectorImpl<WeakVH> &DeletionCandidates,
            const BBSetVector &Incoming,<br>
            +    const BBSetVector &Outgoing) {<br>
               auto &Context = Incoming.front()->getContext();<br>
               auto BoolTrue = ConstantInt::getTrue(Context);<br>
               auto BoolFalse = ConstantInt::getFalse(Context);<br>
            @@ -1172,30 +1216,11 @@ static void
            createGuardPredicates(BasicBlock *FirstGuardBlock,<br>
               }<br>
            <br>
               for (auto In : Incoming) {<br>
            -    auto Branch =
            cast<BranchInst>(In->getTerminator());<br>
            -    BasicBlock *Succ0 = Branch->getSuccessor(0);<br>
            -    BasicBlock *Succ1 = nullptr;<br>
            -<br>
            -    Succ0 = Outgoing.count(Succ0) ? Succ0 : nullptr;<br>
            -<br>
            -    if (Branch->isUnconditional()) {<br>
            -      Branch->setSuccessor(0, FirstGuardBlock);<br>
            -      assert(Succ0);<br>
            -    } else {<br>
            -      Succ1 = Branch->getSuccessor(1);<br>
            -      Succ1 = Outgoing.count(Succ1) ? Succ1 : nullptr;<br>
            -      assert(Succ0 || Succ1);<br>
            -      if (Succ0 && !Succ1) {<br>
            -        Branch->setSuccessor(0, FirstGuardBlock);<br>
            -      } else if (Succ1 && !Succ0) {<br>
            -        Branch->setSuccessor(1, FirstGuardBlock);<br>
            -      } else {<br>
            -        Branch->eraseFromParent();<br>
            -        BranchInst::Create(FirstGuardBlock, In);<br>
            -      }<br>
            -    }<br>
            -<br>
            -    assert(Succ0 || Succ1);<br>
            +    Value *Condition;<br>
            +    BasicBlock *Succ0;<br>
            +    BasicBlock *Succ1;<br>
            +    std::tie(Condition, Succ0, Succ1) =<br>
            +        redirectToHub(In, FirstGuardBlock, Outgoing);<br>
            <br>
                 // Optimization: Consider an incoming block A with both
            successors<br>
                 // Succ0 and Succ1 in the set of outgoing blocks. The
            predicates<br>
            @@ -1205,7 +1230,6 @@ static void
            createGuardPredicates(BasicBlock *FirstGuardBlock,<br>
                 // control must reach Succ1, which means that the
            predicate for<br>
                 // Succ1 is always true.<br>
                 bool OneSuccessorDone = false;<br>
            -    auto Condition = Branch->getCondition();<br>
                 for (int i = 0, e = Outgoing.size() - 1; i != e; ++i) {<br>
                   auto Out = Outgoing[i];<br>
                   auto Phi = GuardPredicates[Out];<br>
            @@ -1287,8 +1311,8 @@ BasicBlock
            *llvm::CreateControlFlowHub(<br>
            <br>
               BBPredicates GuardPredicates;<br>
               SmallVector<WeakVH, 8> DeletionCandidates;<br>
            -  createGuardPredicates(FirstGuardBlock, GuardPredicates,
            DeletionCandidates,<br>
            -                        Incoming, Outgoing);<br>
            +  convertToGuardPredicates(FirstGuardBlock,
            GuardPredicates, DeletionCandidates,<br>
            +                           Incoming, Outgoing);<br>
            <br>
               GuardBlocks.push_back(FirstGuardBlock);<br>
               createGuardBlocks(GuardBlocks, F, Outgoing,
            GuardPredicates, Prefix);<br>
            <br>
            diff  --git a/llvm/lib/Transforms/Utils/CMakeLists.txt
            b/llvm/lib/Transforms/Utils/CMakeLists.txt<br>
            index 7d9fcb566dd3..9a316ad1b36f 100644<br>
            --- a/llvm/lib/Transforms/Utils/CMakeLists.txt<br>
            +++ b/llvm/lib/Transforms/Utils/CMakeLists.txt<br>
            @@ -20,6 +20,7 @@
            add_llvm_component_library(LLVMTransformUtils<br>
               EntryExitInstrumenter.cpp<br>
               EscapeEnumerator.cpp<br>
               Evaluator.cpp<br>
            +  FixIrreducible.cpp<br>
               FlattenCFG.cpp<br>
               FunctionComparator.cpp<br>
               FunctionImportUtils.cpp<br>
            <br>
            diff  --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp
            b/llvm/lib/Transforms/Utils/FixIrreducible.cpp<br>
            new file mode 100644<br>
            index 000000000000..af5a99a0df79<br>
            --- /dev/null<br>
            +++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp<br>
            @@ -0,0 +1,333 @@<br>
            +//===- FixIrreducible.cpp - Convert irreducible
            control-flow into loops ---===//<br>
            +//<br>
            +// Part of the LLVM Project, under the Apache License v2.0
            with LLVM Exceptions.<br>
            +// See <a href="https://llvm.org/LICENSE.txt" originalsrc="https://llvm.org/LICENSE.txt" shash="jJcuT8d3e1o0rGMEx+elUrsIEw/L/wMt43e10NBJP57Tk3C59pohar2f0cXiwfjzmKRSdH7LunLsSiL4MwTnONSeNpAi/VhbLhJxIrkqy1PJJ5QrYIjT/jxkP5UpRu5CT/+MCK91MYH1bOuitu2JGgl+f+5EVC8daQ7oIg85nJU=" rel="noreferrer" target="_blank" moz-do-not-send="true" title="Outlook Unmangled from:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fllvm.org%2FLICENSE.txt&data=02%7C01%7Csameer.sahasrabuddhe%40amd.com%7C6a1c7b47cf6245f08ceb08d7e5533972%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637230017944352879&sdata=oBYdaWuRxVJXa5OnA8L5QEVIlXtwxxzCktgSbJf8b2M%3D&reserved=0">https://llvm.org/LICENSE.txt</a>
            for license information.<br>
            +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
            +//<br>
+//===----------------------------------------------------------------------===//<br>
            +//<br>
            +// An irreducible SCC is one which has multiple "header"
            blocks, i.e., blocks<br>
            +// with control-flow edges incident from outside the SCC. 
            This pass converts a<br>
            +// irreducible SCC into a natural loop by applying the
            following transformation:<br>
            +//<br>
            +// 1. Collect the set of headers H of the SCC.<br>
            +// 2. Collect the set of predecessors P of these headers.
            These may be inside as<br>
            +//    well as outside the SCC.<br>
            +// 3. Create block N and redirect every edge from set P to
            set H through N.<br>
            +//<br>
            +// This converts the SCC into a natural loop with N as the
            header: N is the only<br>
            +// block with edges incident from outside the SCC, and all
            backedges in the SCC<br>
            +// are incident on N, i.e., for every backedge, the head
            now dominates the tail.<br>
            +//<br>
            +// INPUT CFG: The blocks A and B form an irreducible loop
            with two headers.<br>
            +//<br>
            +//                        Entry<br>
            +//                       /     \<br>
            +//                      v       v<br>
            +//                      A ----> B<br>
            +//                      ^      /|<br>
            +//                       `----' |<br>
            +//                              v<br>
            +//                             Exit<br>
            +//<br>
            +// OUTPUT CFG: Edges incident on A and B are now redirected
            through a<br>
            +// new block N, forming a natural loop consisting of N, A
            and B.<br>
            +//<br>
            +//                        Entry<br>
            +//                          |<br>
            +//                          v<br>
            +//                    .---> N <---.<br>
            +//                   /     / \     \<br>
            +//                  |     /   \     |<br>
            +//                  \    v     v    /<br>
            +//                   `-- A     B --'<br>
            +//                             |<br>
            +//                             v<br>
            +//                            Exit<br>
            +//<br>
            +// The transformation is applied to every maximal SCC that
            is not already<br>
            +// recognized as a loop. The pass operates on all maximal
            SCCs found in the<br>
            +// function body outside of any loop, as well as those
            found inside each loop,<br>
            +// including inside any newly created loops. This ensures
            that any SCC hidden<br>
            +// inside a maximal SCC is also transformed.<br>
            +//<br>
            +// The actual transformation is handled by function
            CreateControlFlowHub, which<br>
            +// takes a set of incoming blocks (the predecessors) and
            outgoing blocks (the<br>
            +// headers). The function also moves every PHINode in an
            outgoing block to the<br>
            +// hub. Since the hub dominates all the outgoing blocks,
            each such PHINode<br>
            +// continues to dominate its uses. Since every header in an
            SCC has at least two<br>
            +// predecessors, every value used in the header (or later)
            but defined in a<br>
            +// predecessor (or earlier) is represented by a PHINode in
            a header. Hence the<br>
            +// above handling of PHINodes is sufficient and no further
            processing is<br>
            +// required to restore SSA.<br>
            +//<br>
            +// Limitation: The pass cannot handle switch statements and
            indirect<br>
            +//             branches. Both must be lowered to plain
            branches first.<br>
            +//<br>
+//===----------------------------------------------------------------------===//<br>
            +<br>
            +#include "llvm/ADT/SCCIterator.h"<br>
            +#include "llvm/Analysis/LoopIterator.h"<br>
            +#include "llvm/InitializePasses.h"<br>
            +#include "llvm/Pass.h"<br>
            +#include "llvm/Transforms/Utils.h"<br>
            +#include "llvm/Transforms/Utils/BasicBlockUtils.h"<br>
            +<br>
            +#define DEBUG_TYPE "fix-irreducible"<br>
            +<br>
            +using namespace llvm;<br>
            +<br>
            +namespace {<br>
            +struct FixIrreducible : public FunctionPass {<br>
            +  static char ID;<br>
            +  FixIrreducible() : FunctionPass(ID) {<br>
            +   
            initializeFixIrreduciblePass(*PassRegistry::getPassRegistry());<br>
            +  }<br>
            +<br>
            +  void getAnalysisUsage(AnalysisUsage &AU) const {<br>
            +    AU.addRequiredID(LowerSwitchID);<br>
            +    AU.addRequired<DominatorTreeWrapperPass>();<br>
            +    AU.addRequired<LoopInfoWrapperPass>();<br>
            +    AU.addPreservedID(LowerSwitchID);<br>
            +    AU.addPreserved<DominatorTreeWrapperPass>();<br>
            +    AU.addPreserved<LoopInfoWrapperPass>();<br>
            +  }<br>
            +<br>
            +  bool runOnFunction(Function &F);<br>
            +};<br>
            +} // namespace<br>
            +<br>
            +char FixIrreducible::ID = 0;<br>
            +<br>
            +FunctionPass *llvm::createFixIrreduciblePass() { return new
            FixIrreducible(); }<br>
            +<br>
            +INITIALIZE_PASS_BEGIN(FixIrreducible, "fix-irreducible",<br>
            +                      "Convert irreducible control-flow
            into natural loops",<br>
            +                      false /* Only looks at CFG */, false
            /* Analysis Pass */)<br>
            +INITIALIZE_PASS_DEPENDENCY(LowerSwitch)<br>
            +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)<br>
            +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)<br>
            +INITIALIZE_PASS_END(FixIrreducible, "fix-irreducible",<br>
            +                    "Convert irreducible control-flow into
            natural loops",<br>
            +                    false /* Only looks at CFG */, false /*
            Analysis Pass */)<br>
            +<br>
            +// When a new loop is created, existing children of the
            parent loop may now be<br>
            +// fully inside the new loop. Reconnect these as children
            of the new loop.<br>
            +static void reconnectChildLoops(LoopInfo &LI, Loop
            *ParentLoop, Loop *NewLoop,<br>
            +                                SetVector<BasicBlock
            *> &Blocks,<br>
            +                                SetVector<BasicBlock
            *> &Headers) {<br>
            +  auto &CandidateLoops = ParentLoop ?
            ParentLoop->getSubLoopsVector()<br>
            +                                    :
            LI.getTopLevelLoopsVector();<br>
            +  // Partition the candidate loops into two ranges. The
            first part<br>
            +  // contains loops that are not children of the new loop.
            The second<br>
            +  // part contains children that need to be moved to the
            new loop.<br>
            +  auto FirstChild =<br>
            +      std::partition(CandidateLoops.begin(),
            CandidateLoops.end(), [&](Loop *L) {<br>
            +        return L == NewLoop ||
            Blocks.count(L->getHeader()) == 0;<br>
            +      });<br>
            +  for (auto II = FirstChild, IE = CandidateLoops.end(); II
            != IE; ++II) {<br>
            +    auto Child = *II;<br>
            +    LLVM_DEBUG(dbgs() << "child loop: " <<
            Child->getHeader()->getName()<br>
            +                      << "\n");<br>
            +    // TODO: A child loop whose header is also a header in
            the current<br>
            +    // SCC gets destroyed since its backedges are removed.
            That may<br>
            +    // not be necessary if we can retain such backedges.<br>
            +    if (Headers.count(Child->getHeader())) {<br>
            +      for (auto BB : Child->blocks()) {<br>
            +        LI.changeLoopFor(BB, NewLoop);<br>
            +        LLVM_DEBUG(dbgs() << "moved block from child:
            " << BB->getName()<br>
            +                          << "\n");<br>
            +      }<br>
            +      LI.destroy(Child);<br>
            +      LLVM_DEBUG(dbgs() << "subsumed child loop
            (common header)\n");<br>
            +      continue;<br>
            +    }<br>
            +<br>
            +    if (ParentLoop) {<br>
            +      LLVM_DEBUG(dbgs() << "removed child loop from
            parent\n");<br>
            +      ParentLoop->removeChildLoop(Child);<br>
            +    }<br>
            +    LLVM_DEBUG(dbgs() << "added child loop to new
            loop\n");<br>
            +    NewLoop->addChildLoop(Child);<br>
            +  }<br>
            +  CandidateLoops.erase(FirstChild, CandidateLoops.end());<br>
            +}<br>
            +<br>
            +// Given a set of blocks and headers in an irreducible SCC,
            convert it into a<br>
            +// natural loop. Also insert this new loop at its
            appropriate place in the<br>
            +// hierarchy of loops.<br>
            +static void createNaturalLoopInternal(LoopInfo &LI,
            DominatorTree &DT,<br>
            +                                      Loop *ParentLoop,<br>
            +                                     
            SetVector<BasicBlock *> &Blocks,<br>
            +                                     
            SetVector<BasicBlock *> &Headers) {<br>
            +#ifndef NDEBUG<br>
            +  // All headers are part of the SCC<br>
            +  for (auto H : Headers) {<br>
            +    assert(Blocks.count(H));<br>
            +  }<br>
            +#endif<br>
            +<br>
            +  SetVector<BasicBlock *> Predecessors;<br>
            +  for (auto H : Headers) {<br>
            +    for (auto P : predecessors(H)) {<br>
            +      Predecessors.insert(P);<br>
            +    }<br>
            +  }<br>
            +<br>
            +  LLVM_DEBUG(<br>
            +      dbgs() << "Found predecessors:";<br>
            +      for (auto P : Predecessors) {<br>
            +        dbgs() << " " << P->getName();<br>
            +      }<br>
            +      dbgs() << "\n");<br>
            +<br>
            +  // Redirect all the backedges through a "hub" consisting
            of a series<br>
            +  // of guard blocks that manage the flow of control from
            the<br>
            +  // predecessors to the headers.<br>
            +  SmallVector<BasicBlock *, 8> GuardBlocks;<br>
            +  DomTreeUpdater DTU(DT,
            DomTreeUpdater::UpdateStrategy::Eager);<br>
            +  CreateControlFlowHub(&DTU, GuardBlocks, Predecessors,
            Headers, "irr");<br>
            +#if defined(EXPENSIVE_CHECKS)<br>
            + 
            assert(DT.verify(DominatorTree::VerificationLevel::Full));<br>
            +#else<br>
            + 
            assert(DT.verify(DominatorTree::VerificationLevel::Fast));<br>
            +#endif<br>
            +<br>
            +  // Create a new loop from the now-transformed cycle<br>
            +  auto NewLoop = LI.AllocateLoop();<br>
            +  if (ParentLoop) {<br>
            +    ParentLoop->addChildLoop(NewLoop);<br>
            +  } else {<br>
            +    LI.addTopLevelLoop(NewLoop);<br>
            +  }<br>
            +<br>
            +  // Add the guard blocks to the new loop. The first guard
            block is<br>
            +  // the head of all the backedges, and it is the first to
            be inserted<br>
            +  // in the loop. This ensures that it is recognized as the<br>
            +  // header. Since the new loop is already in LoopInfo, the
            new blocks<br>
            +  // are also propagated up the chain of parent loops.<br>
            +  for (auto G : GuardBlocks) {<br>
            +    LLVM_DEBUG(dbgs() << "added guard block: "
            << G->getName() << "\n");<br>
            +    NewLoop->addBasicBlockToLoop(G, LI);<br>
            +  }<br>
            +<br>
            +  // Add the SCC blocks to the new loop.<br>
            +  for (auto BB : Blocks) {<br>
            +    NewLoop->addBlockEntry(BB);<br>
            +    if (LI.getLoopFor(BB) == ParentLoop) {<br>
            +      LLVM_DEBUG(dbgs() << "moved block from parent:
            " << BB->getName()<br>
            +                        << "\n");<br>
            +      LI.changeLoopFor(BB, NewLoop);<br>
            +    } else {<br>
            +      LLVM_DEBUG(dbgs() << "added block from child: "
            << BB->getName() << "\n");<br>
            +    }<br>
            +  }<br>
            +  LLVM_DEBUG(dbgs() << "header for new loop: "<br>
            +                    <<
            NewLoop->getHeader()->getName() << "\n");<br>
            +<br>
            +  reconnectChildLoops(LI, ParentLoop, NewLoop, Blocks,
            Headers);<br>
            +<br>
            +  NewLoop->verifyLoop();<br>
            +  if (ParentLoop) {<br>
            +    ParentLoop->verifyLoop();<br>
            +  }<br>
            +#if defined(EXPENSIVE_CHECKS)<br>
            +  LI.verify(DT);<br>
            +#endif // EXPENSIVE_CHECKS<br>
            +}<br>
            +<br>
            +// Enable the graph traits required for traversing a Loop
            body.<br>
            +template <> struct llvm::GraphTraits<Loop> :
            LoopBodyTraits {};<br>
            +<br>
            +// Overloaded wrappers to go with the function template
            below.<br>
            +BasicBlock *unwrapBlock(BasicBlock *B) { return B; }<br>
            +BasicBlock *unwrapBlock(LoopBodyTraits::NodeRef &N) {
            return N.second; }<br>
            +<br>
            +static void createNaturalLoop(LoopInfo &LI,
            DominatorTree &DT, Function *F,<br>
            +                              SetVector<BasicBlock *>
            &Blocks,<br>
            +                              SetVector<BasicBlock *>
            &Headers) {<br>
            +  createNaturalLoopInternal(LI, DT, nullptr, Blocks,
            Headers);<br>
            +}<br>
            +<br>
            +static void createNaturalLoop(LoopInfo &LI,
            DominatorTree &DT, Loop &L,<br>
            +                              SetVector<BasicBlock *>
            &Blocks,<br>
            +                              SetVector<BasicBlock *>
            &Headers) {<br>
            +  createNaturalLoopInternal(LI, DT, &L, Blocks,
            Headers);<br>
            +}<br>
            +<br>
            +// Convert irreducible SCCs; Graph G may be a Function* or
            a Loop&.<br>
            +template <class Graph><br>
            +static bool makeReducible(LoopInfo &LI, DominatorTree
            &DT, Graph &&G) {<br>
            +  bool Changed = false;<br>
            +  for (auto Scc = scc_begin(G); !Scc.isAtEnd(); ++Scc) {<br>
            +    if (Scc->size() < 2)<br>
            +      continue;<br>
            +    SetVector<BasicBlock *> Blocks;<br>
            +    LLVM_DEBUG(dbgs() << "Found SCC:");<br>
            +    for (auto N : *Scc) {<br>
            +      auto BB = unwrapBlock(N);<br>
            +      LLVM_DEBUG(dbgs() << " " <<
            BB->getName());<br>
            +      Blocks.insert(BB);<br>
            +    }<br>
            +    LLVM_DEBUG(dbgs() << "\n");<br>
            +<br>
            +    // Minor optimization: The SCC blocks are usually
            discovered in an order<br>
            +    // that is the opposite of the order in which these
            blocks appear as branch<br>
            +    // targets. This results in a lot of condition
            inversions in the control<br>
            +    // flow out of the new ControlFlowHub, which can be
            mitigated if the orders<br>
            +    // match. So we discover the headers using the reverse
            of the block order.<br>
            +    SetVector<BasicBlock *> Headers;<br>
            +    LLVM_DEBUG(dbgs() << "Found headers:");<br>
            +    for (auto BB : reverse(Blocks)) {<br>
            +      for (const auto P : predecessors(BB)) {<br>
            +        if (!Blocks.count(P)) {<br>
            +          LLVM_DEBUG(dbgs() << " " <<
            BB->getName());<br>
            +          Headers.insert(BB);<br>
            +          break;<br>
            +        }<br>
            +      }<br>
            +    }<br>
            +    LLVM_DEBUG(dbgs() << "\n");<br>
            +<br>
            +    if (Headers.size() == 1) {<br>
            +      assert(LI.isLoopHeader(Headers.front()));<br>
            +      LLVM_DEBUG(dbgs() << "Natural loop with a
            single header: skipped\n");<br>
            +      continue;<br>
            +    }<br>
            +    createNaturalLoop(LI, DT, G, Blocks, Headers);<br>
            +    Changed = true;<br>
            +  }<br>
            +  return Changed;<br>
            +}<br>
            +<br>
            +bool FixIrreducible::runOnFunction(Function &F) {<br>
            +  LLVM_DEBUG(dbgs() << "===== Fix irreducible
            control-flow in function: "<br>
            +                    << F.getName() << "\n");<br>
            +  auto &LI =
            getAnalysis<LoopInfoWrapperPass>().getLoopInfo();<br>
            +  auto &DT =
            getAnalysis<DominatorTreeWrapperPass>().getDomTree();<br>
            +<br>
            +  bool Changed = false;<br>
            +  SmallVector<Loop *, 8> WorkList;<br>
            +<br>
            +  LLVM_DEBUG(dbgs() << "visiting top-level\n");<br>
            +  Changed |= makeReducible(LI, DT, &F);<br>
            +<br>
            +  // Any SCCs reduced are now already in the list of
            top-level loops, so simply<br>
            +  // add them all to the worklist.<br>
            +  for (auto L : LI) {<br>
            +    WorkList.push_back(L);<br>
            +  }<br>
            +<br>
            +  while (!WorkList.empty()) {<br>
            +    auto L = WorkList.back();<br>
            +    WorkList.pop_back();<br>
            +    LLVM_DEBUG(dbgs() << "visiting loop with header "<br>
            +                      <<
            L->getHeader()->getName() << "\n");<br>
            +    Changed |= makeReducible(LI, DT, *L);<br>
            +    // Any SCCs reduced are now already in the list of
            child loops, so simply<br>
            +    // add them all to the worklist.<br>
            +    WorkList.append(L->begin(), L->end());<br>
            +  }<br>
            +<br>
            +  return Changed;<br>
            +}<br>
            <br>
            diff  --git a/llvm/lib/Transforms/Utils/Utils.cpp
            b/llvm/lib/Transforms/Utils/Utils.cpp<br>
            index 363110ab8a7d..7469e388eb21 100644<br>
            --- a/llvm/lib/Transforms/Utils/Utils.cpp<br>
            +++ b/llvm/lib/Transforms/Utils/Utils.cpp<br>
            @@ -40,6 +40,7 @@ void
            llvm::initializeTransformUtils(PassRegistry &Registry) {<br>
               initializeStripGCRelocatesPass(Registry);<br>
               initializePredicateInfoPrinterLegacyPassPass(Registry);<br>
               initializeInjectTLIMappingsLegacyPass(Registry);<br>
            +  initializeFixIrreduciblePass(Registry);<br>
               initializeUnifyLoopExitsPass(Registry);<br>
             }<br>
            <br>
            <br>
            diff  --git a/llvm/test/Transforms/FixIrreducible/basic.ll
            b/llvm/test/Transforms/FixIrreducible/basic.ll<br>
            new file mode 100644<br>
            index 000000000000..ed04c1bf78c0<br>
            --- /dev/null<br>
            +++ b/llvm/test/Transforms/FixIrreducible/basic.ll<br>
            @@ -0,0 +1,268 @@<br>
            +; NOTE: Assertions have been autogenerated by
            utils/update_test_checks.py<br>
            +; RUN: opt < %s -fix-irreducible -S | FileCheck %s
            -check-prefix=CHECK<br>
            +<br>
            +define i32 @basic(i1 %PredEntry, i1 %PredLeft, i1
            %PredRight, i32 %X, i32 %Y) {<br>
            +; CHECK-LABEL: @basic(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       left:<br>
            +; CHECK-NEXT:    [[L:%.*]] = add i32 [[L_PHI_MOVED:%.*]], 1<br>
            +; CHECK-NEXT:    br i1 [[PREDLEFT:%.*]], label
            [[IRR_GUARD]], label [[EXIT:%.*]]<br>
            +; CHECK:       right:<br>
            +; CHECK-NEXT:    br i1 [[PREDRIGHT:%.*]], label
            [[IRR_GUARD]], label [[EXIT]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    [[Z:%.*]] = phi i32 [ [[L]], [[LEFT:%.*]]
            ], [ [[R_PHI_MOVED:%.*]], [[RIGHT:%.*]] ]<br>
            +; CHECK-NEXT:    ret i32 [[Z]]<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_LEFT:%.*]] = phi i1 [ true,
            [[RIGHT]] ], [ [[PREDENTRY:%.*]], [[ENTRY:%.*]] ], [ false,
            [[LEFT]] ]<br>
            +; CHECK-NEXT:    [[L_PHI_MOVED]] = phi i32 [
            [[R_PHI_MOVED]], [[RIGHT]] ], [ [[X:%.*]], [[ENTRY]] ], [
            [[L_PHI_MOVED]], [[LEFT]] ]<br>
            +; CHECK-NEXT:    [[R_PHI_MOVED]] = phi i32 [
            [[R_PHI_MOVED]], [[RIGHT]] ], [ [[Y:%.*]], [[ENTRY]] ], [
            [[L]], [[LEFT]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_LEFT]], label [[LEFT]],
            label [[RIGHT]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %PredEntry, label %left, label %right<br>
            +<br>
            +left:<br>
            +  %L.phi = phi i32 [%X, %entry], [%R.phi, %right]<br>
            +  %L = add i32 %L.phi, 1<br>
            +  br i1 %PredLeft, label %right, label %exit<br>
            +<br>
            +right:<br>
            +  %R.phi = phi i32 [%Y, %entry], [%L, %left]<br>
            +  br i1 %PredRight, label %left, label %exit<br>
            +<br>
            +exit:<br>
            +  %Z = phi i32 [%L, %left], [%R.phi, %right]<br>
            +  ret i32 %Z<br>
            +}<br>
            +<br>
            +define i32 @feedback_loop(i1 %PredEntry, i1 %PredLeft, i1
            %PredRight, i32 %X, i32 %Y) {<br>
            +; CHECK-LABEL: @feedback_loop(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       left:<br>
            +; CHECK-NEXT:    br i1 [[PREDLEFT:%.*]], label
            [[IRR_GUARD]], label [[EXIT:%.*]]<br>
            +; CHECK:       right:<br>
            +; CHECK-NEXT:    br i1 [[PREDRIGHT:%.*]], label
            [[IRR_GUARD]], label [[EXIT]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    [[Z:%.*]] = phi i32 [ [[L_PHI_MOVED:%.*]],
            [[LEFT:%.*]] ], [ [[R_PHI_MOVED:%.*]], [[RIGHT:%.*]] ]<br>
            +; CHECK-NEXT:    ret i32 [[Z]]<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_LEFT:%.*]] = phi i1 [ true,
            [[RIGHT]] ], [ [[PREDENTRY:%.*]], [[ENTRY:%.*]] ], [ false,
            [[LEFT]] ]<br>
            +; CHECK-NEXT:    [[L_PHI_MOVED]] = phi i32 [
            [[R_PHI_MOVED]], [[RIGHT]] ], [ [[X:%.*]], [[ENTRY]] ], [
            [[L_PHI_MOVED]], [[LEFT]] ]<br>
            +; CHECK-NEXT:    [[R_PHI_MOVED]] = phi i32 [
            [[R_PHI_MOVED]], [[RIGHT]] ], [ [[Y:%.*]], [[ENTRY]] ], [
            [[L_PHI_MOVED]], [[LEFT]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_LEFT]], label [[LEFT]],
            label [[RIGHT]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %PredEntry, label %left, label %right<br>
            +<br>
            +left:<br>
            +  %L.phi = phi i32 [%X, %entry], [%R.phi, %right]<br>
            +  br i1 %PredLeft, label %right, label %exit<br>
            +<br>
            +right:<br>
            +  %R.phi = phi i32 [%Y, %entry], [%L.phi, %left]<br>
            +  br i1 %PredRight, label %left, label %exit<br>
            +<br>
            +exit:<br>
            +  %Z = phi i32 [%L.phi, %left], [%R.phi, %right]<br>
            +  ret i32 %Z<br>
            +}<br>
            +<br>
            +define i32 @multiple_predecessors(i1 %PredEntry, i1 %PredA,
            i1 %PredB, i1 %PredC, i1 %PredD, i32 %X, i32 %Y) {<br>
            +; CHECK-LABEL: @multiple_predecessors(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    [[PREDB_INV:%.*]] = xor i1 [[PREDB:%.*]],
            true<br>
            +; CHECK-NEXT:    br i1 [[PREDENTRY:%.*]], label [[A:%.*]],
            label [[B:%.*]]<br>
            +; CHECK:       A:<br>
            +; CHECK-NEXT:    [[A_INC:%.*]] = add i32 [[X:%.*]], 1<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       B:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       C:<br>
            +; CHECK-NEXT:    br i1 [[PREDC:%.*]], label [[IRR_GUARD]],
            label [[EXIT:%.*]]<br>
            +; CHECK:       D:<br>
            +; CHECK-NEXT:    [[D_INC:%.*]] = add i32
            [[D_PHI_MOVED:%.*]], 1<br>
            +; CHECK-NEXT:    br i1 [[PREDD:%.*]], label [[EXIT]], label
            [[IRR_GUARD]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    [[RET:%.*]] = phi i32 [
            [[C_PHI_MOVED:%.*]], [[C:%.*]] ], [ [[D_INC]], [[D:%.*]] ]<br>
            +; CHECK-NEXT:    ret i32 [[RET]]<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_C:%.*]] = phi i1 [ true, [[D]] ],
            [ [[PREDB_INV]], [[B]] ], [ [[PREDA:%.*]], [[A]] ], [ false,
            [[C]] ]<br>
            +; CHECK-NEXT:    [[C_PHI_MOVED]] = phi i32 [ [[D_INC]],
            [[D]] ], [ [[Y:%.*]], [[B]] ], [ [[X]], [[A]] ], [
            [[C_PHI_MOVED]], [[C]] ]<br>
            +; CHECK-NEXT:    [[D_PHI_MOVED]] = phi i32 [
            [[D_PHI_MOVED]], [[D]] ], [ [[Y]], [[B]] ], [ [[A_INC]],
            [[A]] ], [ [[C_PHI_MOVED]], [[C]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_C]], label [[C]], label
            [[D]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %PredEntry, label %A, label %B<br>
            +<br>
            +A:<br>
            +  %A.inc = add i32 %X, 1<br>
            +  br i1 %PredA, label %C, label %D<br>
            +<br>
            +B:<br>
            +  br i1 %PredB, label %D, label %C<br>
            +<br>
            +C:<br>
            +  %C.phi = phi i32 [%X, %A], [%Y, %B], [%D.inc, %D]<br>
            +  br i1 %PredC, label %D, label %exit<br>
            +<br>
            +D:<br>
            +  %D.phi = phi i32 [%A.inc, %A], [%Y, %B], [%C.phi, %C]<br>
            +  %D.inc = add i32 %D.phi, 1<br>
            +  br i1 %PredD, label %exit, label %C<br>
            +<br>
            +exit:<br>
            +  %ret = phi i32 [%C.phi, %C], [%D.inc, %D]<br>
            +  ret i32 %ret<br>
            +}<br>
            +<br>
            +define i32 @separate_predecessors(i1 %PredEntry, i1 %PredA,
            i1 %PredB, i1 %PredC, i1 %PredD, i32 %X, i32 %Y) {<br>
            +; CHECK-LABEL: @separate_predecessors(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br i1 [[PREDENTRY:%.*]], label [[A:%.*]],
            label [[B:%.*]]<br>
            +; CHECK:       A:<br>
            +; CHECK-NEXT:    [[A_INC:%.*]] = add i32 [[X:%.*]], 1<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       B:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       C:<br>
            +; CHECK-NEXT:    br i1 [[PREDC:%.*]], label [[EXIT:%.*]],
            label [[IRR_GUARD]]<br>
            +; CHECK:       D:<br>
            +; CHECK-NEXT:    [[D_INC:%.*]] = add i32
            [[D_PHI_MOVED:%.*]], 1<br>
            +; CHECK-NEXT:    br i1 [[PREDD:%.*]], label [[EXIT]], label
            [[IRR_GUARD]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    [[RET:%.*]] = phi i32 [
            [[C_PHI_MOVED:%.*]], [[C:%.*]] ], [ [[D_INC]], [[D:%.*]] ]<br>
            +; CHECK-NEXT:    ret i32 [[RET]]<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_C:%.*]] = phi i1 [ true, [[D]] ],
            [ true, [[A]] ], [ false, [[C]] ], [ false, [[B]] ]<br>
            +; CHECK-NEXT:    [[C_PHI_MOVED]] = phi i32 [ [[D_INC]],
            [[D]] ], [ [[X]], [[A]] ], [ [[C_PHI_MOVED]], [[C]] ], [
            undef, [[B]] ]<br>
            +; CHECK-NEXT:    [[D_PHI_MOVED]] = phi i32 [
            [[D_PHI_MOVED]], [[D]] ], [ undef, [[A]] ], [
            [[C_PHI_MOVED]], [[C]] ], [ [[Y:%.*]], [[B]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_C]], label [[C]], label
            [[D]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %PredEntry, label %A, label %B<br>
            +<br>
            +A:<br>
            +  %A.inc = add i32 %X, 1<br>
            +  br label %C<br>
            +<br>
            +B:<br>
            +  br label %D<br>
            +<br>
            +C:<br>
            +  %C.phi = phi i32 [%X, %A], [%D.inc, %D]<br>
            +  br i1 %PredC, label %exit, label %D<br>
            +<br>
            +D:<br>
            +  %D.phi = phi i32 [%Y, %B], [%C.phi, %C]<br>
            +  %D.inc = add i32 %D.phi, 1<br>
            +  br i1 %PredD, label %exit, label %C<br>
            +<br>
            +exit:<br>
            +  %ret = phi i32 [%C.phi, %C], [%D.inc, %D]<br>
            +  ret i32 %ret<br>
            +}<br>
            +<br>
            +define void @four_headers(i1 %PredEntry, i1 %PredX, i1 
            %PredY, i1 %PredD) {<br>
            +; CHECK-LABEL: @four_headers(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br i1 [[PREDENTRY:%.*]], label [[X:%.*]],
            label [[Y:%.*]]<br>
            +; CHECK:       X:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       Y:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       A:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       B:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       C:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       D:<br>
            +; CHECK-NEXT:    br i1 [[PREDD:%.*]], label [[EXIT:%.*]],
            label [[IRR_GUARD]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_A:%.*]] = phi i1 [ true, [[D:%.*]]
            ], [ [[PREDX:%.*]], [[X]] ], [ false, [[A:%.*]] ], [ false,
            [[B:%.*]] ], [ false, [[Y]] ], [ false, [[C:%.*]] ]<br>
            +; CHECK-NEXT:    [[GUARD_B:%.*]] = phi i1 [ false, [[D]] ],
            [ true, [[X]] ], [ true, [[A]] ], [ false, [[B]] ], [ false,
            [[Y]] ], [ false, [[C]] ]<br>
            +; CHECK-NEXT:    [[GUARD_C:%.*]] = phi i1 [ false, [[D]] ],
            [ false, [[X]] ], [ false, [[A]] ], [ true, [[B]] ], [
            [[PREDY:%.*]], [[Y]] ], [ false, [[C]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A]], label [[A]], label
            [[IRR_GUARD1:%.*]]<br>
            +; CHECK:       irr.guard1:<br>
            +; CHECK-NEXT:    br i1 [[GUARD_B]], label [[B]], label
            [[IRR_GUARD2:%.*]]<br>
            +; CHECK:       irr.guard2:<br>
            +; CHECK-NEXT:    br i1 [[GUARD_C]], label [[C]], label
            [[D]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %PredEntry, label %X, label %Y<br>
            +<br>
            +X:<br>
            +  br i1 %PredX, label %A, label %B<br>
            +<br>
            +Y:<br>
            +  br i1 %PredY, label %C, label %D<br>
            +<br>
            +A:<br>
            +  br label %B<br>
            +<br>
            +B:<br>
            +  br label %C<br>
            +<br>
            +C:<br>
            +  br label %D<br>
            +<br>
            +D:<br>
            +  br i1 %PredD, label %exit, label %A<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            +<br>
            +define i32 @hidden_nodes(i1 %PredEntry, i1 %PredA, i1
            %PredB, i1 %PredC, i1 %PredD, i32 %X, i32 %Y) {<br>
            +; CHECK-LABEL: @hidden_nodes(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       A:<br>
            +; CHECK-NEXT:    [[A_INC:%.*]] = add i32
            [[A_PHI_MOVED:%.*]], 1<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       B:<br>
            +; CHECK-NEXT:    br label [[C:%.*]]<br>
            +; CHECK:       C:<br>
            +; CHECK-NEXT:    [[C_INC:%.*]] = add i32
            [[B_PHI_MOVED:%.*]], 1<br>
            +; CHECK-NEXT:    br label [[D:%.*]]<br>
            +; CHECK:       D:<br>
            +; CHECK-NEXT:    br i1 [[PREDD:%.*]], label [[EXIT:%.*]],
            label [[E:%.*]]<br>
            +; CHECK:       E:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret i32 [[B_PHI_MOVED]]<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_A:%.*]] = phi i1 [ true, [[E]] ],
            [ [[PREDENTRY:%.*]], [[ENTRY:%.*]] ], [ false, [[A:%.*]] ]<br>
            +; CHECK-NEXT:    [[A_PHI_MOVED]] = phi i32 [ [[C_INC]],
            [[E]] ], [ [[X:%.*]], [[ENTRY]] ], [ [[A_PHI_MOVED]], [[A]]
            ]<br>
            +; CHECK-NEXT:    [[B_PHI_MOVED]] = phi i32 [ undef, [[E]]
            ], [ [[Y:%.*]], [[ENTRY]] ], [ [[A_INC]], [[A]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A]], label [[A]], label
            [[B:%.*]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %PredEntry, label %A, label %B<br>
            +<br>
            +A:<br>
            +  %A.phi = phi i32 [%X, %entry], [%C.inc, %E]<br>
            +  %A.inc = add i32 %A.phi, 1<br>
            +  br label %B<br>
            +<br>
            +B:<br>
            +  %B.phi = phi i32 [%A.inc, %A], [%Y, %entry]<br>
            +  br label %C<br>
            +<br>
            +C:<br>
            +  %C.inc = add i32 %B.phi, 1<br>
            +  br label %D<br>
            +<br>
            +D:<br>
            +  br i1 %PredD, label %exit, label %E<br>
            +<br>
            +E:<br>
            +  br label %A<br>
            +<br>
            +exit:<br>
            +  ret i32 %B.phi<br>
            +}<br>
            <br>
            diff  --git a/llvm/test/Transforms/FixIrreducible/nested.ll
            b/llvm/test/Transforms/FixIrreducible/nested.ll<br>
            new file mode 100644<br>
            index 000000000000..85f7d39920b9<br>
            --- /dev/null<br>
            +++ b/llvm/test/Transforms/FixIrreducible/nested.ll<br>
            @@ -0,0 +1,433 @@<br>
            +; NOTE: Assertions have been autogenerated by
            utils/update_test_checks.py<br>
            +; RUN: opt < %s -fix-irreducible -S | FileCheck %s
            -check-prefix=CHECK<br>
            +<br>
            +define void @nested_irr_top_level(i1 %Pred0, i1 %Pred1, i1
            %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5) {<br>
            +; CHECK-LABEL: @nested_irr_top_level(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       A1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]<br>
            +; CHECK:       B1:<br>
            +; CHECK-NEXT:    br i1 [[PRED2:%.*]], label [[IRR_GUARD1]],
            label [[A3:%.*]]<br>
            +; CHECK:       B2:<br>
            +; CHECK-NEXT:    br i1 [[PRED3:%.*]], label [[IRR_GUARD1]],
            label [[A3]]<br>
            +; CHECK:       A3:<br>
            +; CHECK-NEXT:    br i1 [[PRED4:%.*]], label [[IRR_GUARD]],
            label [[EXIT:%.*]]<br>
            +; CHECK:       A2:<br>
            +; CHECK-NEXT:    br i1 [[PRED5:%.*]], label [[IRR_GUARD]],
            label [[EXIT]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_A1:%.*]] = phi i1 [ true,
            [[A2:%.*]] ], [ [[PRED0:%.*]], [[ENTRY:%.*]] ], [ false,
            [[A3]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A1]], label [[A1:%.*]],
            label [[A2]]<br>
            +; CHECK:       irr.guard1:<br>
            +; CHECK-NEXT:    [[GUARD_B1:%.*]] = phi i1 [ true,
            [[B2:%.*]] ], [ [[PRED1:%.*]], [[A1]] ], [ false, [[B1:%.*]]
            ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_B1]], label [[B1]], label
            [[B2]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %Pred0, label %A1, label %A2<br>
            +<br>
            +A1:<br>
            +  br i1 %Pred1, label %B1, label %B2<br>
            +<br>
            +B1:<br>
            +  br i1 %Pred2, label %B2, label %A3<br>
            +<br>
            +B2:<br>
            +  br i1 %Pred3, label %B1, label %A3<br>
            +<br>
            +A3:<br>
            +  br i1 %Pred4, label %A2, label %exit<br>
            +<br>
            +A2:<br>
            +  br i1 %Pred5, label %A1, label %exit<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            +<br>
            +define void @nested_irr_in_loop(i1 %Pred0, i1 %Pred1, i1
            %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6) {<br>
            +; CHECK-LABEL: @nested_irr_in_loop(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[H1:%.*]]<br>
            +; CHECK:       H1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       A1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]<br>
            +; CHECK:       B1:<br>
            +; CHECK-NEXT:    br i1 [[PRED2:%.*]], label [[IRR_GUARD1]],
            label [[A3:%.*]]<br>
            +; CHECK:       B2:<br>
            +; CHECK-NEXT:    br i1 [[PRED3:%.*]], label [[IRR_GUARD1]],
            label [[A3]]<br>
            +; CHECK:       A3:<br>
            +; CHECK-NEXT:    br i1 [[PRED4:%.*]], label [[IRR_GUARD]],
            label [[L1:%.*]]<br>
            +; CHECK:       A2:<br>
            +; CHECK-NEXT:    br i1 [[PRED5:%.*]], label [[IRR_GUARD]],
            label [[L1]]<br>
            +; CHECK:       L1:<br>
            +; CHECK-NEXT:    br i1 [[PRED6:%.*]], label [[EXIT:%.*]],
            label [[H1]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_A1:%.*]] = phi i1 [ true,
            [[A2:%.*]] ], [ [[PRED0:%.*]], [[H1]] ], [ false, [[A3]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A1]], label [[A1:%.*]],
            label [[A2]]<br>
            +; CHECK:       irr.guard1:<br>
            +; CHECK-NEXT:    [[GUARD_B1:%.*]] = phi i1 [ true,
            [[B2:%.*]] ], [ [[PRED1:%.*]], [[A1]] ], [ false, [[B1:%.*]]
            ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_B1]], label [[B1]], label
            [[B2]]<br>
            +;<br>
            +entry:<br>
            +  br label %H1<br>
            +<br>
            +H1:<br>
            +  br i1 %Pred0, label %A1, label %A2<br>
            +<br>
            +A1:<br>
            +  br i1 %Pred1, label %B1, label %B2<br>
            +<br>
            +B1:<br>
            +  br i1 %Pred2, label %B2, label %A3<br>
            +<br>
            +B2:<br>
            +  br i1 %Pred3, label %B1, label %A3<br>
            +<br>
            +A3:<br>
            +  br i1 %Pred4, label %A2, label %L1<br>
            +<br>
            +A2:<br>
            +  br i1 %Pred5, label %A1, label %L1<br>
            +<br>
            +L1:<br>
            +  br i1 %Pred6, label %exit, label %H1<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            +<br>
            +define void @loop_in_irr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {<br>
            +; CHECK-LABEL: @loop_in_irr(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       A1:<br>
            +; CHECK-NEXT:    br label [[H1:%.*]]<br>
            +; CHECK:       H1:<br>
            +; CHECK-NEXT:    br label [[L1:%.*]]<br>
            +; CHECK:       L1:<br>
            +; CHECK-NEXT:    br i1 [[PRED1:%.*]], label [[H1]], label
            [[A3:%.*]]<br>
            +; CHECK:       A3:<br>
            +; CHECK-NEXT:    br i1 [[PRED2:%.*]], label [[IRR_GUARD]],
            label [[EXIT:%.*]]<br>
            +; CHECK:       A2:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_A1:%.*]] = phi i1 [ true,
            [[A2:%.*]] ], [ [[PRED0:%.*]], [[ENTRY:%.*]] ], [ false,
            [[A3]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A1]], label [[A1:%.*]],
            label [[A2]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %Pred0, label %A1, label %A2<br>
            +<br>
            +A1:<br>
            +  br label %H1<br>
            +<br>
            +H1:<br>
            +  br label %L1<br>
            +<br>
            +L1:<br>
            +  br i1 %Pred1, label %H1, label %A3<br>
            +<br>
            +A3:<br>
            +  br i1 %Pred2, label %A2, label %exit<br>
            +<br>
            +A2:<br>
            +  br label %A1<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            +<br>
            +define void @loop_in_irr_shared_header(i1 %Pred0, i1
            %Pred1, i1 %Pred2) {<br>
            +; CHECK-LABEL: @loop_in_irr_shared_header(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       H1:<br>
            +; CHECK-NEXT:    br label [[L1:%.*]]<br>
            +; CHECK:       L1:<br>
            +; CHECK-NEXT:    br i1 [[PRED1:%.*]], label [[IRR_GUARD]],
            label [[A3:%.*]]<br>
            +; CHECK:       A3:<br>
            +; CHECK-NEXT:    br i1 [[PRED2:%.*]], label [[IRR_GUARD]],
            label [[EXIT:%.*]]<br>
            +; CHECK:       A2:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_H1:%.*]] = phi i1 [ true,
            [[A2:%.*]] ], [ true, [[L1]] ], [ [[PRED0:%.*]],
            [[ENTRY:%.*]] ], [ false, [[A3]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_H1]], label [[H1:%.*]],
            label [[A2]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %Pred0, label %H1, label %A2<br>
            +<br>
            +H1:<br>
            +  br label %L1<br>
            +<br>
            +L1:<br>
            +  br i1 %Pred1, label %H1, label %A3<br>
            +<br>
            +A3:<br>
            +  br i1 %Pred2, label %A2, label %exit<br>
            +<br>
            +A2:<br>
            +  br label %H1<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            +<br>
            +define void @siblings_top_level(i1 %Pred0, i1 %Pred1, i1
            %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6) {<br>
            +; CHECK-LABEL: @siblings_top_level(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br i1 [[PRED0:%.*]], label [[H1:%.*]],
            label [[FORK1:%.*]]<br>
            +; CHECK:       H1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]<br>
            +; CHECK:       A1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD1]]<br>
            +; CHECK:       A2:<br>
            +; CHECK-NEXT:    br i1 [[PRED2:%.*]], label [[IRR_GUARD1]],
            label [[L1:%.*]]<br>
            +; CHECK:       L1:<br>
            +; CHECK-NEXT:    br i1 [[PRED3:%.*]], label [[H1]], label
            [[EXIT:%.*]]<br>
            +; CHECK:       fork1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       B1:<br>
            +; CHECK-NEXT:    br label [[H2:%.*]]<br>
            +; CHECK:       H2:<br>
            +; CHECK-NEXT:    br label [[L2:%.*]]<br>
            +; CHECK:       L2:<br>
            +; CHECK-NEXT:    br i1 [[PRED5:%.*]], label [[H2]], label
            [[IRR_GUARD]]<br>
            +; CHECK:       B2:<br>
            +; CHECK-NEXT:    br i1 [[PRED6:%.*]], label [[IRR_GUARD]],
            label [[EXIT]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_B1:%.*]] = phi i1 [ true,
            [[B2:%.*]] ], [ [[PRED4:%.*]], [[FORK1]] ], [ false, [[L2]]
            ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_B1]], label [[B1:%.*]],
            label [[B2]]<br>
            +; CHECK:       irr.guard1:<br>
            +; CHECK-NEXT:    [[GUARD_A1:%.*]] = phi i1 [ true,
            [[A2:%.*]] ], [ [[PRED1:%.*]], [[H1]] ], [ false, [[A1:%.*]]
            ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A1]], label [[A1]], label
            [[A2]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %Pred0, label %H1, label %fork1<br>
            +<br>
            +H1:<br>
            +  br i1 %Pred1, label %A1, label %A2<br>
            +<br>
            +A1:<br>
            +  br label %A2<br>
            +<br>
            +A2:<br>
            +  br i1 %Pred2, label %A1, label %L1<br>
            +<br>
            +L1:<br>
            +  br i1 %Pred3, label %H1, label %exit<br>
            +<br>
            +fork1:<br>
            +  br i1 %Pred4, label %B1, label %B2<br>
            +<br>
            +B1:<br>
            +  br label %H2<br>
            +<br>
            +H2:<br>
            +  br label %L2<br>
            +<br>
            +L2:<br>
            +  br i1 %Pred5, label %H2, label %B2<br>
            +<br>
            +B2:<br>
            +  br i1 %Pred6, label %B1, label %exit<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            +<br>
            +define void @siblings_in_loop(i1 %Pred0, i1 %Pred1, i1
            %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6, i1
            %Pred7) {<br>
            +; CHECK-LABEL: @siblings_in_loop(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[H0:%.*]]<br>
            +; CHECK:       H0:<br>
            +; CHECK-NEXT:    br i1 [[PRED0:%.*]], label [[H1:%.*]],
            label [[FORK1:%.*]]<br>
            +; CHECK:       H1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]<br>
            +; CHECK:       A1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD1]]<br>
            +; CHECK:       A2:<br>
            +; CHECK-NEXT:    br i1 [[PRED2:%.*]], label [[IRR_GUARD1]],
            label [[L1:%.*]]<br>
            +; CHECK:       L1:<br>
            +; CHECK-NEXT:    br i1 [[PRED3:%.*]], label [[H1]], label
            [[L0:%.*]]<br>
            +; CHECK:       fork1:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       B1:<br>
            +; CHECK-NEXT:    br label [[H2:%.*]]<br>
            +; CHECK:       H2:<br>
            +; CHECK-NEXT:    br label [[L2:%.*]]<br>
            +; CHECK:       L2:<br>
            +; CHECK-NEXT:    br i1 [[PRED5:%.*]], label [[H2]], label
            [[IRR_GUARD]]<br>
            +; CHECK:       B2:<br>
            +; CHECK-NEXT:    br i1 [[PRED6:%.*]], label [[IRR_GUARD]],
            label [[L0]]<br>
            +; CHECK:       L0:<br>
            +; CHECK-NEXT:    br i1 [[PRED7:%.*]], label [[EXIT:%.*]],
            label [[H0]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_B1:%.*]] = phi i1 [ true,
            [[B2:%.*]] ], [ [[PRED4:%.*]], [[FORK1]] ], [ false, [[L2]]
            ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_B1]], label [[B1:%.*]],
            label [[B2]]<br>
            +; CHECK:       irr.guard1:<br>
            +; CHECK-NEXT:    [[GUARD_A1:%.*]] = phi i1 [ true,
            [[A2:%.*]] ], [ [[PRED1:%.*]], [[H1]] ], [ false, [[A1:%.*]]
            ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A1]], label [[A1]], label
            [[A2]]<br>
            +;<br>
            +entry:<br>
            +  br label %H0<br>
            +<br>
            +H0:<br>
            +  br i1 %Pred0, label %H1, label %fork1<br>
            +<br>
            +H1:<br>
            +  br i1 %Pred1, label %A1, label %A2<br>
            +<br>
            +A1:<br>
            +  br label %A2<br>
            +<br>
            +A2:<br>
            +  br i1 %Pred2, label %A1, label %L1<br>
            +<br>
            +L1:<br>
            +  br i1 %Pred3, label %H1, label %L0<br>
            +<br>
            +fork1:<br>
            +  br i1 %Pred4, label %B1, label %B2<br>
            +<br>
            +B1:<br>
            +  br label %H2<br>
            +<br>
            +H2:<br>
            +  br label %L2<br>
            +<br>
            +L2:<br>
            +  br i1 %Pred5, label %H2, label %B2<br>
            +<br>
            +B2:<br>
            +  br i1 %Pred6, label %B1, label %L0<br>
            +<br>
            +L0:<br>
            +  br i1 %Pred7, label %exit, label %H0<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            +<br>
            +define void @irreducible_mountain_bug(i1 %Pred0, i1 %Pred1,
            i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6, i1
            %Pred7, i1 %Pred8, i1 %Pred9, i1 %Pred10, i1 %Pred11, i1
            %Pred12, i1 %Pred13) {<br>
            +; CHECK-LABEL: @irreducible_mountain_bug(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br i1 [[PRED0:%.*]], label [[IF_END:%.*]],
            label [[IF_THEN:%.*]]<br>
            +; CHECK:       if.end:<br>
            +; CHECK-NEXT:    br i1 [[PRED1:%.*]], label
            [[IF_THEN7:%.*]], label [[IF_ELSE:%.*]]<br>
            +; CHECK:       if.then7:<br>
            +; CHECK-NEXT:    br label [[IF_END16:%.*]]<br>
            +; CHECK:       if.else:<br>
            +; CHECK-NEXT:    br label [[IF_END16]]<br>
            +; CHECK:       if.end16:<br>
            +; CHECK-NEXT:    br i1 [[PRED2:%.*]], label
            [[WHILE_COND_PREHEADER:%.*]], label [[IF_THEN39:%.*]]<br>
            +; CHECK:       while.cond.preheader:<br>
            +; CHECK-NEXT:    br label [[WHILE_COND:%.*]]<br>
            +; CHECK:       while.cond:<br>
            +; CHECK-NEXT:    br i1 [[PRED3:%.*]], label
            [[IRR_GUARD:%.*]], label [[LOR_RHS:%.*]]<br>
            +; CHECK:       cond.true49:<br>
            +; CHECK-NEXT:    br i1 [[PRED4:%.*]], label
            [[IF_THEN69:%.*]], label [[WHILE_BODY63:%.*]]<br>
            +; CHECK:       while.body63:<br>
            +; CHECK-NEXT:    br i1 [[PRED5:%.*]], label [[EXIT:%.*]],
            label [[WHILE_COND47:%.*]]<br>
            +; CHECK:       while.cond47:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       cond.end61:<br>
            +; CHECK-NEXT:    br i1 [[PRED7:%.*]], label
            [[WHILE_BODY63]], label [[WHILE_COND]]<br>
            +; CHECK:       if.then69:<br>
            +; CHECK-NEXT:    br i1 [[PRED8:%.*]], label [[EXIT]], label
            [[WHILE_COND]]<br>
            +; CHECK:       lor.rhs:<br>
            +; CHECK-NEXT:    br i1 [[PRED9:%.*]], label [[IRR_GUARD]],
            label [[WHILE_END76:%.*]]<br>
            +; CHECK:       while.end76:<br>
            +; CHECK-NEXT:    br label [[EXIT]]<br>
            +; CHECK:       if.then39:<br>
            +; CHECK-NEXT:    br i1 [[PRED10:%.*]], label [[EXIT]],
            label [[IF_END_I145:%.*]]<br>
            +; CHECK:       if.end.i145:<br>
            +; CHECK-NEXT:    br i1 [[PRED11:%.*]], label [[EXIT]],
            label [[IF_END8_I149:%.*]]<br>
            +; CHECK:       if.end8.i149:<br>
            +; CHECK-NEXT:    br label [[EXIT]]<br>
            +; CHECK:       if.then:<br>
            +; CHECK-NEXT:    br i1 [[PRED12:%.*]], label [[EXIT]],
            label [[IF_END_I:%.*]]<br>
            +; CHECK:       if.end.i:<br>
            +; CHECK-NEXT:    br i1 [[PRED13:%.*]], label [[EXIT]],
            label [[IF_END8_I:%.*]]<br>
            +; CHECK:       if.end8.i:<br>
            +; CHECK-NEXT:    br label [[EXIT]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_COND_TRUE49:%.*]] = phi i1 [
            [[PRED6:%.*]], [[WHILE_COND47]] ], [ true, [[WHILE_COND]] ],
            [ false, [[LOR_RHS]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_COND_TRUE49]], label
            [[COND_TRUE49:%.*]], label [[COND_END61:%.*]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %Pred0, label %if.end, label %if.then<br>
            +<br>
            +if.end:<br>
            +  br i1 %Pred1, label %if.then7, label %if.else<br>
            +<br>
            +if.then7:<br>
            +  br label %if.end16<br>
            +<br>
            +if.else:<br>
            +  br label %if.end16<br>
            +<br>
            +if.end16:<br>
            +  br i1 %Pred2, label %while.cond.preheader, label
            %if.then39<br>
            +<br>
            +while.cond.preheader:<br>
            +  br label %while.cond<br>
            +<br>
            +while.cond:<br>
            +  br i1 %Pred3, label %cond.true49, label %lor.rhs<br>
            +<br>
            +cond.true49:<br>
            +  br i1 %Pred4, label %if.then69, label %while.body63<br>
            +<br>
            +while.body63:<br>
            +  br i1 %Pred5, label %exit, label %while.cond47<br>
            +<br>
            +while.cond47:<br>
            +  br i1 %Pred6, label %cond.true49, label %cond.end61<br>
            +<br>
            +cond.end61:<br>
            +  br i1 %Pred7, label %while.body63, label %while.cond<br>
            +<br>
            +if.then69:<br>
            +  br i1 %Pred8, label %exit, label %while.cond<br>
            +<br>
            +lor.rhs:<br>
            +  br i1 %Pred9, label %cond.end61, label %while.end76<br>
            +<br>
            +while.end76:<br>
            +  br label %exit<br>
            +<br>
            +if.then39:<br>
            +  br i1 %Pred10, label %exit, label %if.end.i145<br>
            +<br>
            +if.end.i145:<br>
            +  br i1 %Pred11, label %exit, label %if.end8.i149<br>
            +<br>
            +if.end8.i149:<br>
            +  br label %exit<br>
            +<br>
            +if.then:<br>
            +  br i1 %Pred12, label %exit, label %if.end.i<br>
            +<br>
            +if.end.i:<br>
            +  br i1 %Pred13, label %exit, label %if.end8.i<br>
            +<br>
            +if.end8.i:<br>
            +  br label %exit<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            <br>
            diff  --git a/llvm/test/Transforms/FixIrreducible/switch.ll
            b/llvm/test/Transforms/FixIrreducible/switch.ll<br>
            new file mode 100644<br>
            index 000000000000..0073560af888<br>
            --- /dev/null<br>
            +++ b/llvm/test/Transforms/FixIrreducible/switch.ll<br>
            @@ -0,0 +1,43 @@<br>
            +; NOTE: Assertions have been autogenerated by
            utils/update_test_checks.py<br>
            +; RUN: opt < %s -fix-irreducible -S | FileCheck %s<br>
            +<br>
            +define void @loop_1(i32 %Value, i1 %PredEntry, i1 %PredD) {<br>
            +; CHECK-LABEL: @loop_1(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       A:<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD]]<br>
            +; CHECK:       B:<br>
            +; CHECK-NEXT:    br label [[NODEBLOCK:%.*]]<br>
            +; CHECK:       NodeBlock:<br>
            +; CHECK-NEXT:    [[PIVOT:%.*]] = icmp slt i32
            [[VALUE:%.*]], 1<br>
            +; CHECK-NEXT:    br i1 [[PIVOT]], label [[LEAFBLOCK:%.*]],
            label [[LEAFBLOCK1:%.*]]<br>
            +; CHECK:       LeafBlock1:<br>
            +; CHECK-NEXT:    [[SWITCHLEAF2:%.*]] = icmp eq i32
            [[VALUE]], 1<br>
            +; CHECK-NEXT:    br i1 [[SWITCHLEAF2]], label
            [[IRR_GUARD]], label [[NEWDEFAULT:%.*]]<br>
            +; CHECK:       LeafBlock:<br>
            +; CHECK-NEXT:    [[SWITCHLEAF:%.*]] = icmp eq i32
            [[VALUE]], 0<br>
            +; CHECK-NEXT:    br i1 [[SWITCHLEAF]], label [[IRR_GUARD]],
            label [[NEWDEFAULT]]<br>
            +; CHECK:       NewDefault:<br>
            +; CHECK-NEXT:    br label [[EXIT:%.*]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_A:%.*]] = phi i1 [ true,
            [[LEAFBLOCK]] ], [ [[PREDENTRY:%.*]], [[ENTRY:%.*]] ], [
            false, [[LEAFBLOCK1]] ], [ false, [[A:%.*]] ]<br>
            +; CHECK-NEXT:    br i1 [[GUARD_A]], label [[A]], label
            [[B:%.*]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %PredEntry, label %A, label %B<br>
            +<br>
            +A:<br>
            +  br label %B<br>
            +<br>
            +B:<br>
            +  switch i32 %Value, label %exit [<br>
            +  i32 0, label %A<br>
            +  i32 1, label %B<br>
            +  ]<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            <br>
            diff  --git
            a/llvm/test/Transforms/StructurizeCFG/workarounds/needs-fix-reducible.ll
b/llvm/test/Transforms/StructurizeCFG/workarounds/needs-fix-reducible.ll<br>
            new file mode 100644<br>
            index 000000000000..f4b1f7dbaed9<br>
            --- /dev/null<br>
            +++
            b/llvm/test/Transforms/StructurizeCFG/workarounds/needs-fix-reducible.ll<br>
            @@ -0,0 +1,60 @@<br>
            +; NOTE: Assertions have been autogenerated by
            utils/update_test_checks.py<br>
            +; RUN: opt < %s -fix-irreducible -structurizecfg -S |
            FileCheck %s<br>
            +<br>
            +; Both B1 and B4 are headers of an irreducible cycle. But
            in the<br>
            +; structurized version, B1 dominates B4. The program is
            structurized<br>
            +; correctly when the irreducible cycle is fixed.<br>
            +<br>
            +define void @irreducible(i1 %PredEntry, i1 %PredB1, i1
            %PredB2, i1 %PredB3, i1 %PredB4)<br>
            +; CHECK-LABEL: @irreducible(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    [[PREDB2_INV:%.*]] = xor i1
            [[PREDB2:%.*]], true<br>
            +; CHECK-NEXT:    [[PREDB1_INV:%.*]] = xor i1
            [[PREDB1:%.*]], true<br>
            +; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]<br>
            +; CHECK:       Flow:<br>
            +; CHECK-NEXT:    [[TMP0:%.*]] = phi i1 [ [[PREDB4:%.*]],
            [[B4:%.*]] ], [ false, [[IRR_GUARD]] ]<br>
            +; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ false, [[B4]] ], [
            true, [[IRR_GUARD]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP1]], label [[B1:%.*]], label
            [[FLOW1:%.*]]<br>
            +; CHECK:       B1:<br>
            +; CHECK-NEXT:    br label [[FLOW1]]<br>
            +; CHECK:       Flow1:<br>
            +; CHECK-NEXT:    [[TMP2:%.*]] = phi i1 [ [[PREDB1_INV]],
            [[B1]] ], [ [[TMP0]], [[FLOW:%.*]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP2]], label [[B2:%.*]], label
            [[FLOW2:%.*]]<br>
            +; CHECK:       B2:<br>
            +; CHECK-NEXT:    br i1 [[PREDB2_INV]], label [[B3:%.*]],
            label [[FLOW3:%.*]]<br>
            +; CHECK:       Flow2:<br>
            +; CHECK-NEXT:    [[TMP3:%.*]] = phi i1 [ [[TMP4:%.*]],
            [[FLOW3]] ], [ true, [[FLOW1]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP3]], label [[EXIT:%.*]], label
            [[IRR_GUARD]]<br>
            +; CHECK:       B3:<br>
            +; CHECK-NEXT:    br label [[FLOW3]]<br>
            +; CHECK:       B4:<br>
            +; CHECK-NEXT:    br label [[FLOW]]<br>
            +; CHECK:       Flow3:<br>
            +; CHECK-NEXT:    [[TMP4]] = phi i1 [ false, [[B3]] ], [
            true, [[B2]] ]<br>
            +; CHECK-NEXT:    br label [[FLOW2]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_B1:%.*]] = phi i1 [
            [[PREDENTRY:%.*]], [[ENTRY:%.*]] ], [ [[PREDB3:%.*]],
            [[FLOW2]] ]<br>
            +; CHECK-NEXT:    [[TMP5:%.*]] = xor i1 [[GUARD_B1]], true<br>
            +; CHECK-NEXT:    br i1 [[TMP5]], label [[B4]], label
            [[FLOW]]<br>
            +;<br>
            +{<br>
            +entry:<br>
            +  br i1 %PredEntry, label %B1, label %B4<br>
            +<br>
            +B1:<br>
            +  br i1 %PredB1, label %exit, label %B2<br>
            +<br>
            +B2:<br>
            +  br i1 %PredB2, label %exit, label %B3<br>
            +<br>
            +B3:<br>
            +  br i1 %PredB3, label %B1, label %B4<br>
            +<br>
            +B4:<br>
            +  br i1 %PredB4, label %B2, label %exit<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            <br>
            diff  --git
            a/llvm/test/Transforms/StructurizeCFG/workarounds/needs-fr-ule.ll
b/llvm/test/Transforms/StructurizeCFG/workarounds/needs-fr-ule.ll<br>
            new file mode 100644<br>
            index 000000000000..1ae1478cff9d<br>
            --- /dev/null<br>
            +++
            b/llvm/test/Transforms/StructurizeCFG/workarounds/needs-fr-ule.ll<br>
            @@ -0,0 +1,186 @@<br>
            +; NOTE: Assertions have been autogenerated by
            utils/update_test_checks.py<br>
            +; RUN: opt < %s -fix-irreducible -unify-loop-exits
            -structurizecfg -S | FileCheck %s<br>
            +define void @irreducible_mountain_bug(i1 %Pred0, i1 %Pred1,
            i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6, i1
            %Pred7, i1 %Pred8, i1 %Pred9, i1 %Pred10, i1 %Pred11, i1
            %Pred12, i1 %Pred13) {<br>
            +; CHECK-LABEL: @irreducible_mountain_bug(<br>
            +; CHECK-NEXT:  entry:<br>
            +; CHECK-NEXT:    [[PRED0_INV:%.*]] = xor i1 [[PRED0:%.*]],
            true<br>
            +; CHECK-NEXT:    [[PRED1_INV:%.*]] = xor i1 [[PRED1:%.*]],
            true<br>
            +; CHECK-NEXT:    [[PRED2_INV:%.*]] = xor i1 [[PRED2:%.*]],
            true<br>
            +; CHECK-NEXT:    [[PRED3_INV:%.*]] = xor i1 [[PRED3:%.*]],
            true<br>
            +; CHECK-NEXT:    [[PRED5_INV:%.*]] = xor i1 [[PRED5:%.*]],
            true<br>
            +; CHECK-NEXT:    [[PRED4_INV:%.*]] = xor i1 [[PRED4:%.*]],
            true<br>
            +; CHECK-NEXT:    [[PRED10_INV:%.*]] = xor i1
            [[PRED10:%.*]], true<br>
            +; CHECK-NEXT:    [[PRED11_INV:%.*]] = xor i1
            [[PRED11:%.*]], true<br>
            +; CHECK-NEXT:    [[PRED12_INV:%.*]] = xor i1
            [[PRED12:%.*]], true<br>
            +; CHECK-NEXT:    [[PRED13_INV:%.*]] = xor i1
            [[PRED13:%.*]], true<br>
            +; CHECK-NEXT:    br i1 [[PRED0_INV]], label
            [[IF_THEN:%.*]], label [[FLOW18:%.*]]<br>
            +; CHECK:       Flow18:<br>
            +; CHECK-NEXT:    [[TMP0:%.*]] = phi i1 [ false,
            [[FLOW3:%.*]] ], [ true, [[ENTRY:%.*]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_END:%.*]],
            label [[FLOW19:%.*]]<br>
            +; CHECK:       if.end:<br>
            +; CHECK-NEXT:    br i1 [[PRED1_INV]], label
            [[IF_ELSE:%.*]], label [[FLOW17:%.*]]<br>
            +; CHECK:       Flow17:<br>
            +; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ false, [[IF_ELSE]]
            ], [ true, [[IF_END]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP1]], label [[IF_THEN7:%.*]],
            label [[IF_END16:%.*]]<br>
            +; CHECK:       if.then7:<br>
            +; CHECK-NEXT:    br label [[IF_END16]]<br>
            +; CHECK:       if.else:<br>
            +; CHECK-NEXT:    br label [[FLOW17]]<br>
            +; CHECK:       Flow19:<br>
            +; CHECK-NEXT:    br label [[EXIT:%.*]]<br>
            +; CHECK:       if.end16:<br>
            +; CHECK-NEXT:    br i1 [[PRED2_INV]], label
            [[IF_THEN39:%.*]], label [[FLOW15:%.*]]<br>
            +; CHECK:       Flow15:<br>
            +; CHECK-NEXT:    [[TMP2:%.*]] = phi i1 [ false,
            [[FLOW5:%.*]] ], [ true, [[IF_END16]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP2]], label
            [[WHILE_COND_PREHEADER:%.*]], label [[FLOW16:%.*]]<br>
            +; CHECK:       while.cond.preheader:<br>
            +; CHECK-NEXT:    br label [[WHILE_COND:%.*]]<br>
            +; CHECK:       Flow16:<br>
            +; CHECK-NEXT:    br label [[FLOW19]]<br>
            +; CHECK:       while.cond:<br>
            +; CHECK-NEXT:    br i1 [[PRED3_INV]], label
            [[LOR_RHS:%.*]], label [[FLOW11:%.*]]<br>
            +; CHECK:       Flow7:<br>
            +; CHECK-NEXT:    [[TMP3:%.*]] = phi i1 [ [[PRED7:%.*]],
            [[COND_END61:%.*]] ], [ false, [[IRR_GUARD:%.*]] ]<br>
            +; CHECK-NEXT:    [[TMP4:%.*]] = phi i1 [ false,
            [[COND_END61]] ], [ true, [[IRR_GUARD]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP4]], label [[COND_TRUE49:%.*]],
            label [[FLOW8:%.*]]<br>
            +; CHECK:       cond.true49:<br>
            +; CHECK-NEXT:    br label [[FLOW8]]<br>
            +; CHECK:       Flow8:<br>
            +; CHECK-NEXT:    [[TMP5:%.*]] = phi i1 [ false,
            [[COND_TRUE49]] ], [ true, [[FLOW7:%.*]] ]<br>
            +; CHECK-NEXT:    [[TMP6:%.*]] = phi i1 [ [[PRED4_INV]],
            [[COND_TRUE49]] ], [ [[TMP3]], [[FLOW7]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP6]], label
            [[WHILE_BODY63:%.*]], label [[FLOW9:%.*]]<br>
            +; CHECK:       while.body63:<br>
            +; CHECK-NEXT:    br i1 [[PRED5_INV]], label
            [[WHILE_COND47:%.*]], label [[FLOW10:%.*]]<br>
            +; CHECK:       Flow9:<br>
            +; CHECK-NEXT:    [[TMP7:%.*]] = phi i1 [ true, [[FLOW10]]
            ], [ false, [[FLOW8]] ]<br>
            +; CHECK-NEXT:    [[TMP8:%.*]] = phi i1 [ false, [[FLOW10]]
            ], [ [[TMP5]], [[FLOW8]] ]<br>
            +; CHECK-NEXT:    [[TMP9:%.*]] = phi i1 [ [[TMP18:%.*]],
            [[FLOW10]] ], [ true, [[FLOW8]] ]<br>
            +; CHECK-NEXT:    [[TMP10:%.*]] = xor i1 [[TMP7]], true<br>
            +; CHECK-NEXT:    [[TMP11:%.*]] = xor i1 [[TMP8]], true<br>
            +; CHECK-NEXT:    br i1 [[TMP9]], label
            [[LOOP_EXIT_GUARD1:%.*]], label [[IRR_GUARD]]<br>
            +; CHECK:       while.cond47:<br>
            +; CHECK-NEXT:    br label [[FLOW10]]<br>
            +; CHECK:       cond.end61:<br>
            +; CHECK-NEXT:    br label [[FLOW7]]<br>
            +; CHECK:       Flow13:<br>
            +; CHECK-NEXT:    [[TMP12:%.*]] = phi i1 [ false,
            [[FLOW14:%.*]] ], [ true, [[LOOP_EXIT_GUARD1]] ]<br>
            +; CHECK-NEXT:    [[TMP13:%.*]] = phi i1 [ [[TMP17:%.*]],
            [[FLOW14]] ], [ [[TMP11]], [[LOOP_EXIT_GUARD1]] ]<br>
            +; CHECK-NEXT:    br label [[FLOW12:%.*]]<br>
            +; CHECK:       if.then69:<br>
            +; CHECK-NEXT:    br label [[FLOW14]]<br>
            +; CHECK:       lor.rhs:<br>
            +; CHECK-NEXT:    br label [[FLOW11]]<br>
            +; CHECK:       while.end76:<br>
            +; CHECK-NEXT:    br label [[FLOW6:%.*]]<br>
            +; CHECK:       if.then39:<br>
            +; CHECK-NEXT:    br i1 [[PRED10_INV]], label
            [[IF_END_I145:%.*]], label [[FLOW5]]<br>
            +; CHECK:       if.end.i145:<br>
            +; CHECK-NEXT:    br i1 [[PRED11_INV]], label
            [[IF_END8_I149:%.*]], label [[FLOW4:%.*]]<br>
            +; CHECK:       if.end8.i149:<br>
            +; CHECK-NEXT:    br label [[FLOW4]]<br>
            +; CHECK:       if.then:<br>
            +; CHECK-NEXT:    br i1 [[PRED12_INV]], label
            [[IF_END_I:%.*]], label [[FLOW3]]<br>
            +; CHECK:       if.end.i:<br>
            +; CHECK-NEXT:    br i1 [[PRED13_INV]], label
            [[IF_END8_I:%.*]], label [[FLOW:%.*]]<br>
            +; CHECK:       if.end8.i:<br>
            +; CHECK-NEXT:    br label [[FLOW]]<br>
            +; CHECK:       Flow:<br>
            +; CHECK-NEXT:    br label [[FLOW3]]<br>
            +; CHECK:       Flow3:<br>
            +; CHECK-NEXT:    br label [[FLOW18]]<br>
            +; CHECK:       Flow4:<br>
            +; CHECK-NEXT:    br label [[FLOW5]]<br>
            +; CHECK:       Flow5:<br>
            +; CHECK-NEXT:    br label [[FLOW15]]<br>
            +; CHECK:       Flow6:<br>
            +; CHECK-NEXT:    br label [[FLOW16]]<br>
            +; CHECK:       exit:<br>
            +; CHECK-NEXT:    ret void<br>
            +; CHECK:       Flow11:<br>
            +; CHECK-NEXT:    [[TMP14:%.*]] = phi i1 [ false,
            [[LOR_RHS]] ], [ true, [[WHILE_COND]] ]<br>
            +; CHECK-NEXT:    [[TMP15:%.*]] = phi i1 [ [[PRED9:%.*]],
            [[LOR_RHS]] ], [ [[PRED3]], [[WHILE_COND]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP15]], label [[IRR_GUARD]],
            label [[FLOW12]]<br>
            +; CHECK:       irr.guard:<br>
            +; CHECK-NEXT:    [[GUARD_COND_TRUE49:%.*]] = phi i1 [
            [[PRED6:%.*]], [[FLOW9]] ], [ [[TMP14]], [[FLOW11]] ]<br>
            +; CHECK-NEXT:    [[TMP16:%.*]] = xor i1
            [[GUARD_COND_TRUE49]], true<br>
            +; CHECK-NEXT:    br i1 [[TMP16]], label [[COND_END61]],
            label [[FLOW7]]<br>
            +; CHECK:       Flow14:<br>
            +; CHECK-NEXT:    [[TMP17]] = phi i1 [ [[PRED8:%.*]],
            [[IF_THEN69:%.*]] ], [ [[TMP11]], [[LOOP_EXIT_GUARD2:%.*]] ]<br>
            +; CHECK-NEXT:    br label [[FLOW13:%.*]]<br>
            +; CHECK:       loop.exit.guard:<br>
            +; CHECK-NEXT:    br i1 [[TMP19:%.*]], label
            [[WHILE_END76:%.*]], label [[FLOW6]]<br>
            +; CHECK:       Flow10:<br>
            +; CHECK-NEXT:    [[TMP18]] = phi i1 [ false,
            [[WHILE_COND47]] ], [ true, [[WHILE_BODY63]] ]<br>
            +; CHECK-NEXT:    br label [[FLOW9]]<br>
            +; CHECK:       Flow12:<br>
            +; CHECK-NEXT:    [[TMP19]] = phi i1 [ [[TMP12]], [[FLOW13]]
            ], [ true, [[FLOW11]] ]<br>
            +; CHECK-NEXT:    [[TMP20:%.*]] = phi i1 [ [[TMP13]],
            [[FLOW13]] ], [ true, [[FLOW11]] ]<br>
            +; CHECK-NEXT:    br i1 [[TMP20]], label
            [[LOOP_EXIT_GUARD:%.*]], label [[WHILE_COND]]<br>
            +; CHECK:       loop.exit.guard1:<br>
            +; CHECK-NEXT:    br i1 [[TMP11]], label
            [[LOOP_EXIT_GUARD2]], label [[FLOW13]]<br>
            +; CHECK:       loop.exit.guard2:<br>
            +; CHECK-NEXT:    br i1 [[TMP10]], label [[IF_THEN69]],
            label [[FLOW14]]<br>
            +;<br>
            +entry:<br>
            +  br i1 %Pred0, label %if.end, label %if.then<br>
            +<br>
            +if.end:<br>
            +  br i1 %Pred1, label %if.then7, label %if.else<br>
            +<br>
            +if.then7:<br>
            +  br label %if.end16<br>
            +<br>
            +if.else:<br>
            +  br label %if.end16<br>
            +<br>
            +if.end16:<br>
            +  br i1 %Pred2, label %while.cond.preheader, label
            %if.then39<br>
            +<br>
            +while.cond.preheader:<br>
            +  br label %while.cond<br>
            +<br>
            +while.cond:<br>
            +  br i1 %Pred3, label %cond.true49, label %lor.rhs<br>
            +<br>
            +cond.true49:<br>
            +  br i1 %Pred4, label %if.then69, label %while.body63<br>
            +<br>
            +while.body63:<br>
            +  br i1 %Pred5, label %exit, label %while.cond47<br>
            +<br>
            +while.cond47:<br>
            +  br i1 %Pred6, label %cond.true49, label %cond.end61<br>
            +<br>
            +cond.end61:<br>
            +  br i1 %Pred7, label %while.body63, label %while.cond<br>
            +<br>
            +if.then69:<br>
            +  br i1 %Pred8, label %exit, label %while.cond<br>
            +<br>
            +lor.rhs:<br>
            +  br i1 %Pred9, label %cond.end61, label %while.end76<br>
            +<br>
            +while.end76:<br>
            +  br label %exit<br>
            +<br>
            +if.then39:<br>
            +  br i1 %Pred10, label %exit, label %if.end.i145<br>
            +<br>
            +if.end.i145:<br>
            +  br i1 %Pred11, label %exit, label %if.end8.i149<br>
            +<br>
            +if.end8.i149:<br>
            +  br label %exit<br>
            +<br>
            +if.then:<br>
            +  br i1 %Pred12, label %exit, label %if.end.i<br>
            +<br>
            +if.end.i:<br>
            +  br i1 %Pred13, label %exit, label %if.end8.i<br>
            +<br>
            +if.end8.i:<br>
            +  br label %exit<br>
            +<br>
            +exit:<br>
            +  ret void<br>
            +}<br>
            <br>
            <br>
            <br>
            _______________________________________________<br>
            llvm-commits mailing list<br>
            <a href="mailto:llvm-commits@lists.llvm.org" target="_blank" moz-do-not-send="true">llvm-commits@lists.llvm.org</a><br>
            <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" originalsrc="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" shash="D6Ww3C+QZvb7tViX24aQY/rep+l0wOt2OwtrbPL+Mce+DPk/NAWOAZSA8x1WWITf31nneBydpzi7k7Px8ujpcu/Fyz6ykh/RPwmzeuBArb6z+NcVYPmC+74uWNTMIPEiHRSko3JzhlzXPLm11WzodO8ru+8yT1RXDt/HJDG2LaI=" rel="noreferrer" target="_blank" moz-do-not-send="true" title="Outlook Unmangled from:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-commits&data=02%7C01%7Csameer.sahasrabuddhe%40amd.com%7C6a1c7b47cf6245f08ceb08d7e5533972%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637230017944362870&sdata=8Op%2FmS7YVPnQbdrxAUIQuwvzXvj3KKUwvFbkLcCvFb4%3D&reserved=0">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
          </blockquote>
        </div>
      </div>
    </blockquote>
  </body>
</html>