[llvm] [LICM] Use DomTreeUpdater version of SplitBlockPredecessors, nfc (PR #107190)

Joshua Cao via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 24 01:48:45 PDT 2024


https://github.com/caojoshua updated https://github.com/llvm/llvm-project/pull/107190

>From 0caf5b57d24fdf3454fd1a9a13eedffeccba7517 Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Tue, 3 Sep 2024 21:35:27 -0700
Subject: [PATCH 01/10] [BasicBlockUtils] Fix SplitBlockPredecessors incorrect
 dominator insert

When SplitBlockPredecessors uses DomTreeUpdater, it always assumes that
the newly created BB dominates the old BB. This is not true if the
consumer only passes in a subset of producers. For example:

```
bb0:
  br label %bb2
bb1:
  br label %bb2
bb2: ...
```

If the consumer calls SplitBlockPredecessors on bb2 with only bb0 as the
predecessor:

```
bb0:
  br label %new_bb
new_bb:
  br label %bb2
bb1:
  br label %bb2
bb2: ...
```

In this case, new_bb does NOT dominate bb2 because there is an
alternative path to bb2 from bb1. We fix this by only marking the new BB
as dominating the old BB(bb2) if the old BB has a single predecessor.

SplitBlockPredecessors with DominatorTree is deprecated in favor of
using the function with DomTreeUpdater. We move over a consumer in
LICM::splitPredecessorsOfLoopExit() in this patch, which would have
triggered the error.
---
 llvm/lib/Transforms/Scalar/LICM.cpp           |  4 +-
 llvm/lib/Transforms/Utils/BasicBlockUtils.cpp |  5 +-
 .../Transforms/Utils/BasicBlockUtilsTest.cpp  | 71 +++++++++++++++++++
 3 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 86c7dceffc5245..d16a2a5fcad3a9 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -44,6 +44,7 @@
 #include "llvm/Analysis/AliasSetTracker.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/Analysis/GuardUtils.h"
 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
 #include "llvm/Analysis/Loads.h"
@@ -1603,13 +1604,14 @@ static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT,
   //
   const auto &BlockColors = SafetyInfo->getBlockColors();
   SmallSetVector<BasicBlock *, 8> PredBBs(pred_begin(ExitBB), pred_end(ExitBB));
+  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
   while (!PredBBs.empty()) {
     BasicBlock *PredBB = *PredBBs.begin();
     assert(CurLoop->contains(PredBB) &&
            "Expect all predecessors are in the loop");
     if (PN->getBasicBlockIndex(PredBB) >= 0) {
       BasicBlock *NewPred = SplitBlockPredecessors(
-          ExitBB, PredBB, ".split.loop.exit", DT, LI, MSSAU, true);
+          ExitBB, PredBB, ".split.loop.exit", &DTU, LI, MSSAU, true);
       // Since we do not allow splitting EH-block with BlockColors in
       // canSplitPredecessors(), we can simply assign predecessor's color to
       // the new block.
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 4144c7993b7e42..24d9d023211499 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1160,7 +1160,10 @@ static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB,
       // Split block expects NewBB to have a non-empty set of predecessors.
       SmallVector<DominatorTree::UpdateType, 8> Updates;
       SmallPtrSet<BasicBlock *, 8> UniquePreds;
-      Updates.push_back({DominatorTree::Insert, NewBB, OldBB});
+      if (OldBB->getSinglePredecessor()) {
+        assert(OldBB->getSinglePredecessor() == NewBB);
+        Updates.push_back({DominatorTree::Insert, NewBB, OldBB});
+      }
       Updates.reserve(Updates.size() + 2 * Preds.size());
       for (auto *Pred : Preds)
         if (UniquePreds.insert(Pred).second) {
diff --git a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
index 56692cf25b7972..8b452e852f4565 100644
--- a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
+++ b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
@@ -414,6 +414,77 @@ define i32 @basic_func(i1 %cond) {
   EXPECT_TRUE(DT.verify());
 }
 
+TEST(BasicBlockUtils, SplitBlockPredecessorsLinear) {
+  LLVMContext C;
+  std::unique_ptr<Module> M = parseIR(C, R"IR(
+define i32 @basic_func() {
+entry:
+  br label %bb0
+bb0:
+  ret i32 0
+}
+)IR");
+  Function *F = M->getFunction("basic_func");
+  DominatorTree DT(*F);
+  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
+
+  BasicBlock *Entry = &F->getEntryBlock();
+  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
+  SplitBlockPredecessors(BB0, {Entry}, "split.entry", &DTU);
+  EXPECT_TRUE(DT.verify());
+}
+
+TEST(BasicBlockUtils, SplitBlockPredecessorsSubsetOfPreds) {
+  LLVMContext C;
+  std::unique_ptr<Module> M = parseIR(C, R"IR(
+define i32 @basic_func(i1 %cond) {
+entry:
+  br i1 %cond, label %bb0, label %bb1
+bb0:
+  br label %bb2
+bb1:
+  br label %bb2
+bb2:
+  %phi = phi i32 [ 0, %bb0 ], [ 1, %bb1 ]
+  ret i32 %phi
+}
+)IR");
+  Function *F = M->getFunction("basic_func");
+  DominatorTree DT(*F);
+  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
+
+  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
+  BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");
+  SplitBlockPredecessors(BB2, {BB0}, "split.entry", &DTU);
+  EXPECT_TRUE(DT.verify());
+}
+
+TEST(BasicBlockUtils, SplitBlockPredecessorsAllPreds) {
+  LLVMContext C;
+  std::unique_ptr<Module> M = parseIR(C, R"IR(
+define i32 @basic_func(i1 %cond) {
+entry:
+  br i1 %cond, label %bb0, label %bb1
+bb0:
+  br label %bb2
+bb1:
+  br label %bb2
+bb2:
+  %phi = phi i32 [ 0, %bb0 ], [ 1, %bb1 ]
+  ret i32 %phi
+}
+)IR");
+  Function *F = M->getFunction("basic_func");
+  DominatorTree DT(*F);
+  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
+
+  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
+  BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
+  BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");
+  SplitBlockPredecessors(BB2, {BB0, BB1}, "split.entry", &DTU);
+  EXPECT_TRUE(DT.verify());
+}
+
 TEST(BasicBlockUtils, SplitCriticalEdge) {
   LLVMContext C;
   std::unique_ptr<Module> M = parseIR(C, R"IR(

>From a5ec0c30517f110328f2d17d54616facbb448fa0 Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Tue, 3 Sep 2024 23:38:21 -0700
Subject: [PATCH 02/10] Fix formatting

---
 llvm/lib/Transforms/Scalar/LICM.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index d16a2a5fcad3a9..931880cd50b5ff 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -66,9 +66,9 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/PatternMatch.h"

>From 785a1d7793cabc86f2876f4ecf9d5fcf7c5eb11a Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Mon, 23 Sep 2024 00:47:53 -0700
Subject: [PATCH 03/10] Add reproducing test

---
 .../Transforms/LICM/iterate-over-dom-nodes.ll | 304 ++++++++++++++++++
 1 file changed, 304 insertions(+)
 create mode 100644 llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll

diff --git a/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
new file mode 100644
index 00000000000000..889b57f24f5b68
--- /dev/null
+++ b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
@@ -0,0 +1,304 @@
+; RUN: opt -S -passes=cgscc(devirt<4>(inline,function<eager-inv;no-rerun>(early-cse<memssa>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,loop-mssa(licm<allowspeculation>)))) < %s | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%"struct.__gnu_cxx::__ops::_Iter_equals_val" = type { ptr }
+
+declare ptr @_ZN4llvm16itanium_demangle12OutputBuffer9getBufferEv()
+
+define i64 @_ZNKSt17basic_string_viewIcSt11char_traitsIcEE4sizeEv() {
+entry:
+  ret i64 0
+}
+
+define fastcc i1 @_ZL14decodePunycodeSt17basic_string_viewIcSt11char_traitsIcEERN4llvm16itanium_demangle12OutputBufferE(i64 %InputIdx.2, i1 %cmp23.not) {
+entry:
+  %call = call i64 @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv()
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  br i1 true, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  br label %if.end19
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond
+
+for.cond6:                                        ; preds = %for.inc15
+  br i1 false, label %for.end17, label %for.body8
+
+for.body8:                                        ; preds = %for.cond6
+  %call10 = call i1 @_ZL7isValidc()
+  br label %if.end12
+
+if.end12:                                         ; preds = %for.body8
+  br label %arrayinit.body
+
+arrayinit.body:                                   ; preds = %arrayinit.body, %if.end12
+  br label %arrayinit.body
+
+arrayinit.end13:                                  ; No predecessors!
+  br label %for.inc15
+
+for.inc15:                                        ; preds = %arrayinit.end13
+  br label %for.cond6
+
+for.end17:                                        ; preds = %for.cond6
+  br label %if.end19
+
+if.end19:                                         ; preds = %for.end17, %for.cond.cleanup
+  br label %for.cond21
+
+for.cond21:                                       ; preds = %for.inc100, %if.end19
+  br i1 %cmp23.not, label %cleanup102, label %for.body25
+
+for.body25:                                       ; preds = %for.cond21
+  br label %for.cond27
+
+for.cond27:                                       ; preds = %for.inc67, %for.body25
+  %call30 = call i64 @_ZNKSt17basic_string_viewIcSt11char_traitsIcEE4sizeEv()
+  br i1 %cmp23.not, label %cleanup69, label %if.end33
+
+if.end33:                                         ; preds = %for.cond27
+  br label %if.end39
+
+if.end39:                                         ; preds = %if.end33
+  br i1 false, label %cleanup63, label %if.end42
+
+if.end42:                                         ; preds = %if.end39
+  br label %if.else
+
+if.then44:                                        ; No predecessors!
+  br label %if.end51
+
+if.else:                                          ; preds = %if.end42
+  br label %if.end51
+
+if.end51:                                         ; preds = %if.else, %if.then44
+  br label %cleanup63
+
+if.end54:                                         ; No predecessors!
+  br label %cleanup63
+
+cleanup63:                                        ; preds = %if.end54, %if.end51, %if.end39
+  br label %for.inc67
+
+for.inc67:                                        ; preds = %cleanup63
+  br label %for.cond27
+
+cleanup69:                                        ; preds = %for.cond27
+  br label %for.end71
+
+for.end71:                                        ; preds = %cleanup69
+  %call72 = call i64 @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv()
+  %call77 = call fastcc i64 @"_ZZL14decodePunycodeSt17basic_string_viewIcSt11char_traitsIcEERN4llvm16itanium_demangle12OutputBufferEENK3$_0clEmm"()
+  br i1 false, label %cleanup95, label %if.end82
+
+if.end82:                                         ; preds = %for.end71
+  %call87 = call fastcc i1 @_ZL10encodeUTF8mPc(i64 %InputIdx.2, ptr null)
+  br i1 %call87, label %if.end89, label %cleanup93
+
+if.end89:                                         ; preds = %if.end82
+  call void null(ptr null, i64 0, ptr null, i64 0)
+  br label %cleanup93
+
+cleanup93:                                        ; preds = %if.end89, %if.end82
+  br label %cleanup95
+
+cleanup95:                                        ; preds = %cleanup93, %for.end71
+  br label %for.inc100
+
+for.inc100:                                       ; preds = %cleanup95
+  br label %for.cond21
+
+cleanup102:                                       ; preds = %for.cond21
+  br label %for.end104
+
+for.end104:                                       ; preds = %cleanup102
+  call fastcc void @_ZL15removeNullBytesRN4llvm16itanium_demangle12OutputBufferEm()
+  br label %cleanup105
+
+cleanup105:                                       ; preds = %for.end104
+  br label %cleanup113
+
+cleanup113:                                       ; preds = %cleanup105
+  ret i1 false
+}
+
+define i64 @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv() {
+entry:
+  ret i64 0
+}
+
+define i1 @_ZL7isValidc() {
+entry:
+  unreachable
+}
+
+define fastcc i64 @"_ZZL14decodePunycodeSt17basic_string_viewIcSt11char_traitsIcEERN4llvm16itanium_demangle12OutputBufferEENK3$_0clEmm"() {
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond, %entry
+  %Delta.addr.0 = phi i64 [ 0, %entry ], [ 1, %while.cond ]
+  %cmp = icmp ugt i64 %Delta.addr.0, 0
+  br i1 %cmp, label %while.cond, label %while.end
+
+while.end:                                        ; preds = %while.cond
+  ret i64 0
+}
+
+define fastcc i1 @_ZL10encodeUTF8mPc(i64 %CodePoint, ptr %Output) {
+entry:
+  %0 = and i64 %CodePoint, 1
+  %or.cond = icmp eq i64 %0, 0
+  br i1 %or.cond, label %return, label %if.end
+
+if.end:                                           ; preds = %entry
+  %cmp2 = icmp ult i64 %CodePoint, 1
+  br i1 %cmp2, label %if.then3, label %if.end4
+
+if.then3:                                         ; preds = %if.end
+  store i8 0, ptr %Output, align 1
+  br label %return
+
+if.end4:                                          ; preds = %if.end
+  %cmp5 = icmp ult i64 %CodePoint, 2048
+  br i1 %cmp5, label %return, label %if.end13
+
+if.end13:                                         ; preds = %if.end4
+  %cmp14 = icmp ult i64 %CodePoint, 65536
+  br i1 %cmp14, label %if.then15, label %if.end29
+
+if.then15:                                        ; preds = %if.end13
+  %shr16 = lshr i64 %CodePoint, 1
+  %1 = trunc i64 %shr16 to i8
+  br label %return
+
+if.end29:                                         ; preds = %if.end13
+  %cmp30 = icmp ult i64 %CodePoint, 1114112
+  %spec.select = select i1 %cmp30, i1 false, i1 false
+  br label %return
+
+return:                                           ; preds = %if.end29, %if.then15, %if.end4, %if.then3, %entry
+  %retval.0 = phi i1 [ false, %if.then3 ], [ true, %if.then15 ], [ false, %entry ], [ false, %if.end29 ], [ true, %if.end4 ]
+  ret i1 %retval.0
+}
+
+define fastcc void @_ZL15removeNullBytesRN4llvm16itanium_demangle12OutputBufferEm() {
+entry:
+  %ref.tmp = alloca i8, align 1
+  %call = call ptr @_ZN4llvm16itanium_demangle12OutputBuffer9getBufferEv()
+  store i8 0, ptr %ref.tmp, align 1
+  %call3 = call ptr @_ZSt6removeIPccET_S1_S1_RKT0_(ptr %call)
+  ret void
+}
+
+define ptr @_ZSt6removeIPccET_S1_S1_RKT0_(ptr %__last) {
+entry:
+  %call2 = call ptr @_ZSt11__remove_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_(ptr %__last)
+  ret ptr null
+}
+
+define ptr @_ZSt11__remove_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_(ptr %__last) {
+entry:
+  %__pred = alloca %"struct.__gnu_cxx::__ops::_Iter_equals_val", align 8
+  store ptr null, ptr %__pred, align 8
+  %call = call ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_()
+  %cmp = icmp eq ptr %call, null
+  br i1 %cmp, label %return, label %for.cond
+
+for.cond:                                         ; preds = %if.then4, %for.body, %entry
+  %call.pn = phi ptr [ %__last, %entry ], [ null, %if.then4 ], [ null, %for.body ]
+  %cmp2.not = icmp eq ptr %call.pn, null
+  br i1 %cmp2.not, label %return, label %for.body
+
+for.body:                                         ; preds = %for.cond
+  %call3 = load i1, ptr null, align 1
+  br i1 %call3, label %for.cond, label %if.then4
+
+if.then4:                                         ; preds = %for.body
+  store i8 0, ptr %__last, align 1
+  br label %for.cond
+
+return:                                           ; preds = %for.cond, %entry
+  ret ptr null
+}
+
+define ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_() {
+entry:
+  %call1 = call ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_St26random_access_iterator_tag(ptr null)
+  ret ptr %call1
+}
+
+define ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_St26random_access_iterator_tag(ptr %__first.addr.0) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %if.end11, %entry
+  %__first.addr.01 = phi ptr [ null, %entry ], [ %incdec.ptr12, %if.end11 ]
+  %__trip_count.0 = phi i64 [ 0, %entry ], [ 1, %if.end11 ]
+  %cmp = icmp sgt i64 %__trip_count.0, 0
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %call = load i1, ptr %__first.addr.01, align 1
+  br i1 %call, label %cleanup, label %if.end
+
+if.end:                                           ; preds = %for.body
+  %incdec.ptr = getelementptr i8, ptr %__first.addr.01, i64 1
+  %call1 = load i1, ptr %incdec.ptr, align 1
+  br i1 %call1, label %cleanup, label %if.end3
+
+if.end3:                                          ; preds = %if.end
+  %incdec.ptr4 = getelementptr i8, ptr %__first.addr.0, i64 2
+  %call5 = load i1, ptr %incdec.ptr4, align 1
+  br i1 %call5, label %cleanup, label %if.end7
+
+if.end7:                                          ; preds = %if.end3
+  %call9 = load i1, ptr null, align 1
+  br i1 %call9, label %cleanup, label %if.end11
+
+if.end11:                                         ; preds = %if.end7
+  %incdec.ptr12 = getelementptr i8, ptr %__first.addr.01, i64 4
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  %sub.ptr.rhs.cast14 = ptrtoint ptr %__first.addr.01 to i64
+  switch i64 %sub.ptr.rhs.cast14, label %sw.default [
+    i64 -3, label %sw.bb
+    i64 1, label %sw.bb20
+    i64 0, label %sw.bb25
+  ]
+
+sw.bb:                                            ; preds = %for.end
+  %call16 = load i1, ptr null, align 1
+  br i1 %call16, label %cleanup, label %if.end18
+
+if.end18:                                         ; preds = %sw.bb
+  %incdec.ptr19 = getelementptr i8, ptr %__first.addr.01, i64 1
+  br label %sw.bb20
+
+sw.bb20:                                          ; preds = %if.end18, %for.end
+  %__first.addr.1 = phi ptr [ null, %for.end ], [ %incdec.ptr19, %if.end18 ]
+  %incdec.ptr24 = getelementptr i8, ptr %__first.addr.1, i64 1
+  br label %sw.bb25
+
+sw.bb25:                                          ; preds = %sw.bb20, %for.end
+  %__first.addr.2 = phi ptr [ null, %for.end ], [ %incdec.ptr24, %sw.bb20 ]
+  %call26 = load i1, ptr null, align 1
+  br i1 %call26, label %cleanup, label %sw.default
+
+sw.default:                                       ; preds = %sw.bb25, %for.end
+  br label %cleanup
+
+cleanup:                                          ; preds = %sw.default, %sw.bb25, %sw.bb, %if.end7, %if.end3, %if.end, %for.body
+  %retval.0 = phi ptr [ null, %sw.default ], [ null, %for.body ], [ %incdec.ptr, %if.end ], [ null, %if.end3 ], [ null, %if.end7 ], [ null, %sw.bb ], [ %__first.addr.2, %sw.bb25 ]
+  ret ptr %retval.0
+}
+
+; uselistorder directives
+uselistorder ptr @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv, { 1, 0 }
+

>From e51beac3790f157a0b07fcc39ec1245d9cc9a812 Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Mon, 23 Sep 2024 00:48:30 -0700
Subject: [PATCH 04/10] Revert "Fix formatting"

This reverts commit a5ec0c30517f110328f2d17d54616facbb448fa0.
---
 llvm/lib/Transforms/Scalar/LICM.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 931880cd50b5ff..d16a2a5fcad3a9 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -66,9 +66,9 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Dominators.h"
-#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/PatternMatch.h"

>From b63245d401051ddaa033541de2ae29f2fc7dec43 Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Mon, 23 Sep 2024 00:48:39 -0700
Subject: [PATCH 05/10] Revert "[BasicBlockUtils] Fix SplitBlockPredecessors
 incorrect dominator insert"

This reverts commit 0caf5b57d24fdf3454fd1a9a13eedffeccba7517.
---
 llvm/lib/Transforms/Scalar/LICM.cpp           |  4 +-
 llvm/lib/Transforms/Utils/BasicBlockUtils.cpp |  5 +-
 .../Transforms/Utils/BasicBlockUtilsTest.cpp  | 71 -------------------
 3 files changed, 2 insertions(+), 78 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index d16a2a5fcad3a9..86c7dceffc5245 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -44,7 +44,6 @@
 #include "llvm/Analysis/AliasSetTracker.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/CaptureTracking.h"
-#include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/Analysis/GuardUtils.h"
 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
 #include "llvm/Analysis/Loads.h"
@@ -1604,14 +1603,13 @@ static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT,
   //
   const auto &BlockColors = SafetyInfo->getBlockColors();
   SmallSetVector<BasicBlock *, 8> PredBBs(pred_begin(ExitBB), pred_end(ExitBB));
-  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
   while (!PredBBs.empty()) {
     BasicBlock *PredBB = *PredBBs.begin();
     assert(CurLoop->contains(PredBB) &&
            "Expect all predecessors are in the loop");
     if (PN->getBasicBlockIndex(PredBB) >= 0) {
       BasicBlock *NewPred = SplitBlockPredecessors(
-          ExitBB, PredBB, ".split.loop.exit", &DTU, LI, MSSAU, true);
+          ExitBB, PredBB, ".split.loop.exit", DT, LI, MSSAU, true);
       // Since we do not allow splitting EH-block with BlockColors in
       // canSplitPredecessors(), we can simply assign predecessor's color to
       // the new block.
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 24d9d023211499..4144c7993b7e42 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1160,10 +1160,7 @@ static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB,
       // Split block expects NewBB to have a non-empty set of predecessors.
       SmallVector<DominatorTree::UpdateType, 8> Updates;
       SmallPtrSet<BasicBlock *, 8> UniquePreds;
-      if (OldBB->getSinglePredecessor()) {
-        assert(OldBB->getSinglePredecessor() == NewBB);
-        Updates.push_back({DominatorTree::Insert, NewBB, OldBB});
-      }
+      Updates.push_back({DominatorTree::Insert, NewBB, OldBB});
       Updates.reserve(Updates.size() + 2 * Preds.size());
       for (auto *Pred : Preds)
         if (UniquePreds.insert(Pred).second) {
diff --git a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
index 8b452e852f4565..56692cf25b7972 100644
--- a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
+++ b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp
@@ -414,77 +414,6 @@ define i32 @basic_func(i1 %cond) {
   EXPECT_TRUE(DT.verify());
 }
 
-TEST(BasicBlockUtils, SplitBlockPredecessorsLinear) {
-  LLVMContext C;
-  std::unique_ptr<Module> M = parseIR(C, R"IR(
-define i32 @basic_func() {
-entry:
-  br label %bb0
-bb0:
-  ret i32 0
-}
-)IR");
-  Function *F = M->getFunction("basic_func");
-  DominatorTree DT(*F);
-  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
-
-  BasicBlock *Entry = &F->getEntryBlock();
-  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
-  SplitBlockPredecessors(BB0, {Entry}, "split.entry", &DTU);
-  EXPECT_TRUE(DT.verify());
-}
-
-TEST(BasicBlockUtils, SplitBlockPredecessorsSubsetOfPreds) {
-  LLVMContext C;
-  std::unique_ptr<Module> M = parseIR(C, R"IR(
-define i32 @basic_func(i1 %cond) {
-entry:
-  br i1 %cond, label %bb0, label %bb1
-bb0:
-  br label %bb2
-bb1:
-  br label %bb2
-bb2:
-  %phi = phi i32 [ 0, %bb0 ], [ 1, %bb1 ]
-  ret i32 %phi
-}
-)IR");
-  Function *F = M->getFunction("basic_func");
-  DominatorTree DT(*F);
-  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
-
-  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
-  BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");
-  SplitBlockPredecessors(BB2, {BB0}, "split.entry", &DTU);
-  EXPECT_TRUE(DT.verify());
-}
-
-TEST(BasicBlockUtils, SplitBlockPredecessorsAllPreds) {
-  LLVMContext C;
-  std::unique_ptr<Module> M = parseIR(C, R"IR(
-define i32 @basic_func(i1 %cond) {
-entry:
-  br i1 %cond, label %bb0, label %bb1
-bb0:
-  br label %bb2
-bb1:
-  br label %bb2
-bb2:
-  %phi = phi i32 [ 0, %bb0 ], [ 1, %bb1 ]
-  ret i32 %phi
-}
-)IR");
-  Function *F = M->getFunction("basic_func");
-  DominatorTree DT(*F);
-  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
-
-  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
-  BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
-  BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");
-  SplitBlockPredecessors(BB2, {BB0, BB1}, "split.entry", &DTU);
-  EXPECT_TRUE(DT.verify());
-}
-
 TEST(BasicBlockUtils, SplitCriticalEdge) {
   LLVMContext C;
   std::unique_ptr<Module> M = parseIR(C, R"IR(

>From c898316148d35a59889bfb51f30bf2b30b470a47 Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Mon, 23 Sep 2024 00:52:50 -0700
Subject: [PATCH 06/10] Auto generate file checks

---
 .../Transforms/LICM/iterate-over-dom-nodes.ll | 591 +++++++++++++++++-
 1 file changed, 587 insertions(+), 4 deletions(-)

diff --git a/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
index 889b57f24f5b68..f267febea89953 100644
--- a/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
+++ b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
@@ -1,4 +1,5 @@
-; RUN: opt -S -passes=cgscc(devirt<4>(inline,function<eager-inv;no-rerun>(early-cse<memssa>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,loop-mssa(licm<allowspeculation>)))) < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes='cgscc(devirt<4>(inline,function<eager-inv;no-rerun>(early-cse<memssa>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,loop-mssa(licm<allowspeculation>))))' < %s | FileCheck %s
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
@@ -8,11 +9,143 @@ target triple = "x86_64-unknown-linux-gnu"
 declare ptr @_ZN4llvm16itanium_demangle12OutputBuffer9getBufferEv()
 
 define i64 @_ZNKSt17basic_string_viewIcSt11char_traitsIcEE4sizeEv() {
+; CHECK-LABEL: define i64 @_ZNKSt17basic_string_viewIcSt11char_traitsIcEE4sizeEv() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i64 0
+;
 entry:
   ret i64 0
 }
 
 define fastcc i1 @_ZL14decodePunycodeSt17basic_string_viewIcSt11char_traitsIcEERN4llvm16itanium_demangle12OutputBufferE(i64 %InputIdx.2, i1 %cmp23.not) {
+; CHECK-LABEL: define fastcc i1 @_ZL14decodePunycodeSt17basic_string_viewIcSt11char_traitsIcEERN4llvm16itanium_demangle12OutputBufferE(
+; CHECK-SAME: i64 [[INPUTIDX_2:%.*]], i1 [[CMP23_NOT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[__PRED_I_I_I:%.*]] = alloca %"struct.__gnu_cxx::__ops::_Iter_equals_val", align 8
+; CHECK-NEXT:    [[REF_TMP_I:%.*]] = alloca i8, align 1
+; CHECK-NEXT:    [[TMP0:%.*]] = and i64 [[INPUTIDX_2]], 1
+; CHECK-NEXT:    [[OR_COND_I:%.*]] = icmp eq i64 [[TMP0]], 0
+; CHECK-NEXT:    [[CMP2_I:%.*]] = icmp ult i64 [[INPUTIDX_2]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[CMP2_I]], true
+; CHECK-NEXT:    [[CMP5_I:%.*]] = icmp ult i64 [[INPUTIDX_2]], 2048
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[CMP5_I]], true
+; CHECK-NEXT:    [[CMP14_I:%.*]] = icmp ult i64 [[INPUTIDX_2]], 65536
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[CMP14_I]], true
+; CHECK-NEXT:    br label %[[FOR_COND21:.*]]
+; CHECK:       [[FOR_COND21]]:
+; CHECK-NEXT:    br i1 [[CMP23_NOT]], label %[[FOR_END104:.*]], label %[[FOR_INC67_PREHEADER:.*]]
+; CHECK:       [[FOR_INC67_PREHEADER]]:
+; CHECK-NEXT:    br label %[[FOR_INC67:.*]]
+; CHECK:       [[FOR_INC67]]:
+; CHECK-NEXT:    br i1 [[CMP23_NOT]], label %[[WHILE_COND_I_PREHEADER:.*]], label %[[FOR_INC67]]
+; CHECK:       [[WHILE_COND_I_PREHEADER]]:
+; CHECK-NEXT:    br label %[[WHILE_COND_I:.*]]
+; CHECK:       [[WHILE_COND_I]]:
+; CHECK-NEXT:    [[DELTA_ADDR_0_I:%.*]] = phi i64 [ 1, %[[WHILE_COND_I]] ], [ 0, %[[WHILE_COND_I_PREHEADER]] ]
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp ugt i64 [[DELTA_ADDR_0_I]], 0
+; CHECK-NEXT:    br i1 [[CMP_I]], label %[[WHILE_COND_I]], label %[[IF_END82:.*]]
+; CHECK:       [[IF_END82]]:
+; CHECK-NEXT:    br i1 [[OR_COND_I]], label %[[FOR_INC100:.*]], label %[[IF_END_I:.*]]
+; CHECK:       [[IF_END_I]]:
+; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP2]])
+; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP3]])
+; CHECK-NEXT:    br label %[[FOR_INC100]]
+; CHECK:       [[FOR_INC100]]:
+; CHECK-NEXT:    br label %[[FOR_COND21]]
+; CHECK:       [[FOR_END104]]:
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 1, ptr [[REF_TMP_I]])
+; CHECK-NEXT:    [[CALL_I:%.*]] = call ptr @_ZN4llvm16itanium_demangle12OutputBuffer9getBufferEv()
+; CHECK-NEXT:    store i8 0, ptr [[REF_TMP_I]], align 1
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[__PRED_I_I_I]])
+; CHECK-NEXT:    store ptr null, ptr [[__PRED_I_I_I]], align 8
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I_I_I:.*]]
+; CHECK:       [[FOR_COND_I_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_I_I:%.*]] = phi ptr [ null, %[[FOR_END104]] ], [ [[INCDEC_PTR12_I_I_I_I_I:%.*]], %[[IF_END11_I_I_I_I_I:.*]] ]
+; CHECK-NEXT:    [[__TRIP_COUNT_0_I_I_I_I_I:%.*]] = phi i64 [ 0, %[[FOR_END104]] ], [ 1, %[[IF_END11_I_I_I_I_I]] ]
+; CHECK-NEXT:    [[CMP_I_I_I_I_I:%.*]] = icmp sgt i64 [[__TRIP_COUNT_0_I_I_I_I_I]], 0
+; CHECK-NEXT:    br i1 [[CMP_I_I_I_I_I]], label %[[FOR_BODY_I_I_I_I_I:.*]], label %[[FOR_END_I_I_I_I_I:.*]]
+; CHECK:       [[FOR_BODY_I_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL_I_I_I_I_I:%.*]] = load i1, ptr [[__FIRST_ADDR_01_I_I_I_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL_I_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT:.*]], label %[[IF_END_I_I_I_I_I:.*]]
+; CHECK:       [[IF_END_I_I_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR_I_I_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I_I]], i64 1
+; CHECK-NEXT:    [[CALL1_I_I_I_I_I:%.*]] = load i1, ptr [[INCDEC_PTR_I_I_I_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL1_I_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT10:.*]], label %[[IF_END3_I_I_I_I_I:.*]]
+; CHECK:       [[IF_END3_I_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL5_I_I_I_I_I:%.*]] = load i1, ptr inttoptr (i64 2 to ptr), align 1
+; CHECK-NEXT:    br i1 [[CALL5_I_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT12:.*]], label %[[IF_END7_I_I_I_I_I:.*]]
+; CHECK:       [[IF_END7_I_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL9_I_I_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL9_I_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT14:.*]], label %[[IF_END11_I_I_I_I_I]]
+; CHECK:       [[IF_END11_I_I_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR12_I_I_I_I_I]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I_I]], i64 4
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I_I_I]]
+; CHECK:       [[FOR_END_I_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_I_I_LCSSA:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I_I_I_I]], %[[FOR_COND_I_I_I_I_I]] ]
+; CHECK-NEXT:    [[SUB_PTR_RHS_CAST14_I_I_I_I_I:%.*]] = ptrtoint ptr [[__FIRST_ADDR_01_I_I_I_I_I_LCSSA]] to i64
+; CHECK-NEXT:    switch i64 [[SUB_PTR_RHS_CAST14_I_I_I_I_I]], label %[[SW_DEFAULT_I_I_I_I_I:.*]] [
+; CHECK-NEXT:      i64 -3, label %[[SW_BB_I_I_I_I_I:.*]]
+; CHECK-NEXT:      i64 1, label %[[SW_BB20_I_I_I_I_I:.*]]
+; CHECK-NEXT:      i64 0, label %[[SW_BB25_I_I_I_I_I:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW_BB_I_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL16_I_I_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL16_I_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I:.*]], label %[[IF_END18_I_I_I_I_I:.*]]
+; CHECK:       [[IF_END18_I_I_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR19_I_I_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I_I_LCSSA]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB20_I_I_I_I_I]]
+; CHECK:       [[SW_BB20_I_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_1_I_I_I_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I_I_I_I]] ], [ [[INCDEC_PTR19_I_I_I_I_I]], %[[IF_END18_I_I_I_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR24_I_I_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_1_I_I_I_I_I]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB25_I_I_I_I_I]]
+; CHECK:       [[SW_BB25_I_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_2_I_I_I_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I_I_I_I]] ], [ [[INCDEC_PTR24_I_I_I_I_I]], %[[SW_BB20_I_I_I_I_I]] ]
+; CHECK-NEXT:    [[CALL26_I_I_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL26_I_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I]], label %[[SW_DEFAULT_I_I_I_I_I]]
+; CHECK:       [[SW_DEFAULT_I_I_I_I_I]]:
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_I_PH_PH:%.*]] = phi ptr [ null, %[[FOR_BODY_I_I_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT:.*]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT10]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_I_I_LCSSA16:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I_I_I_I]], %[[IF_END_I_I_I_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR_I_I_I_I_I_LE:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I_I_LCSSA16]], i64 1
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT12]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_I_PH_PH13:%.*]] = phi ptr [ null, %[[IF_END3_I_I_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT14]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_I_PH_PH15:%.*]] = phi ptr [ null, %[[IF_END7_I_I_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_I_PH:%.*]] = phi ptr [ [[RETVAL_0_I_I_I_I_I_PH_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT]] ], [ [[INCDEC_PTR_I_I_I_I_I_LE]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT10]] ], [ [[RETVAL_0_I_I_I_I_I_PH_PH13]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT12]] ], [ [[RETVAL_0_I_I_I_I_I_PH_PH15]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT_SPLIT_LOOP_EXIT14]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_I:%.*]] = phi ptr [ null, %[[SW_DEFAULT_I_I_I_I_I]] ], [ null, %[[SW_BB_I_I_I_I_I]] ], [ [[__FIRST_ADDR_2_I_I_I_I_I]], %[[SW_BB25_I_I_I_I_I]] ], [ [[RETVAL_0_I_I_I_I_I_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_I_LOOPEXIT]] ]
+; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp eq ptr [[RETVAL_0_I_I_I_I_I]], null
+; CHECK-NEXT:    br i1 [[CMP_I_I_I]], label %[[_ZL15REMOVENULLBYTESRN4LLVM16ITANIUM_DEMANGLE12OUTPUTBUFFEREM_EXIT:.*]], label %[[FOR_COND_I_I_I_PREHEADER:.*]]
+; CHECK:       [[FOR_COND_I_I_I_PREHEADER]]:
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I:.*]]
+; CHECK:       [[FOR_COND_I_I_I]]:
+; CHECK-NEXT:    [[CALL_PN_I_I_I:%.*]] = phi ptr [ null, %[[FOR_COND_BACKEDGE_I_I_I:.*]] ], [ [[CALL_I]], %[[FOR_COND_I_I_I_PREHEADER]] ]
+; CHECK-NEXT:    [[CMP2_NOT_I_I_I:%.*]] = icmp eq ptr [[CALL_PN_I_I_I]], null
+; CHECK-NEXT:    br i1 [[CMP2_NOT_I_I_I]], label %[[_ZL15REMOVENULLBYTESRN4LLVM16ITANIUM_DEMANGLE12OUTPUTBUFFEREM_EXIT_LOOPEXIT:.*]], label %[[FOR_BODY_I_I_I:.*]]
+; CHECK:       [[FOR_BODY_I_I_I]]:
+; CHECK-NEXT:    [[CALL3_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL3_I_I_I]], label %[[FOR_COND_BACKEDGE_I_I_I]], label %[[IF_THEN4_I_I_I:.*]]
+; CHECK:       [[FOR_COND_BACKEDGE_I_I_I]]:
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I]]
+; CHECK:       [[IF_THEN4_I_I_I]]:
+; CHECK-NEXT:    store i8 0, ptr [[CALL_I]], align 1
+; CHECK-NEXT:    br label %[[FOR_COND_BACKEDGE_I_I_I]]
+; CHECK:       [[_ZL15REMOVENULLBYTESRN4LLVM16ITANIUM_DEMANGLE12OUTPUTBUFFEREM_EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[_ZL15REMOVENULLBYTESRN4LLVM16ITANIUM_DEMANGLE12OUTPUTBUFFEREM_EXIT]]
+; CHECK:       [[_ZL15REMOVENULLBYTESRN4LLVM16ITANIUM_DEMANGLE12OUTPUTBUFFEREM_EXIT]]:
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[__PRED_I_I_I]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 1, ptr [[REF_TMP_I]])
+; CHECK-NEXT:    ret i1 false
+;
 entry:
   %call = call i64 @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv()
   br label %for.cond
@@ -128,11 +261,19 @@ cleanup113:                                       ; preds = %cleanup105
 }
 
 define i64 @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv() {
+; CHECK-LABEL: define i64 @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i64 0
+;
 entry:
   ret i64 0
 }
 
 define i1 @_ZL7isValidc() {
+; CHECK-LABEL: define i1 @_ZL7isValidc() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    unreachable
+;
 entry:
   unreachable
 }
@@ -151,6 +292,34 @@ while.end:                                        ; preds = %while.cond
 }
 
 define fastcc i1 @_ZL10encodeUTF8mPc(i64 %CodePoint, ptr %Output) {
+; CHECK-LABEL: define fastcc i1 @_ZL10encodeUTF8mPc(
+; CHECK-SAME: i64 [[CODEPOINT:%.*]], ptr [[OUTPUT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i64 [[CODEPOINT]], 1
+; CHECK-NEXT:    [[OR_COND:%.*]] = icmp eq i64 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[OR_COND]], label %[[RETURN:.*]], label %[[IF_END:.*]]
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i64 [[CODEPOINT]], 1
+; CHECK-NEXT:    br i1 [[CMP2]], label %[[IF_THEN3:.*]], label %[[IF_END4:.*]]
+; CHECK:       [[IF_THEN3]]:
+; CHECK-NEXT:    store i8 0, ptr [[OUTPUT]], align 1
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[IF_END4]]:
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i64 [[CODEPOINT]], 2048
+; CHECK-NEXT:    br i1 [[CMP5]], label %[[RETURN]], label %[[IF_END13:.*]]
+; CHECK:       [[IF_END13]]:
+; CHECK-NEXT:    [[CMP14:%.*]] = icmp ult i64 [[CODEPOINT]], 65536
+; CHECK-NEXT:    br i1 [[CMP14]], label %[[IF_THEN15:.*]], label %[[IF_END29:.*]]
+; CHECK:       [[IF_THEN15]]:
+; CHECK-NEXT:    [[SHR16:%.*]] = lshr i64 [[CODEPOINT]], 1
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[IF_END29]]:
+; CHECK-NEXT:    [[CMP30:%.*]] = icmp ult i64 [[CODEPOINT]], 1114112
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i1 [ false, %[[IF_THEN3]] ], [ true, %[[IF_THEN15]] ], [ false, %[[ENTRY]] ], [ false, %[[IF_END29]] ], [ true, %[[IF_END4]] ]
+; CHECK-NEXT:    ret i1 [[RETVAL_0]]
+;
 entry:
   %0 = and i64 %CodePoint, 1
   %or.cond = icmp eq i64 %0, 0
@@ -188,6 +357,100 @@ return:                                           ; preds = %if.end29, %if.then1
 }
 
 define fastcc void @_ZL15removeNullBytesRN4llvm16itanium_demangle12OutputBufferEm() {
+; CHECK-LABEL: define fastcc void @_ZL15removeNullBytesRN4llvm16itanium_demangle12OutputBufferEm() {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[__PRED_I_I:%.*]] = alloca %"struct.__gnu_cxx::__ops::_Iter_equals_val", align 8
+; CHECK-NEXT:    [[REF_TMP:%.*]] = alloca i8, align 1
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @_ZN4llvm16itanium_demangle12OutputBuffer9getBufferEv()
+; CHECK-NEXT:    store i8 0, ptr [[REF_TMP]], align 1
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[__PRED_I_I]])
+; CHECK-NEXT:    store ptr null, ptr [[__PRED_I_I]], align 8
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I_I:.*]]
+; CHECK:       [[FOR_COND_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_I:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[INCDEC_PTR12_I_I_I_I:%.*]], %[[IF_END11_I_I_I_I:.*]] ]
+; CHECK-NEXT:    [[__TRIP_COUNT_0_I_I_I_I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ 1, %[[IF_END11_I_I_I_I]] ]
+; CHECK-NEXT:    [[CMP_I_I_I_I:%.*]] = icmp sgt i64 [[__TRIP_COUNT_0_I_I_I_I]], 0
+; CHECK-NEXT:    br i1 [[CMP_I_I_I_I]], label %[[FOR_BODY_I_I_I_I:.*]], label %[[FOR_END_I_I_I_I:.*]]
+; CHECK:       [[FOR_BODY_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL_I_I_I_I:%.*]] = load i1, ptr [[__FIRST_ADDR_01_I_I_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT:.*]], label %[[IF_END_I_I_I_I:.*]]
+; CHECK:       [[IF_END_I_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR_I_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I]], i64 1
+; CHECK-NEXT:    [[CALL1_I_I_I_I:%.*]] = load i1, ptr [[INCDEC_PTR_I_I_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL1_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT2:.*]], label %[[IF_END3_I_I_I_I:.*]]
+; CHECK:       [[IF_END3_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL5_I_I_I_I:%.*]] = load i1, ptr inttoptr (i64 2 to ptr), align 1
+; CHECK-NEXT:    br i1 [[CALL5_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT4:.*]], label %[[IF_END7_I_I_I_I:.*]]
+; CHECK:       [[IF_END7_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL9_I_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL9_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT6:.*]], label %[[IF_END11_I_I_I_I]]
+; CHECK:       [[IF_END11_I_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR12_I_I_I_I]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I]], i64 4
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I_I]]
+; CHECK:       [[FOR_END_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_I_LCSSA:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I_I_I]], %[[FOR_COND_I_I_I_I]] ]
+; CHECK-NEXT:    [[SUB_PTR_RHS_CAST14_I_I_I_I:%.*]] = ptrtoint ptr [[__FIRST_ADDR_01_I_I_I_I_LCSSA]] to i64
+; CHECK-NEXT:    switch i64 [[SUB_PTR_RHS_CAST14_I_I_I_I]], label %[[SW_DEFAULT_I_I_I_I:.*]] [
+; CHECK-NEXT:      i64 -3, label %[[SW_BB_I_I_I_I:.*]]
+; CHECK-NEXT:      i64 1, label %[[SW_BB20_I_I_I_I:.*]]
+; CHECK-NEXT:      i64 0, label %[[SW_BB25_I_I_I_I:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW_BB_I_I_I_I]]:
+; CHECK-NEXT:    [[CALL16_I_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL16_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I:.*]], label %[[IF_END18_I_I_I_I:.*]]
+; CHECK:       [[IF_END18_I_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR19_I_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I_LCSSA]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB20_I_I_I_I]]
+; CHECK:       [[SW_BB20_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_1_I_I_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I_I_I]] ], [ [[INCDEC_PTR19_I_I_I_I]], %[[IF_END18_I_I_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR24_I_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_1_I_I_I_I]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB25_I_I_I_I]]
+; CHECK:       [[SW_BB25_I_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_2_I_I_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I_I_I]] ], [ [[INCDEC_PTR24_I_I_I_I]], %[[SW_BB20_I_I_I_I]] ]
+; CHECK-NEXT:    [[CALL26_I_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL26_I_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I]], label %[[SW_DEFAULT_I_I_I_I]]
+; CHECK:       [[SW_DEFAULT_I_I_I_I]]:
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_PH_PH:%.*]] = phi ptr [ null, %[[FOR_BODY_I_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT:.*]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT2]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_I_LCSSA8:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I_I_I]], %[[IF_END_I_I_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR_I_I_I_I_LE:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_I_LCSSA8]], i64 1
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT4]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_PH_PH5:%.*]] = phi ptr [ null, %[[IF_END3_I_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT6]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_PH_PH7:%.*]] = phi ptr [ null, %[[IF_END7_I_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I_PH:%.*]] = phi ptr [ [[RETVAL_0_I_I_I_I_PH_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT]] ], [ [[INCDEC_PTR_I_I_I_I_LE]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT2]] ], [ [[RETVAL_0_I_I_I_I_PH_PH5]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT4]] ], [ [[RETVAL_0_I_I_I_I_PH_PH7]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT_SPLIT_LOOP_EXIT6]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_I:%.*]] = phi ptr [ null, %[[SW_DEFAULT_I_I_I_I]] ], [ null, %[[SW_BB_I_I_I_I]] ], [ [[__FIRST_ADDR_2_I_I_I_I]], %[[SW_BB25_I_I_I_I]] ], [ [[RETVAL_0_I_I_I_I_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_I_LOOPEXIT]] ]
+; CHECK-NEXT:    [[CMP_I_I:%.*]] = icmp eq ptr [[RETVAL_0_I_I_I_I]], null
+; CHECK-NEXT:    br i1 [[CMP_I_I]], label %[[_ZST6REMOVEIPCCET_S1_S1_RKT0__EXIT:.*]], label %[[FOR_COND_I_I_PREHEADER:.*]]
+; CHECK:       [[FOR_COND_I_I_PREHEADER]]:
+; CHECK-NEXT:    br label %[[FOR_COND_I_I:.*]]
+; CHECK:       [[FOR_COND_I_I]]:
+; CHECK-NEXT:    [[CALL_PN_I_I:%.*]] = phi ptr [ null, %[[FOR_COND_BACKEDGE_I_I:.*]] ], [ [[CALL]], %[[FOR_COND_I_I_PREHEADER]] ]
+; CHECK-NEXT:    [[CMP2_NOT_I_I:%.*]] = icmp eq ptr [[CALL_PN_I_I]], null
+; CHECK-NEXT:    br i1 [[CMP2_NOT_I_I]], label %[[_ZST6REMOVEIPCCET_S1_S1_RKT0__EXIT_LOOPEXIT:.*]], label %[[FOR_BODY_I_I:.*]]
+; CHECK:       [[FOR_BODY_I_I]]:
+; CHECK-NEXT:    [[CALL3_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL3_I_I]], label %[[FOR_COND_BACKEDGE_I_I]], label %[[IF_THEN4_I_I:.*]]
+; CHECK:       [[FOR_COND_BACKEDGE_I_I]]:
+; CHECK-NEXT:    br label %[[FOR_COND_I_I]]
+; CHECK:       [[IF_THEN4_I_I]]:
+; CHECK-NEXT:    store i8 0, ptr [[CALL]], align 1
+; CHECK-NEXT:    br label %[[FOR_COND_BACKEDGE_I_I]]
+; CHECK:       [[_ZST6REMOVEIPCCET_S1_S1_RKT0__EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[_ZST6REMOVEIPCCET_S1_S1_RKT0__EXIT]]
+; CHECK:       [[_ZST6REMOVEIPCCET_S1_S1_RKT0__EXIT]]:
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[__PRED_I_I]])
+; CHECK-NEXT:    ret void
+;
 entry:
   %ref.tmp = alloca i8, align 1
   %call = call ptr @_ZN4llvm16itanium_demangle12OutputBuffer9getBufferEv()
@@ -197,12 +460,194 @@ entry:
 }
 
 define ptr @_ZSt6removeIPccET_S1_S1_RKT0_(ptr %__last) {
+; CHECK-LABEL: define ptr @_ZSt6removeIPccET_S1_S1_RKT0_(
+; CHECK-SAME: ptr [[__LAST:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[__PRED_I:%.*]] = alloca %"struct.__gnu_cxx::__ops::_Iter_equals_val", align 8
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[__PRED_I]])
+; CHECK-NEXT:    store ptr null, ptr [[__PRED_I]], align 8
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I:.*]]
+; CHECK:       [[FOR_COND_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[INCDEC_PTR12_I_I_I:%.*]], %[[IF_END11_I_I_I:.*]] ]
+; CHECK-NEXT:    [[__TRIP_COUNT_0_I_I_I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ 1, %[[IF_END11_I_I_I]] ]
+; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp sgt i64 [[__TRIP_COUNT_0_I_I_I]], 0
+; CHECK-NEXT:    br i1 [[CMP_I_I_I]], label %[[FOR_BODY_I_I_I:.*]], label %[[FOR_END_I_I_I:.*]]
+; CHECK:       [[FOR_BODY_I_I_I]]:
+; CHECK-NEXT:    [[CALL_I_I_I:%.*]] = load i1, ptr [[__FIRST_ADDR_01_I_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT6:.*]], label %[[IF_END_I_I_I:.*]]
+; CHECK:       [[IF_END_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I]], i64 1
+; CHECK-NEXT:    [[CALL1_I_I_I:%.*]] = load i1, ptr [[INCDEC_PTR_I_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL1_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT4:.*]], label %[[IF_END3_I_I_I:.*]]
+; CHECK:       [[IF_END3_I_I_I]]:
+; CHECK-NEXT:    [[CALL5_I_I_I:%.*]] = load i1, ptr inttoptr (i64 2 to ptr), align 1
+; CHECK-NEXT:    br i1 [[CALL5_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT2:.*]], label %[[IF_END7_I_I_I:.*]]
+; CHECK:       [[IF_END7_I_I_I]]:
+; CHECK-NEXT:    [[CALL9_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL9_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT:.*]], label %[[IF_END11_I_I_I]]
+; CHECK:       [[IF_END11_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR12_I_I_I]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I]], i64 4
+; CHECK-NEXT:    br label %[[FOR_COND_I_I_I]]
+; CHECK:       [[FOR_END_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_LCSSA:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I_I]], %[[FOR_COND_I_I_I]] ]
+; CHECK-NEXT:    [[SUB_PTR_RHS_CAST14_I_I_I:%.*]] = ptrtoint ptr [[__FIRST_ADDR_01_I_I_I_LCSSA]] to i64
+; CHECK-NEXT:    switch i64 [[SUB_PTR_RHS_CAST14_I_I_I]], label %[[SW_DEFAULT_I_I_I:.*]] [
+; CHECK-NEXT:      i64 -3, label %[[SW_BB_I_I_I:.*]]
+; CHECK-NEXT:      i64 1, label %[[SW_BB20_I_I_I:.*]]
+; CHECK-NEXT:      i64 0, label %[[SW_BB25_I_I_I:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW_BB_I_I_I]]:
+; CHECK-NEXT:    [[CALL16_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL16_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I:.*]], label %[[IF_END18_I_I_I:.*]]
+; CHECK:       [[IF_END18_I_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR19_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_LCSSA]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB20_I_I_I]]
+; CHECK:       [[SW_BB20_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_1_I_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I_I]] ], [ [[INCDEC_PTR19_I_I_I]], %[[IF_END18_I_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR24_I_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_1_I_I_I]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB25_I_I_I]]
+; CHECK:       [[SW_BB25_I_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_2_I_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I_I]] ], [ [[INCDEC_PTR24_I_I_I]], %[[SW_BB20_I_I_I]] ]
+; CHECK-NEXT:    [[CALL26_I_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL26_I_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I]], label %[[SW_DEFAULT_I_I_I]]
+; CHECK:       [[SW_DEFAULT_I_I_I]]:
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_PH_PH:%.*]] = phi ptr [ null, %[[IF_END7_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT:.*]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT2]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_PH_PH3:%.*]] = phi ptr [ null, %[[IF_END3_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT4]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_I_LCSSA8:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I_I]], %[[IF_END_I_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR_I_I_I_LE:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_I_LCSSA8]], i64 1
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT6]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_PH_PH7:%.*]] = phi ptr [ null, %[[FOR_BODY_I_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I_PH:%.*]] = phi ptr [ [[RETVAL_0_I_I_I_PH_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT]] ], [ [[RETVAL_0_I_I_I_PH_PH3]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT2]] ], [ [[INCDEC_PTR_I_I_I_LE]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT4]] ], [ [[RETVAL_0_I_I_I_PH_PH7]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT_SPLIT_LOOP_EXIT6]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_I:%.*]] = phi ptr [ null, %[[SW_DEFAULT_I_I_I]] ], [ null, %[[SW_BB_I_I_I]] ], [ [[__FIRST_ADDR_2_I_I_I]], %[[SW_BB25_I_I_I]] ], [ [[RETVAL_0_I_I_I_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_I_LOOPEXIT]] ]
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq ptr [[RETVAL_0_I_I_I]], null
+; CHECK-NEXT:    br i1 [[CMP_I]], label %[[_ZST11__REMOVE_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT:.*]], label %[[FOR_COND_I_PREHEADER:.*]]
+; CHECK:       [[FOR_COND_I_PREHEADER]]:
+; CHECK-NEXT:    br label %[[FOR_COND_I:.*]]
+; CHECK:       [[FOR_COND_I]]:
+; CHECK-NEXT:    [[CALL_PN_I:%.*]] = phi ptr [ null, %[[FOR_COND_BACKEDGE_I:.*]] ], [ [[__LAST]], %[[FOR_COND_I_PREHEADER]] ]
+; CHECK-NEXT:    [[CMP2_NOT_I:%.*]] = icmp eq ptr [[CALL_PN_I]], null
+; CHECK-NEXT:    br i1 [[CMP2_NOT_I]], label %[[_ZST11__REMOVE_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT:.*]], label %[[FOR_BODY_I:.*]]
+; CHECK:       [[FOR_BODY_I]]:
+; CHECK-NEXT:    [[CALL3_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL3_I]], label %[[FOR_COND_BACKEDGE_I]], label %[[IF_THEN4_I:.*]]
+; CHECK:       [[FOR_COND_BACKEDGE_I]]:
+; CHECK-NEXT:    br label %[[FOR_COND_I]]
+; CHECK:       [[IF_THEN4_I]]:
+; CHECK-NEXT:    store i8 0, ptr [[__LAST]], align 1
+; CHECK-NEXT:    br label %[[FOR_COND_BACKEDGE_I]]
+; CHECK:       [[_ZST11__REMOVE_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[_ZST11__REMOVE_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT]]
+; CHECK:       [[_ZST11__REMOVE_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT]]:
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[__PRED_I]])
+; CHECK-NEXT:    ret ptr null
+;
 entry:
   %call2 = call ptr @_ZSt11__remove_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_(ptr %__last)
   ret ptr null
 }
 
 define ptr @_ZSt11__remove_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_(ptr %__last) {
+; CHECK-LABEL: define ptr @_ZSt11__remove_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_(
+; CHECK-SAME: ptr [[__LAST:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[__PRED:%.*]] = alloca %"struct.__gnu_cxx::__ops::_Iter_equals_val", align 8
+; CHECK-NEXT:    store ptr null, ptr [[__PRED]], align 8
+; CHECK-NEXT:    br label %[[FOR_COND_I_I:.*]]
+; CHECK:       [[FOR_COND_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[INCDEC_PTR12_I_I:%.*]], %[[IF_END11_I_I:.*]] ]
+; CHECK-NEXT:    [[__TRIP_COUNT_0_I_I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ 1, %[[IF_END11_I_I]] ]
+; CHECK-NEXT:    [[CMP_I_I:%.*]] = icmp sgt i64 [[__TRIP_COUNT_0_I_I]], 0
+; CHECK-NEXT:    br i1 [[CMP_I_I]], label %[[FOR_BODY_I_I:.*]], label %[[FOR_END_I_I:.*]]
+; CHECK:       [[FOR_BODY_I_I]]:
+; CHECK-NEXT:    [[CALL_I_I:%.*]] = load i1, ptr [[__FIRST_ADDR_01_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT:.*]], label %[[IF_END_I_I:.*]]
+; CHECK:       [[IF_END_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I]], i64 1
+; CHECK-NEXT:    [[CALL1_I_I:%.*]] = load i1, ptr [[INCDEC_PTR_I_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL1_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT2:.*]], label %[[IF_END3_I_I:.*]]
+; CHECK:       [[IF_END3_I_I]]:
+; CHECK-NEXT:    [[CALL5_I_I:%.*]] = load i1, ptr inttoptr (i64 2 to ptr), align 1
+; CHECK-NEXT:    br i1 [[CALL5_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT4:.*]], label %[[IF_END7_I_I:.*]]
+; CHECK:       [[IF_END7_I_I]]:
+; CHECK-NEXT:    [[CALL9_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL9_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT6:.*]], label %[[IF_END11_I_I]]
+; CHECK:       [[IF_END11_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR12_I_I]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I]], i64 4
+; CHECK-NEXT:    br label %[[FOR_COND_I_I]]
+; CHECK:       [[FOR_END_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_LCSSA:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I]], %[[FOR_COND_I_I]] ]
+; CHECK-NEXT:    [[SUB_PTR_RHS_CAST14_I_I:%.*]] = ptrtoint ptr [[__FIRST_ADDR_01_I_I_LCSSA]] to i64
+; CHECK-NEXT:    switch i64 [[SUB_PTR_RHS_CAST14_I_I]], label %[[SW_DEFAULT_I_I:.*]] [
+; CHECK-NEXT:      i64 -3, label %[[SW_BB_I_I:.*]]
+; CHECK-NEXT:      i64 1, label %[[SW_BB20_I_I:.*]]
+; CHECK-NEXT:      i64 0, label %[[SW_BB25_I_I:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW_BB_I_I]]:
+; CHECK-NEXT:    [[CALL16_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL16_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT:.*]], label %[[IF_END18_I_I:.*]]
+; CHECK:       [[IF_END18_I_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR19_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_LCSSA]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB20_I_I]]
+; CHECK:       [[SW_BB20_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_1_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I]] ], [ [[INCDEC_PTR19_I_I]], %[[IF_END18_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR24_I_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_1_I_I]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB25_I_I]]
+; CHECK:       [[SW_BB25_I_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_2_I_I:%.*]] = phi ptr [ null, %[[FOR_END_I_I]] ], [ [[INCDEC_PTR24_I_I]], %[[SW_BB20_I_I]] ]
+; CHECK-NEXT:    [[CALL26_I_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL26_I_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT]], label %[[SW_DEFAULT_I_I]]
+; CHECK:       [[SW_DEFAULT_I_I]]:
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_PH_PH:%.*]] = phi ptr [ null, %[[FOR_BODY_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT:.*]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT2]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_I_LCSSA8:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I_I]], %[[IF_END_I_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR_I_I_LE:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_I_LCSSA8]], i64 1
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT4]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_PH_PH5:%.*]] = phi ptr [ null, %[[IF_END3_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT6]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_PH_PH7:%.*]] = phi ptr [ null, %[[IF_END7_I_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I_PH:%.*]] = phi ptr [ [[RETVAL_0_I_I_PH_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT]] ], [ [[INCDEC_PTR_I_I_LE]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT2]] ], [ [[RETVAL_0_I_I_PH_PH5]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT4]] ], [ [[RETVAL_0_I_I_PH_PH7]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT_SPLIT_LOOP_EXIT6]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_I:%.*]] = phi ptr [ null, %[[SW_DEFAULT_I_I]] ], [ null, %[[SW_BB_I_I]] ], [ [[__FIRST_ADDR_2_I_I]], %[[SW_BB25_I_I]] ], [ [[RETVAL_0_I_I_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0__EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[RETVAL_0_I_I]], null
+; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[FOR_COND_PREHEADER:.*]]
+; CHECK:       [[FOR_COND_PREHEADER]]:
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[CALL_PN:%.*]] = phi ptr [ [[__LAST]], %[[FOR_COND_PREHEADER]] ], [ null, %[[FOR_COND_BACKEDGE:.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq ptr [[CALL_PN]], null
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label %[[RETURN_LOOPEXIT:.*]], label %[[FOR_BODY:.*]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[CALL3:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL3]], label %[[FOR_COND_BACKEDGE]], label %[[IF_THEN4:.*]]
+; CHECK:       [[FOR_COND_BACKEDGE]]:
+; CHECK-NEXT:    br label %[[FOR_COND]]
+; CHECK:       [[IF_THEN4]]:
+; CHECK-NEXT:    store i8 0, ptr [[__LAST]], align 1
+; CHECK-NEXT:    br label %[[FOR_COND_BACKEDGE]]
+; CHECK:       [[RETURN_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret ptr null
+;
 entry:
   %__pred = alloca %"struct.__gnu_cxx::__ops::_Iter_equals_val", align 8
   store ptr null, ptr %__pred, align 8
@@ -228,12 +673,150 @@ return:                                           ; preds = %for.cond, %entry
 }
 
 define ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_() {
+; CHECK-LABEL: define ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_() {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[FOR_COND_I:.*]]
+; CHECK:       [[FOR_COND_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[INCDEC_PTR12_I:%.*]], %[[IF_END11_I:.*]] ]
+; CHECK-NEXT:    [[__TRIP_COUNT_0_I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ 1, %[[IF_END11_I]] ]
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp sgt i64 [[__TRIP_COUNT_0_I]], 0
+; CHECK-NEXT:    br i1 [[CMP_I]], label %[[FOR_BODY_I:.*]], label %[[FOR_END_I:.*]]
+; CHECK:       [[FOR_BODY_I]]:
+; CHECK-NEXT:    [[CALL_I:%.*]] = load i1, ptr [[__FIRST_ADDR_01_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT6:.*]], label %[[IF_END_I:.*]]
+; CHECK:       [[IF_END_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I]], i64 1
+; CHECK-NEXT:    [[CALL1_I:%.*]] = load i1, ptr [[INCDEC_PTR_I]], align 1
+; CHECK-NEXT:    br i1 [[CALL1_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT4:.*]], label %[[IF_END3_I:.*]]
+; CHECK:       [[IF_END3_I]]:
+; CHECK-NEXT:    [[CALL5_I:%.*]] = load i1, ptr inttoptr (i64 2 to ptr), align 1
+; CHECK-NEXT:    br i1 [[CALL5_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT2:.*]], label %[[IF_END7_I:.*]]
+; CHECK:       [[IF_END7_I]]:
+; CHECK-NEXT:    [[CALL9_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL9_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT:.*]], label %[[IF_END11_I]]
+; CHECK:       [[IF_END11_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR12_I]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I]], i64 4
+; CHECK-NEXT:    br label %[[FOR_COND_I]]
+; CHECK:       [[FOR_END_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_LCSSA:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I]], %[[FOR_COND_I]] ]
+; CHECK-NEXT:    [[SUB_PTR_RHS_CAST14_I:%.*]] = ptrtoint ptr [[__FIRST_ADDR_01_I_LCSSA]] to i64
+; CHECK-NEXT:    switch i64 [[SUB_PTR_RHS_CAST14_I]], label %[[SW_DEFAULT_I:.*]] [
+; CHECK-NEXT:      i64 -3, label %[[SW_BB_I:.*]]
+; CHECK-NEXT:      i64 1, label %[[SW_BB20_I:.*]]
+; CHECK-NEXT:      i64 0, label %[[SW_BB25_I:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW_BB_I]]:
+; CHECK-NEXT:    [[CALL16_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL16_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT:.*]], label %[[IF_END18_I:.*]]
+; CHECK:       [[IF_END18_I]]:
+; CHECK-NEXT:    [[INCDEC_PTR19_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_LCSSA]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB20_I]]
+; CHECK:       [[SW_BB20_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_1_I:%.*]] = phi ptr [ null, %[[FOR_END_I]] ], [ [[INCDEC_PTR19_I]], %[[IF_END18_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR24_I:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_1_I]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB25_I]]
+; CHECK:       [[SW_BB25_I]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_2_I:%.*]] = phi ptr [ null, %[[FOR_END_I]] ], [ [[INCDEC_PTR24_I]], %[[SW_BB20_I]] ]
+; CHECK-NEXT:    [[CALL26_I:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL26_I]], label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT]], label %[[SW_DEFAULT_I]]
+; CHECK:       [[SW_DEFAULT_I]]:
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_PH_PH:%.*]] = phi ptr [ null, %[[IF_END7_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT:.*]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT2]]:
+; CHECK-NEXT:    [[RETVAL_0_I_PH_PH3:%.*]] = phi ptr [ null, %[[IF_END3_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT4]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_I_LCSSA8:%.*]] = phi ptr [ [[__FIRST_ADDR_01_I]], %[[IF_END_I]] ]
+; CHECK-NEXT:    [[INCDEC_PTR_I_LE:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_I_LCSSA8]], i64 1
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT6]]:
+; CHECK-NEXT:    [[RETVAL_0_I_PH_PH7:%.*]] = phi ptr [ null, %[[FOR_BODY_I]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I_PH:%.*]] = phi ptr [ [[RETVAL_0_I_PH_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT]] ], [ [[RETVAL_0_I_PH_PH3]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT2]] ], [ [[INCDEC_PTR_I_LE]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT4]] ], [ [[RETVAL_0_I_PH_PH7]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT_SPLIT_LOOP_EXIT6]] ]
+; CHECK-NEXT:    br label %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT]]
+; CHECK:       [[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_I:%.*]] = phi ptr [ null, %[[SW_DEFAULT_I]] ], [ null, %[[SW_BB_I]] ], [ [[__FIRST_ADDR_2_I]], %[[SW_BB25_I]] ], [ [[RETVAL_0_I_PH]], %[[_ZST9__FIND_IFIPCN9__GNU_CXX5__OPS16_ITER_EQUALS_VALIKCEEET_S6_S6_T0_ST26RANDOM_ACCESS_ITERATOR_TAG_EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret ptr [[RETVAL_0_I]]
+;
 entry:
   %call1 = call ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_St26random_access_iterator_tag(ptr null)
   ret ptr %call1
 }
 
 define ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_St26random_access_iterator_tag(ptr %__first.addr.0) {
+; CHECK-LABEL: define ptr @_ZSt9__find_ifIPcN9__gnu_cxx5__ops16_Iter_equals_valIKcEEET_S6_S6_T0_St26random_access_iterator_tag(
+; CHECK-SAME: ptr [[__FIRST_ADDR_0:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[INCDEC_PTR4:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_0]], i64 2
+; CHECK-NEXT:    br label %[[FOR_COND:.*]]
+; CHECK:       [[FOR_COND]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[INCDEC_PTR12:%.*]], %[[IF_END11:.*]] ]
+; CHECK-NEXT:    [[__TRIP_COUNT_0:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ 1, %[[IF_END11]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[__TRIP_COUNT_0]], 0
+; CHECK-NEXT:    br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[CALL:%.*]] = load i1, ptr [[__FIRST_ADDR_01]], align 1
+; CHECK-NEXT:    br i1 [[CALL]], label %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT:.*]], label %[[IF_END:.*]]
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01]], i64 1
+; CHECK-NEXT:    [[CALL1:%.*]] = load i1, ptr [[INCDEC_PTR]], align 1
+; CHECK-NEXT:    br i1 [[CALL1]], label %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT2:.*]], label %[[IF_END3:.*]]
+; CHECK:       [[IF_END3]]:
+; CHECK-NEXT:    [[CALL5:%.*]] = load i1, ptr [[INCDEC_PTR4]], align 1
+; CHECK-NEXT:    br i1 [[CALL5]], label %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT4:.*]], label %[[IF_END7:.*]]
+; CHECK:       [[IF_END7]]:
+; CHECK-NEXT:    [[CALL9:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL9]], label %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT6:.*]], label %[[IF_END11]]
+; CHECK:       [[IF_END11]]:
+; CHECK-NEXT:    [[INCDEC_PTR12]] = getelementptr i8, ptr [[__FIRST_ADDR_01]], i64 4
+; CHECK-NEXT:    br label %[[FOR_COND]]
+; CHECK:       [[FOR_END]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_LCSSA:%.*]] = phi ptr [ [[__FIRST_ADDR_01]], %[[FOR_COND]] ]
+; CHECK-NEXT:    [[SUB_PTR_RHS_CAST14:%.*]] = ptrtoint ptr [[__FIRST_ADDR_01_LCSSA]] to i64
+; CHECK-NEXT:    switch i64 [[SUB_PTR_RHS_CAST14]], label %[[SW_DEFAULT:.*]] [
+; CHECK-NEXT:      i64 -3, label %[[SW_BB:.*]]
+; CHECK-NEXT:      i64 1, label %[[SW_BB20:.*]]
+; CHECK-NEXT:      i64 0, label %[[SW_BB25:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW_BB]]:
+; CHECK-NEXT:    [[CALL16:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL16]], label %[[CLEANUP:.*]], label %[[IF_END18:.*]]
+; CHECK:       [[IF_END18]]:
+; CHECK-NEXT:    [[INCDEC_PTR19:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_LCSSA]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB20]]
+; CHECK:       [[SW_BB20]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_1:%.*]] = phi ptr [ null, %[[FOR_END]] ], [ [[INCDEC_PTR19]], %[[IF_END18]] ]
+; CHECK-NEXT:    [[INCDEC_PTR24:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_1]], i64 1
+; CHECK-NEXT:    br label %[[SW_BB25]]
+; CHECK:       [[SW_BB25]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_2:%.*]] = phi ptr [ null, %[[FOR_END]] ], [ [[INCDEC_PTR24]], %[[SW_BB20]] ]
+; CHECK-NEXT:    [[CALL26:%.*]] = load i1, ptr null, align 1
+; CHECK-NEXT:    br i1 [[CALL26]], label %[[CLEANUP]], label %[[SW_DEFAULT]]
+; CHECK:       [[SW_DEFAULT]]:
+; CHECK-NEXT:    br label %[[CLEANUP]]
+; CHECK:       [[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_PH_PH:%.*]] = phi ptr [ null, %[[FOR_BODY]] ]
+; CHECK-NEXT:    br label %[[CLEANUP_LOOPEXIT:.*]]
+; CHECK:       [[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT2]]:
+; CHECK-NEXT:    [[__FIRST_ADDR_01_LCSSA8:%.*]] = phi ptr [ [[__FIRST_ADDR_01]], %[[IF_END]] ]
+; CHECK-NEXT:    [[INCDEC_PTR_LE:%.*]] = getelementptr i8, ptr [[__FIRST_ADDR_01_LCSSA8]], i64 1
+; CHECK-NEXT:    br label %[[CLEANUP_LOOPEXIT]]
+; CHECK:       [[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT4]]:
+; CHECK-NEXT:    [[RETVAL_0_PH_PH5:%.*]] = phi ptr [ null, %[[IF_END3]] ]
+; CHECK-NEXT:    br label %[[CLEANUP_LOOPEXIT]]
+; CHECK:       [[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT6]]:
+; CHECK-NEXT:    [[RETVAL_0_PH_PH7:%.*]] = phi ptr [ null, %[[IF_END7]] ]
+; CHECK-NEXT:    br label %[[CLEANUP_LOOPEXIT]]
+; CHECK:       [[CLEANUP_LOOPEXIT]]:
+; CHECK-NEXT:    [[RETVAL_0_PH:%.*]] = phi ptr [ [[RETVAL_0_PH_PH]], %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT]] ], [ [[INCDEC_PTR_LE]], %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT2]] ], [ [[RETVAL_0_PH_PH5]], %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT4]] ], [ [[RETVAL_0_PH_PH7]], %[[CLEANUP_LOOPEXIT_SPLIT_LOOP_EXIT6]] ]
+; CHECK-NEXT:    br label %[[CLEANUP]]
+; CHECK:       [[CLEANUP]]:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ null, %[[SW_DEFAULT]] ], [ null, %[[SW_BB]] ], [ [[__FIRST_ADDR_2]], %[[SW_BB25]] ], [ [[RETVAL_0_PH]], %[[CLEANUP_LOOPEXIT]] ]
+; CHECK-NEXT:    ret ptr [[RETVAL_0]]
+;
 entry:
   br label %for.cond
 
@@ -268,9 +851,9 @@ if.end11:                                         ; preds = %if.end7
 for.end:                                          ; preds = %for.cond
   %sub.ptr.rhs.cast14 = ptrtoint ptr %__first.addr.01 to i64
   switch i64 %sub.ptr.rhs.cast14, label %sw.default [
-    i64 -3, label %sw.bb
-    i64 1, label %sw.bb20
-    i64 0, label %sw.bb25
+  i64 -3, label %sw.bb
+  i64 1, label %sw.bb20
+  i64 0, label %sw.bb25
   ]
 
 sw.bb:                                            ; preds = %for.end

>From d768432d3b1dd6a6c7bba76f833b2d8ea92fc6b1 Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Mon, 23 Sep 2024 01:13:55 -0700
Subject: [PATCH 07/10] [LICM] Use DomTreeUpdater version of
 SplitBlockPredecessors, nfc

The DominatorTree version is marked for deprecation, so we use the
DomTreeUpdater version. We also update sinkRegion() to iterate over
basic blocks instead of DomTreeNodes. The loop body calls
SplitBlockPredecessors. The DTU version calls
DomTreeUpdater::apply_updates(), which may call DominatorTree::reset().
This invalidates the worklist of DomTreeNodes to iterate over.

The added test would crash if we iterated over DomTreeNodes and called
the SplitBlockPredecessors DTU version.
---
 llvm/include/llvm/Transforms/Utils/LoopUtils.h |  6 +++---
 llvm/lib/Transforms/Scalar/LICM.cpp            | 12 ++++++------
 llvm/lib/Transforms/Utils/LoopUtils.cpp        | 13 +++++++------
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index 56880bd4822c75..c5e10d6a1cdb76 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -224,9 +224,9 @@ bool promoteLoopAccessesToScalars(
     bool AllowSpeculation, bool HasReadsOutsideSet);
 
 /// Does a BFS from a given node to all of its children inside a given loop.
-/// The returned vector of nodes includes the starting point.
-SmallVector<DomTreeNode *, 16> collectChildrenInLoop(DomTreeNode *N,
-                                                     const Loop *CurLoop);
+/// The returned vector of basic blocks includes the starting point.
+SmallVector<BasicBlock *, 16>
+collectChildrenInLoop(DominatorTree *DT, DomTreeNode *N, const Loop *CurLoop);
 
 /// Returns the instructions that use values defined in the loop.
 SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L);
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 86c7dceffc5245..00bb03de5f6c22 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -44,6 +44,7 @@
 #include "llvm/Analysis/AliasSetTracker.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/Analysis/GuardUtils.h"
 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
 #include "llvm/Analysis/Loads.h"
@@ -65,9 +66,9 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/PatternMatch.h"
@@ -567,12 +568,10 @@ bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
   // We want to visit children before parents. We will enqueue all the parents
   // before their children in the worklist and process the worklist in reverse
   // order.
-  SmallVector<DomTreeNode *, 16> Worklist = collectChildrenInLoop(N, CurLoop);
+  SmallVector<BasicBlock *, 16> Worklist = collectChildrenInLoop(DT, N, CurLoop);
 
   bool Changed = false;
-  for (DomTreeNode *DTN : reverse(Worklist)) {
-    BasicBlock *BB = DTN->getBlock();
-    // Only need to process the contents of this block if it is not part of a
+  for (BasicBlock *BB : reverse(Worklist)) {
     // subloop (which would already have been processed).
     if (inSubLoop(BB, CurLoop, LI))
       continue;
@@ -1603,13 +1602,14 @@ static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT,
   //
   const auto &BlockColors = SafetyInfo->getBlockColors();
   SmallSetVector<BasicBlock *, 8> PredBBs(pred_begin(ExitBB), pred_end(ExitBB));
+  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
   while (!PredBBs.empty()) {
     BasicBlock *PredBB = *PredBBs.begin();
     assert(CurLoop->contains(PredBB) &&
            "Expect all predecessors are in the loop");
     if (PN->getBasicBlockIndex(PredBB) >= 0) {
       BasicBlock *NewPred = SplitBlockPredecessors(
-          ExitBB, PredBB, ".split.loop.exit", DT, LI, MSSAU, true);
+          ExitBB, PredBB, ".split.loop.exit", &DTU, LI, MSSAU, true);
       // Since we do not allow splitting EH-block with BlockColors in
       // canSplitPredecessors(), we can simply assign predecessor's color to
       // the new block.
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 8a8d8afece6cb4..7fc1082264d956 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -445,21 +445,22 @@ TransformationMode llvm::hasLICMVersioningTransformation(const Loop *L) {
 }
 
 /// Does a BFS from a given node to all of its children inside a given loop.
-/// The returned vector of nodes includes the starting point.
-SmallVector<DomTreeNode *, 16>
-llvm::collectChildrenInLoop(DomTreeNode *N, const Loop *CurLoop) {
-  SmallVector<DomTreeNode *, 16> Worklist;
+/// The returned vector of basic blocks includes the starting point.
+SmallVector<BasicBlock *, 16> llvm::collectChildrenInLoop(DominatorTree *DT,
+                                                          DomTreeNode *N,
+                                                          const Loop *CurLoop) {
+  SmallVector<BasicBlock *, 16> Worklist;
   auto AddRegionToWorklist = [&](DomTreeNode *DTN) {
     // Only include subregions in the top level loop.
     BasicBlock *BB = DTN->getBlock();
     if (CurLoop->contains(BB))
-      Worklist.push_back(DTN);
+      Worklist.push_back(DTN->getBlock());
   };
 
   AddRegionToWorklist(N);
 
   for (size_t I = 0; I < Worklist.size(); I++) {
-    for (DomTreeNode *Child : Worklist[I]->children())
+    for (DomTreeNode *Child : DT->getNode(Worklist[I])->children())
       AddRegionToWorklist(Child);
   }
 

>From 842a1ab62bfaa2db5fa1418125370a853fd2dbfc Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Mon, 23 Sep 2024 01:28:25 -0700
Subject: [PATCH 08/10] Add a note to the test

---
 llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
index f267febea89953..1e1dc03d53dff3 100644
--- a/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
+++ b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -S -passes='cgscc(devirt<4>(inline,function<eager-inv;no-rerun>(early-cse<memssa>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,loop-mssa(licm<allowspeculation>))))' < %s | FileCheck %s
 
+; Tests that we should not iterate over DomTreeNodes and modify the DomTree at the same time.
+
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 

>From feb3971b91db6bfd5176ecbfd9b2aad6f5151619 Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Mon, 23 Sep 2024 01:47:43 -0700
Subject: [PATCH 09/10] Fix formatting

---
 llvm/lib/Transforms/Scalar/LICM.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 00bb03de5f6c22..0e11b0f896245a 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -568,7 +568,8 @@ bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
   // We want to visit children before parents. We will enqueue all the parents
   // before their children in the worklist and process the worklist in reverse
   // order.
-  SmallVector<BasicBlock *, 16> Worklist = collectChildrenInLoop(DT, N, CurLoop);
+  SmallVector<BasicBlock *, 16> Worklist =
+      collectChildrenInLoop(DT, N, CurLoop);
 
   bool Changed = false;
   for (BasicBlock *BB : reverse(Worklist)) {

>From 860f4ac367e6efcd03dd73c04fa79e589a2aedbe Mon Sep 17 00:00:00 2001
From: Joshua Cao <cao.joshua at yahoo.com>
Date: Tue, 24 Sep 2024 01:48:21 -0700
Subject: [PATCH 10/10] Remove uselistorder from test

---
 llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
index 1e1dc03d53dff3..634b74087ab98f 100644
--- a/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
+++ b/llvm/test/Transforms/LICM/iterate-over-dom-nodes.ll
@@ -883,7 +883,3 @@ cleanup:                                          ; preds = %sw.default, %sw.bb2
   %retval.0 = phi ptr [ null, %sw.default ], [ null, %for.body ], [ %incdec.ptr, %if.end ], [ null, %if.end3 ], [ null, %if.end7 ], [ null, %sw.bb ], [ %__first.addr.2, %sw.bb25 ]
   ret ptr %retval.0
 }
-
-; uselistorder directives
-uselistorder ptr @_ZNK4llvm16itanium_demangle12OutputBuffer18getCurrentPositionEv, { 1, 0 }
-



More information about the llvm-commits mailing list