rename a function to indicate that it checks for profitability as well
authorChris Lattner <sabre@nondot.org>
Sat, 21 Feb 2009 00:46:50 +0000 (00:46 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 21 Feb 2009 00:46:50 +0000 (00:46 +0000)
as legality.  Make load sinking and gep sinking more careful: we only
do it when it won't pessimize loads from the stack.  This has the added
benefit of not producing code that is unanalyzable to SROA.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@65209 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/2009-02-20-InstCombine-SROA.ll [new file with mode: 0644]

index bca6abc60515e3d64a87d60148e01fbc46192c0b..9f72910cb759d51648798f55b56d7703ef018bf1 100644 (file)
@@ -10180,6 +10180,9 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) {
   
   SmallVector<Value*, 16> FixedOperands(FirstInst->op_begin(), 
                                         FirstInst->op_end());
+  // This is true if all GEP bases are allocas and if all indices into them are
+  // constants.
+  bool AllBasePointersAreAllocas = true;
   
   // Scan to see if all operands are the same opcode, all have one use, and all
   // kill their operands (i.e. the operands have one use).
@@ -10189,6 +10192,12 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) {
       GEP->getNumOperands() != FirstInst->getNumOperands())
       return 0;
 
+    // Keep track of whether or not all GEPs are of alloca pointers.
+    if (AllBasePointersAreAllocas &&
+        (!isa<AllocaInst>(GEP->getOperand(0)) ||
+         !GEP->hasAllConstantIndices()))
+      AllBasePointersAreAllocas = false;
+    
     // Compare the operand lists.
     for (unsigned op = 0, e = FirstInst->getNumOperands(); op != e; ++op) {
       if (FirstInst->getOperand(op) == GEP->getOperand(op))
@@ -10209,6 +10218,15 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) {
     }
   }
   
+  // If all of the base pointers of the PHI'd GEPs are from allocas, don't
+  // bother doing this transformation.  At best, this will just safe a bit of
+  // offset calculation, but all the predecessors will have to materialize the
+  // stack address into a register anyway.  We'd actually rather *clone* the
+  // load up into the predecessors so that we have a load of a gep of an alloca,
+  // which can usually all be folded into the load.
+  if (AllBasePointersAreAllocas)
+    return 0;
+  
   // Otherwise, this is safe to transform.  Insert PHI nodes for each operand
   // that is variable.
   SmallVector<PHINode*, 16> OperandPhis(FixedOperands.size());
@@ -10247,15 +10265,15 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) {
 }
 
 
-/// isSafeToSinkLoad - Return true if we know that it is safe sink the load out
-/// of the block that defines it.  This means that it must be obvious the value
-/// of the load is not changed from the point of the load to the end of the
-/// block it is in.
+/// isSafeAndProfitableToSinkLoad - Return true if we know that it is safe sink
+/// the load out of the block that defines it.  This means that it must be
+/// obvious the value of the load is not changed from the point of the load to
+/// the end of the block it is in.
 ///
 /// Finally, it is safe, but not profitable, to sink a load targetting a
 /// non-address-taken alloca.  Doing so will cause us to not promote the alloca
 /// to a register.
-static bool isSafeToSinkLoad(LoadInst *L) {
+static bool isSafeAndProfitableToSinkLoad(LoadInst *L) {
   BasicBlock::iterator BBI = L, E = L->getParent()->end();
   
   for (++BBI; BBI != E; ++BBI)
@@ -10277,10 +10295,20 @@ static bool isSafeToSinkLoad(LoadInst *L) {
       break;
     }
     
-    if (!isAddressTaken)
+    if (!isAddressTaken && AI->isStaticAlloca())
       return false;
   }
   
+  // If this load is a load from a GEP with a constant offset from an alloca,
+  // then we don't want to sink it.  In its present form, it will be
+  // load [constant stack offset].  Sinking it will cause us to have to
+  // materialize the stack addresses in each predecessor in a register only to
+  // do a shared load from register in the successor.
+  if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(L->getOperand(0)))
+    if (AllocaInst *AI = dyn_cast<AllocaInst>(GEP->getOperand(0)))
+      if (AI->isStaticAlloca() && GEP->hasAllConstantIndices())
+        return false;
+  
   return true;
 }
 
@@ -10311,7 +10339,7 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
     // We can't sink the load if the loaded value could be modified between the
     // load and the PHI.
     if (LI->getParent() != PN.getIncomingBlock(0) ||
-        !isSafeToSinkLoad(LI))
+        !isSafeAndProfitableToSinkLoad(LI))
       return 0;
     
     // If the PHI is of volatile loads and the load block has multiple
@@ -10341,7 +10369,7 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
       // the load and the PHI.
       if (LI->isVolatile() != isVolatile ||
           LI->getParent() != PN.getIncomingBlock(i) ||
-          !isSafeToSinkLoad(LI))
+          !isSafeAndProfitableToSinkLoad(LI))
         return 0;
       
       // If the PHI is of volatile loads and the load block has multiple
@@ -10350,7 +10378,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
       if (isVolatile &&
           LI->getParent()->getTerminator()->getNumSuccessors() != 1)
         return 0;
-
       
     } else if (I->getOperand(1) != ConstantOp) {
       return 0;
diff --git a/test/Transforms/InstCombine/2009-02-20-InstCombine-SROA.ll b/test/Transforms/InstCombine/2009-02-20-InstCombine-SROA.ll
new file mode 100644 (file)
index 0000000..52bcead
--- /dev/null
@@ -0,0 +1,278 @@
+; RUN: llvm-as < %s | opt -instcombine -scalarrepl | llvm-dis | not grep { = alloca}
+; rdar://6417724
+; Instcombine shouldn't do anything to this function that prevents promoting the allocas inside it.
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9.6"
+       %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >" = type { i32* }
+       %"struct.std::_Vector_base<int,std::allocator<int> >" = type { %"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl" }
+       %"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl" = type { i32*, i32*, i32* }
+       %"struct.std::bidirectional_iterator_tag" = type <{ i8 }>
+       %"struct.std::forward_iterator_tag" = type <{ i8 }>
+       %"struct.std::input_iterator_tag" = type <{ i8 }>
+       %"struct.std::random_access_iterator_tag" = type <{ i8 }>
+       %"struct.std::vector<int,std::allocator<int> >" = type { %"struct.std::_Vector_base<int,std::allocator<int> >" }
+
+define i32* @_Z3fooRSt6vectorIiSaIiEE(%"struct.std::vector<int,std::allocator<int> >"* %X) {
+entry:
+       %0 = alloca %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"                ; <%"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"*> [#uses=2]
+       %__first_addr.i.i = alloca %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"         ; <%"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"*> [#uses=31]
+       %__last_addr.i.i = alloca %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"          ; <%"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"*> [#uses=4]
+       %unnamed_arg.i = alloca %"struct.std::bidirectional_iterator_tag", align 8              ; <%"struct.std::bidirectional_iterator_tag"*> [#uses=1]
+       %1 = alloca %"struct.std::bidirectional_iterator_tag"           ; <%"struct.std::bidirectional_iterator_tag"*> [#uses=1]
+       %__first_addr.i = alloca %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"           ; <%"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"*> [#uses=2]
+       %2 = alloca %"struct.std::bidirectional_iterator_tag"           ; <%"struct.std::bidirectional_iterator_tag"*> [#uses=2]
+       %3 = alloca %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"                ; <%"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"*> [#uses=2]
+       %4 = alloca i32         ; <i32*> [#uses=8]
+       %"alloca point" = bitcast i32 0 to i32          ; <i32> [#uses=0]
+       store i32 42, i32* %4, align 4
+       %5 = getelementptr %"struct.std::vector<int,std::allocator<int> >"* %X, i32 0, i32 0            ; <%"struct.std::_Vector_base<int,std::allocator<int> >"*> [#uses=1]
+       %6 = getelementptr %"struct.std::_Vector_base<int,std::allocator<int> >"* %5, i32 0, i32 0              ; <%"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl"*> [#uses=1]
+       %7 = getelementptr %"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl"* %6, i32 0, i32 1                ; <i32**> [#uses=1]
+       %8 = load i32** %7, align 4             ; <i32*> [#uses=1]
+       %9 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %3, i32 0, i32 0               ; <i32**> [#uses=1]
+       store i32* %8, i32** %9, align 4
+       %10 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %3, i32 0, i32 0              ; <i32**> [#uses=1]
+       %11 = load i32** %10, align 4           ; <i32*> [#uses=1]
+       %tmp2.i = ptrtoint i32* %11 to i32              ; <i32> [#uses=1]
+       %tmp1.i = inttoptr i32 %tmp2.i to i32*          ; <i32*> [#uses=1]
+       %tmp3 = ptrtoint i32* %tmp1.i to i32            ; <i32> [#uses=1]
+       %tmp2 = inttoptr i32 %tmp3 to i32*              ; <i32*> [#uses=1]
+       %12 = getelementptr %"struct.std::vector<int,std::allocator<int> >"* %X, i32 0, i32 0           ; <%"struct.std::_Vector_base<int,std::allocator<int> >"*> [#uses=1]
+       %13 = getelementptr %"struct.std::_Vector_base<int,std::allocator<int> >"* %12, i32 0, i32 0            ; <%"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl"*> [#uses=1]
+       %14 = getelementptr %"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl"* %13, i32 0, i32 0              ; <i32**> [#uses=1]
+       %15 = load i32** %14, align 4           ; <i32*> [#uses=1]
+       %16 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %0, i32 0, i32 0              ; <i32**> [#uses=1]
+       store i32* %15, i32** %16, align 4
+       %17 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %0, i32 0, i32 0              ; <i32**> [#uses=1]
+       %18 = load i32** %17, align 4           ; <i32*> [#uses=1]
+       %tmp2.i17 = ptrtoint i32* %18 to i32            ; <i32> [#uses=1]
+       %tmp1.i18 = inttoptr i32 %tmp2.i17 to i32*              ; <i32*> [#uses=1]
+       %tmp8 = ptrtoint i32* %tmp1.i18 to i32          ; <i32> [#uses=1]
+       %tmp6 = inttoptr i32 %tmp8 to i32*              ; <i32*> [#uses=1]
+       %19 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i, i32 0, i32 0         ; <i32**> [#uses=1]
+       store i32* %tmp6, i32** %19
+       %20 = getelementptr %"struct.std::bidirectional_iterator_tag"* %1, i32 0, i32 0         ; <i8*> [#uses=1]
+       %21 = load i8* %20, align 1             ; <i8> [#uses=1]
+       %22 = or i8 %21, 0              ; <i8> [#uses=1]
+       %23 = or i8 %22, 0              ; <i8> [#uses=1]
+       %24 = or i8 %23, 0              ; <i8> [#uses=0]
+       %25 = getelementptr %"struct.std::bidirectional_iterator_tag"* %2, i32 0, i32 0         ; <i8*> [#uses=1]
+       store i8 0, i8* %25, align 1
+       %elt.i = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %val.i = load i32** %elt.i              ; <i32*> [#uses=1]
+       %tmp.i = bitcast %"struct.std::bidirectional_iterator_tag"* %unnamed_arg.i to i8*               ; <i8*> [#uses=1]
+       %tmp9.i = bitcast %"struct.std::bidirectional_iterator_tag"* %2 to i8*          ; <i8*> [#uses=1]
+       call void @llvm.memcpy.i64(i8* %tmp.i, i8* %tmp9.i, i64 1, i32 1)
+       %26 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       store i32* %val.i, i32** %26
+       %27 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__last_addr.i.i, i32 0, i32 0                ; <i32**> [#uses=1]
+       store i32* %tmp2, i32** %27
+       %28 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__last_addr.i.i, i32 0, i32 0                ; <i32**> [#uses=1]
+       %29 = load i32** %28, align 4           ; <i32*> [#uses=1]
+       %30 = ptrtoint i32* %29 to i32          ; <i32> [#uses=1]
+       %31 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %32 = load i32** %31, align 4           ; <i32*> [#uses=1]
+       %33 = ptrtoint i32* %32 to i32          ; <i32> [#uses=1]
+       %34 = sub i32 %30, %33          ; <i32> [#uses=1]
+       %35 = ashr i32 %34, 2           ; <i32> [#uses=1]
+       %36 = ashr i32 %35, 2           ; <i32> [#uses=1]
+       br label %bb12.i.i
+
+bb.i.i:                ; preds = %bb12.i.i
+       %37 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %38 = load i32** %37, align 4           ; <i32*> [#uses=1]
+       %39 = load i32* %38, align 4            ; <i32> [#uses=1]
+       %40 = load i32* %4, align 4             ; <i32> [#uses=1]
+       %41 = icmp eq i32 %39, %40              ; <i1> [#uses=1]
+       %42 = zext i1 %41 to i8         ; <i8> [#uses=1]
+       %toBool.i.i = icmp ne i8 %42, 0         ; <i1> [#uses=1]
+       br i1 %toBool.i.i, label %bb1.i.i, label %bb2.i.i
+
+bb1.i.i:               ; preds = %bb.i.i
+       %43 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %44 = load i32** %43, align 4           ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+bb2.i.i:               ; preds = %bb.i.i
+       %45 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %46 = load i32** %45, align 4           ; <i32*> [#uses=1]
+       %47 = getelementptr i32* %46, i64 1             ; <i32*> [#uses=1]
+       %48 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       store i32* %47, i32** %48, align 4
+       %49 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %50 = load i32** %49, align 4           ; <i32*> [#uses=1]
+       %51 = load i32* %50, align 4            ; <i32> [#uses=1]
+       %52 = load i32* %4, align 4             ; <i32> [#uses=1]
+       %53 = icmp eq i32 %51, %52              ; <i1> [#uses=1]
+       %54 = zext i1 %53 to i8         ; <i8> [#uses=1]
+       %toBool3.i.i = icmp ne i8 %54, 0                ; <i1> [#uses=1]
+       br i1 %toBool3.i.i, label %bb4.i.i, label %bb5.i.i
+
+bb4.i.i:               ; preds = %bb2.i.i
+       %55 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %56 = load i32** %55, align 4           ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+bb5.i.i:               ; preds = %bb2.i.i
+       %57 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %58 = load i32** %57, align 4           ; <i32*> [#uses=1]
+       %59 = getelementptr i32* %58, i64 1             ; <i32*> [#uses=1]
+       %60 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       store i32* %59, i32** %60, align 4
+       %61 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %62 = load i32** %61, align 4           ; <i32*> [#uses=1]
+       %63 = load i32* %62, align 4            ; <i32> [#uses=1]
+       %64 = load i32* %4, align 4             ; <i32> [#uses=1]
+       %65 = icmp eq i32 %63, %64              ; <i1> [#uses=1]
+       %66 = zext i1 %65 to i8         ; <i8> [#uses=1]
+       %toBool6.i.i = icmp ne i8 %66, 0                ; <i1> [#uses=1]
+       br i1 %toBool6.i.i, label %bb7.i.i, label %bb8.i.i
+
+bb7.i.i:               ; preds = %bb5.i.i
+       %67 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %68 = load i32** %67, align 4           ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+bb8.i.i:               ; preds = %bb5.i.i
+       %69 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %70 = load i32** %69, align 4           ; <i32*> [#uses=1]
+       %71 = getelementptr i32* %70, i64 1             ; <i32*> [#uses=1]
+       %72 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       store i32* %71, i32** %72, align 4
+       %73 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %74 = load i32** %73, align 4           ; <i32*> [#uses=1]
+       %75 = load i32* %74, align 4            ; <i32> [#uses=1]
+       %76 = load i32* %4, align 4             ; <i32> [#uses=1]
+       %77 = icmp eq i32 %75, %76              ; <i1> [#uses=1]
+       %78 = zext i1 %77 to i8         ; <i8> [#uses=1]
+       %toBool9.i.i = icmp ne i8 %78, 0                ; <i1> [#uses=1]
+       br i1 %toBool9.i.i, label %bb10.i.i, label %bb11.i.i
+
+bb10.i.i:              ; preds = %bb8.i.i
+       %79 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %80 = load i32** %79, align 4           ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+bb11.i.i:              ; preds = %bb8.i.i
+       %81 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %82 = load i32** %81, align 4           ; <i32*> [#uses=1]
+       %83 = getelementptr i32* %82, i64 1             ; <i32*> [#uses=1]
+       %84 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       store i32* %83, i32** %84, align 4
+       %85 = sub i32 %__trip_count.0.i.i, 1            ; <i32> [#uses=1]
+       br label %bb12.i.i
+
+bb12.i.i:              ; preds = %bb11.i.i, %entry
+       %__trip_count.0.i.i = phi i32 [ %36, %entry ], [ %85, %bb11.i.i ]               ; <i32> [#uses=2]
+       %86 = icmp sgt i32 %__trip_count.0.i.i, 0               ; <i1> [#uses=1]
+       br i1 %86, label %bb.i.i, label %bb13.i.i
+
+bb13.i.i:              ; preds = %bb12.i.i
+       %87 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__last_addr.i.i, i32 0, i32 0                ; <i32**> [#uses=1]
+       %88 = load i32** %87, align 4           ; <i32*> [#uses=1]
+       %89 = ptrtoint i32* %88 to i32          ; <i32> [#uses=1]
+       %90 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %91 = load i32** %90, align 4           ; <i32*> [#uses=1]
+       %92 = ptrtoint i32* %91 to i32          ; <i32> [#uses=1]
+       %93 = sub i32 %89, %92          ; <i32> [#uses=1]
+       %94 = ashr i32 %93, 2           ; <i32> [#uses=1]
+       switch i32 %94, label %bb26.i.i [
+               i32 1, label %bb22.i.i
+               i32 2, label %bb18.i.i
+               i32 3, label %bb14.i.i
+       ]
+
+bb14.i.i:              ; preds = %bb13.i.i
+       %95 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %96 = load i32** %95, align 4           ; <i32*> [#uses=1]
+       %97 = load i32* %96, align 4            ; <i32> [#uses=1]
+       %98 = load i32* %4, align 4             ; <i32> [#uses=1]
+       %99 = icmp eq i32 %97, %98              ; <i1> [#uses=1]
+       %100 = zext i1 %99 to i8                ; <i8> [#uses=1]
+       %toBool15.i.i = icmp ne i8 %100, 0              ; <i1> [#uses=1]
+       br i1 %toBool15.i.i, label %bb16.i.i, label %bb17.i.i
+
+bb16.i.i:              ; preds = %bb14.i.i
+       %101 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %102 = load i32** %101, align 4         ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+bb17.i.i:              ; preds = %bb14.i.i
+       %103 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %104 = load i32** %103, align 4         ; <i32*> [#uses=1]
+       %105 = getelementptr i32* %104, i64 1           ; <i32*> [#uses=1]
+       %106 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       store i32* %105, i32** %106, align 4
+       br label %bb18.i.i
+
+bb18.i.i:              ; preds = %bb17.i.i, %bb13.i.i
+       %107 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %108 = load i32** %107, align 4         ; <i32*> [#uses=1]
+       %109 = load i32* %108, align 4          ; <i32> [#uses=1]
+       %110 = load i32* %4, align 4            ; <i32> [#uses=1]
+       %111 = icmp eq i32 %109, %110           ; <i1> [#uses=1]
+       %112 = zext i1 %111 to i8               ; <i8> [#uses=1]
+       %toBool19.i.i = icmp ne i8 %112, 0              ; <i1> [#uses=1]
+       br i1 %toBool19.i.i, label %bb20.i.i, label %bb21.i.i
+
+bb20.i.i:              ; preds = %bb18.i.i
+       %113 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %114 = load i32** %113, align 4         ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+bb21.i.i:              ; preds = %bb18.i.i
+       %115 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %116 = load i32** %115, align 4         ; <i32*> [#uses=1]
+       %117 = getelementptr i32* %116, i64 1           ; <i32*> [#uses=1]
+       %118 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       store i32* %117, i32** %118, align 4
+       br label %bb22.i.i
+
+bb22.i.i:              ; preds = %bb21.i.i, %bb13.i.i
+       %119 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %120 = load i32** %119, align 4         ; <i32*> [#uses=1]
+       %121 = load i32* %120, align 4          ; <i32> [#uses=1]
+       %122 = load i32* %4, align 4            ; <i32> [#uses=1]
+       %123 = icmp eq i32 %121, %122           ; <i1> [#uses=1]
+       %124 = zext i1 %123 to i8               ; <i8> [#uses=1]
+       %toBool23.i.i = icmp ne i8 %124, 0              ; <i1> [#uses=1]
+       br i1 %toBool23.i.i, label %bb24.i.i, label %bb25.i.i
+
+bb24.i.i:              ; preds = %bb22.i.i
+       %125 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %126 = load i32** %125, align 4         ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+bb25.i.i:              ; preds = %bb22.i.i
+       %127 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       %128 = load i32** %127, align 4         ; <i32*> [#uses=1]
+       %129 = getelementptr i32* %128, i64 1           ; <i32*> [#uses=1]
+       %130 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__first_addr.i.i, i32 0, i32 0              ; <i32**> [#uses=1]
+       store i32* %129, i32** %130, align 4
+       br label %bb26.i.i
+
+bb26.i.i:              ; preds = %bb25.i.i, %bb13.i.i
+       %131 = getelementptr %"struct.__gnu_cxx::__normal_iterator<int*,std::vector<int, std::allocator<int> > >"* %__last_addr.i.i, i32 0, i32 0               ; <i32**> [#uses=1]
+       %132 = load i32** %131, align 4         ; <i32*> [#uses=1]
+       br label %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+
+_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit:            ; preds = %bb26.i.i, %bb24.i.i, %bb20.i.i, %bb16.i.i, %bb10.i.i, %bb7.i.i, %bb4.i.i, %bb1.i.i
+       %.0.0.i.i = phi i32* [ %132, %bb26.i.i ], [ %126, %bb24.i.i ], [ %114, %bb20.i.i ], [ %102, %bb16.i.i ], [ %80, %bb10.i.i ], [ %68, %bb7.i.i ], [ %56, %bb4.i.i ], [ %44, %bb1.i.i ]            ; <i32*> [#uses=1]
+       %tmp2.i.i = ptrtoint i32* %.0.0.i.i to i32              ; <i32> [#uses=1]
+       %tmp1.i.i = inttoptr i32 %tmp2.i.i to i32*              ; <i32*> [#uses=1]
+       %tmp4.i = ptrtoint i32* %tmp1.i.i to i32                ; <i32> [#uses=1]
+       %tmp3.i = inttoptr i32 %tmp4.i to i32*          ; <i32*> [#uses=1]
+       %tmp8.i = ptrtoint i32* %tmp3.i to i32          ; <i32> [#uses=1]
+       %tmp6.i = inttoptr i32 %tmp8.i to i32*          ; <i32*> [#uses=1]
+       %tmp12 = ptrtoint i32* %tmp6.i to i32           ; <i32> [#uses=1]
+       %tmp10 = inttoptr i32 %tmp12 to i32*            ; <i32*> [#uses=1]
+       %tmp16 = ptrtoint i32* %tmp10 to i32            ; <i32> [#uses=1]
+       br label %return
+
+return:                ; preds = %_ZSt4findIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiET_S7_S7_RKT0_.exit
+       %tmp14 = inttoptr i32 %tmp16 to i32*            ; <i32*> [#uses=1]
+       ret i32* %tmp14
+}
+
+declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind