Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -621,9 +621,13 @@ DestBB->moveAfter(PredBB); if (DT) { - BasicBlock *PredBBIDom = DT->getNode(PredBB)->getIDom()->getBlock(); - DT->changeImmediateDominator(DestBB, PredBBIDom); - DT->eraseNode(PredBB); + // For some irreducible CFG we end up having forward-unreachable blocks + // so check if getNode returns a valid node before updating the domtree. + if (DomTreeNode *DTN = DT->getNode(PredBB)) { + BasicBlock *PredBBIDom = DTN->getIDom()->getBlock(); + DT->changeImmediateDominator(DestBB, PredBBIDom); + DT->eraseNode(PredBB); + } } // Nuke BB. PredBB->eraseFromParent(); Index: unittests/Transforms/Utils/Local.cpp =================================================================== --- unittests/Transforms/Utils/Local.cpp +++ unittests/Transforms/Utils/Local.cpp @@ -166,3 +166,355 @@ Declares++; EXPECT_EQ(2, Declares); } + +/// Build the dominator tree for the function and run the Test. +static void runWithDomTree( + Module &M, StringRef FuncName, + function_ref Test) { + auto *F = M.getFunction(FuncName); + ASSERT_NE(F, nullptr) << "Could not find " << FuncName; + // Compute the dominator tree for the function. + DominatorTree DT(*F); + Test(*F, &DT); +} + +TEST(Local, MergeBasicBlockIntoOnlyPred) { + LLVMContext C; + + std::unique_ptr M = parseIR( + C, + "define i32 @f(i8* %str) {\n" + "entry:\n" + " br label %bb2.i\n" + "bb2.i: ; preds = %bb4.i, %entry\n" + " br i1 false, label %bb4.i, label %base2flt.exit204\n" + "bb4.i: ; preds = %bb2.i\n" + " br i1 false, label %base2flt.exit204, label %bb2.i\n" + "bb10.i196.bb7.i197_crit_edge: ; No predecessors!\n" + " br label %bb7.i197\n" + "bb7.i197: ; preds = %bb10.i196.bb7.i197_crit_edge\n" + " %.reg2mem.0 = phi i32 [ %.reg2mem.0, %bb10.i196.bb7.i197_crit_edge ]\n" + " br i1 undef, label %base2flt.exit204, label %base2flt.exit204\n" + "base2flt.exit204: ; preds = %bb7.i197, %bb7.i197, %bb2.i, %bb4.i\n" + " br i1 false, label %base2flt.exit204.bb8_crit_edge, label %bb\n" + "base2flt.exit204.bb8_crit_edge: ; preds = %base2flt.exit204\n" + " br label %bb8\n" + "bb: ; preds = %base2flt.exit204\n" + " br i1 false, label %bb.bb18_crit_edge, label %bb1.i\n" + "bb.bb18_crit_edge: ; preds = %bb9, %bb\n" + " br label %bb18\n" + "bb1.i: ; preds = %bb\n" + " br i1 false, label %bb1.i.bb7_crit_edge, label %bb1.i158\n" + "bb1.i.bb7_crit_edge.loopexit: ; preds = %bb2.i164\n" + " br label %bb1.i.bb7_crit_edge\n" + "bb1.i.bb7_crit_edge: ; preds = %bb1.i.bb7_crit_edge.loopexit, %bb1.i\n" + " br label %bb7.preheader\n" + "bb1.i158: ; preds = %bb1.i\n" + " br i1 false, label %bb1.i158.bb10.i179_crit_edge, label %bb1.i158.bb2.i164_crit_edge\n" + "bb1.i158.bb2.i164_crit_edge: ; preds = %bb1.i158\n" + " br label %bb2.i164\n" + "bb1.i158.bb10.i179_crit_edge: ; preds = %bb1.i158\n" + " br label %bb10.i179\n" + "bb2.i164: ; preds = %bb4.i166.bb2.i164_crit_edge, %bb1.i158.bb2.i164_crit_edge\n" + " br i1 false, label %bb4.i166, label %bb1.i.bb7_crit_edge.loopexit\n" + "bb4.i166: ; preds = %bb2.i164\n" + " br i1 false, label %bb4.i166.bb11.i172_crit_edge, label %bb4.i166.bb2.i164_crit_edge\n" + "bb4.i166.bb2.i164_crit_edge: ; preds = %bb4.i166\n" + " br label %bb2.i164\n" + "bb4.i166.bb11.i172_crit_edge: ; preds = %bb4.i166\n" + " br label %bb11.i172\n" + "bb11.i172: ; preds = %bb10.i179.bb11.i172_crit_edge, %bb4.i166.bb11.i172_crit_edge\n" + " br label %bb7.preheader\n" + "bb10.i179: ; preds = %bb9.i182, %bb1.i158.bb10.i179_crit_edge\n" + " br i1 false, label %bb7.i180, label %bb10.i179.bb11.i172_crit_edge\n" + "bb10.i179.bb11.i172_crit_edge: ; preds = %bb10.i179\n" + " br label %bb11.i172\n" + "bb7.i180: ; preds = %bb10.i179\n" + " br i1 false, label %bb7.i180.bb7_crit_edge, label %bb9.i182\n" + "bb7.i180.bb7_crit_edge: ; preds = %bb7.i180\n" + " br label %bb7.preheader\n" + "bb7.preheader: ; preds = %bb7.i180.bb7_crit_edge, %bb11.i172, %bb1.i.bb7_crit_edge\n" + " br label %bb7\n" + "bb9.i182: ; preds = %bb7.i180\n" + " br label %bb10.i179\n" + "bb7: ; preds = %addflt.exit114, %bb7.preheader\n" + " switch i8 0, label %bb4 [\n" + " i8 0, label %bb7.bb8_crit_edge\n" + " i8 46, label %bb7.bb8_crit_edge\n" + " ]\n" + "bb7.bb8_crit_edge: ; preds = %bb7, %bb7\n" + " br label %bb8\n" + "bb4: ; preds = %bb7\n" + " br i1 false, label %bb18.loopexit1, label %bb1.i5\n" + "bb1.i5: ; preds = %bb4\n" + " br i1 false, label %bb1.i5.mulflt.exit157_crit_edge, label %bb3.i147\n" + "bb1.i5.mulflt.exit157_crit_edge: ; preds = %bb5.i148, %bb1.i5\n" + " br label %mulflt.exit157\n" + "bb3.i147: ; preds = %bb1.i5\n" + " br i1 false, label %bb3.i147.mulflt.exit157_crit_edge, label %bb5.i148\n" + "bb3.i147.mulflt.exit157_crit_edge: ; preds = %bb8.i150, %bb3.i147\n" + " br label %mulflt.exit157\n" + "bb5.i148: ; preds = %bb3.i147\n" + " br i1 false, label %bb1.i5.mulflt.exit157_crit_edge, label %bb7.i149\n" + "bb7.i149: ; preds = %bb5.i148\n" + " br i1 false, label %bb8.i150, label %bb7.i149.bb12.i154_crit_edge\n" + "bb7.i149.bb12.i154_crit_edge: ; preds = %bb7.i149\n" + " br label %bb12.i154\n" + "bb8.i150: ; preds = %bb7.i149\n" + " br i1 false, label %bb3.i147.mulflt.exit157_crit_edge, label %bb10.i151\n" + "bb10.i151: ; preds = %bb8.i150\n" + " br label %bb12.i154\n" + "bb12.i154: ; preds = %bb10.i151, %bb7.i149.bb12.i154_crit_edge\n" + " br label %mulflt.exit157\n" + "mulflt.exit157: ; preds = %bb12.i154, %bb3.i147.mulflt.exit157_crit_edge, %bb1.i5.mulflt.exit157_crit_edge\n" + " br i1 false, label %mulflt.exit157.base2flt.exit144_crit_edge, label %bb1.i115\n" + "mulflt.exit157.base2flt.exit144_crit_edge.loopexit: ; preds = %bb2.i121\n" + " br label %mulflt.exit157.base2flt.exit144_crit_edge\n" + "mulflt.exit157.base2flt.exit144_crit_edge: ; preds = %mulflt.exit157.base2flt.exit144_crit_edge.loopexit, %mulflt.exit157\n" + " br label %base2flt.exit144\n" + "bb1.i115: ; preds = %mulflt.exit157\n" + " br i1 false, label %bb1.i115.bb10.i136_crit_edge, label %bb1.i115.bb2.i121_crit_edge\n" + "bb1.i115.bb2.i121_crit_edge: ; preds = %bb1.i115\n" + " br label %bb2.i121\n" + "bb1.i115.bb10.i136_crit_edge: ; preds = %bb1.i115\n" + " br label %bb10.i136\n" + "bb2.i121: ; preds = %bb4.i123.bb2.i121_crit_edge, %bb1.i115.bb2.i121_crit_edge\n" + " br i1 false, label %bb4.i123, label %mulflt.exit157.base2flt.exit144_crit_edge.loopexit\n" + "bb4.i123: ; preds = %bb2.i121\n" + " br i1 false, label %bb4.i123.bb11.i129_crit_edge, label %bb4.i123.bb2.i121_crit_edge\n" + "bb4.i123.bb2.i121_crit_edge: ; preds = %bb4.i123\n" + " br label %bb2.i121\n" + "bb4.i123.bb11.i129_crit_edge: ; preds = %bb4.i123\n" + " br label %bb11.i129\n" + "bb11.i129: ; preds = %bb10.i136.bb11.i129_crit_edge, %bb4.i123.bb11.i129_crit_edge\n" + " br label %base2flt.exit144\n" + "bb10.i136: ; preds = %bb9.i139, %bb1.i115.bb10.i136_crit_edge\n" + " br i1 false, label %bb7.i137, label %bb10.i136.bb11.i129_crit_edge\n" + "bb10.i136.bb11.i129_crit_edge: ; preds = %bb10.i136\n" + " br label %bb11.i129\n" + "bb7.i137: ; preds = %bb10.i136\n" + " br i1 false, label %bb7.i137.base2flt.exit144_crit_edge, label %bb9.i139\n" + "bb7.i137.base2flt.exit144_crit_edge: ; preds = %bb7.i137\n" + " br label %base2flt.exit144\n" + "bb9.i139: ; preds = %bb7.i137\n" + " br label %bb10.i136\n" + "base2flt.exit144: ; preds = %bb7.i137.base2flt.exit144_crit_edge, %bb11.i129, %mulflt.exit157.base2flt.exit144_crit_edge\n" + " br i1 false, label %base2flt.exit144.addflt.exit114_crit_edge, label %bb3.i105\n" + "base2flt.exit144.addflt.exit114_crit_edge: ; preds = %bb3.i105, %base2flt.exit144\n" + " br label %addflt.exit114\n" + "bb3.i105: ; preds = %base2flt.exit144\n" + " br i1 false, label %base2flt.exit144.addflt.exit114_crit_edge, label %bb5.i106\n" + "bb5.i106: ; preds = %bb3.i105\n" + " br i1 false, label %bb5.i106.bb9.i111_crit_edge, label %bb6.i107\n" + "bb5.i106.bb9.i111_crit_edge: ; preds = %bb5.i106\n" + " br label %bb9.i111\n" + "bb6.i107: ; preds = %bb5.i106\n" + " br i1 false, label %bb6.i107.addflt.exit114_crit_edge, label %bb8.i108\n" + "bb6.i107.addflt.exit114_crit_edge: ; preds = %bb6.i107\n" + " br label %addflt.exit114\n" + "bb8.i108: ; preds = %bb6.i107\n" + " br label %bb9.i111\n" + "bb9.i111: ; preds = %bb8.i108, %bb5.i106.bb9.i111_crit_edge\n" + " br label %addflt.exit114\n" + "addflt.exit114: ; preds = %bb9.i111, %bb6.i107.addflt.exit114_crit_edge, %base2flt.exit144.addflt.exit114_crit_edge\n" + " br label %bb7\n" + "bb18.loopexit1: ; preds = %bb4\n" + " ret i32 -1\n" + "bb18: ; preds = %bb8.bb18_crit_edge, %bb.bb18_crit_edge\n" + " ret i32 0\n" + "bb8: ; preds = %bb7.bb8_crit_edge, %base2flt.exit204.bb8_crit_edge\n" + " br i1 false, label %bb9, label %bb8.bb18_crit_edge\n" + "bb8.bb18_crit_edge: ; preds = %bb8\n" + " br label %bb18\n" + "bb9: ; preds = %bb8\n" + " br i1 false, label %bb.bb18_crit_edge, label %bb1.i13\n" + "bb1.i13: ; preds = %bb9\n" + " br i1 false, label %bb1.i13.base2flt.exit102_crit_edge, label %bb1.i73\n" + "bb1.i13.base2flt.exit102_crit_edge.loopexit: ; preds = %bb2.i79\n" + " br label %bb1.i13.base2flt.exit102_crit_edge\n" + "bb1.i13.base2flt.exit102_crit_edge: ; preds = %bb1.i13.base2flt.exit102_crit_edge.loopexit, %bb1.i13\n" + " br label %base2flt.exit102\n" + "bb1.i73: ; preds = %bb1.i13\n" + " br i1 false, label %bb1.i73.bb10.i94_crit_edge, label %bb1.i73.bb2.i79_crit_edge\n" + "bb1.i73.bb2.i79_crit_edge: ; preds = %bb1.i73\n" + " br label %bb2.i79\n" + "bb1.i73.bb10.i94_crit_edge: ; preds = %bb1.i73\n" + " br label %bb10.i94\n" + "bb2.i79: ; preds = %bb4.i81.bb2.i79_crit_edge, %bb1.i73.bb2.i79_crit_edge\n" + " br i1 false, label %bb4.i81, label %bb1.i13.base2flt.exit102_crit_edge.loopexit\n" + "bb4.i81: ; preds = %bb2.i79\n" + " br i1 false, label %bb4.i81.bb11.i87_crit_edge, label %bb4.i81.bb2.i79_crit_edge\n" + "bb4.i81.bb2.i79_crit_edge: ; preds = %bb4.i81\n" + " br label %bb2.i79\n" + "bb4.i81.bb11.i87_crit_edge: ; preds = %bb4.i81\n" + " br label %bb11.i87\n" + "bb11.i87: ; preds = %bb10.i94.bb11.i87_crit_edge, %bb4.i81.bb11.i87_crit_edge\n" + " br label %base2flt.exit102\n" + "bb10.i94: ; preds = %bb9.i97, %bb1.i73.bb10.i94_crit_edge\n" + " br i1 false, label %bb7.i95, label %bb10.i94.bb11.i87_crit_edge\n" + "bb10.i94.bb11.i87_crit_edge: ; preds = %bb10.i94\n" + " br label %bb11.i87\n" + "bb7.i95: ; preds = %bb10.i94\n" + " br i1 false, label %bb7.i95.base2flt.exit102_crit_edge, label %bb9.i97\n" + "bb7.i95.base2flt.exit102_crit_edge: ; preds = %bb7.i95\n" + " br label %base2flt.exit102\n" + "bb9.i97: ; preds = %bb7.i95\n" + " br label %bb10.i94\n" + "base2flt.exit102: ; preds = %bb7.i95.base2flt.exit102_crit_edge, %bb11.i87, %bb1.i13.base2flt.exit102_crit_edge\n" + " br i1 false, label %base2flt.exit102.mulflt.exit72_crit_edge, label %bb3.i62\n" + "base2flt.exit102.mulflt.exit72_crit_edge: ; preds = %bb5.i63, %base2flt.exit102\n" + " br label %mulflt.exit72\n" + "bb3.i62: ; preds = %base2flt.exit102\n" + " br i1 false, label %bb3.i62.mulflt.exit72_crit_edge, label %bb5.i63\n" + "bb3.i62.mulflt.exit72_crit_edge: ; preds = %bb8.i65, %bb3.i62\n" + " br label %mulflt.exit72\n" + "bb5.i63: ; preds = %bb3.i62\n" + " br i1 false, label %base2flt.exit102.mulflt.exit72_crit_edge, label %bb7.i64\n" + "bb7.i64: ; preds = %bb5.i63\n" + " br i1 false, label %bb8.i65, label %bb7.i64.bb12.i69_crit_edge\n" + "bb7.i64.bb12.i69_crit_edge: ; preds = %bb7.i64\n" + " br label %bb12.i69\n" + "bb8.i65: ; preds = %bb7.i64\n" + " br i1 false, label %bb3.i62.mulflt.exit72_crit_edge, label %bb10.i66\n" + "bb10.i66: ; preds = %bb8.i65\n" + " br label %bb12.i69\n" + "bb12.i69: ; preds = %bb10.i66, %bb7.i64.bb12.i69_crit_edge\n" + " br label %mulflt.exit72\n" + "mulflt.exit72: ; preds = %bb12.i69, %bb3.i62.mulflt.exit72_crit_edge, %base2flt.exit102.mulflt.exit72_crit_edge\n" + " br i1 false, label %mulflt.exit72.bb10.i58_crit_edge, label %bb3.i50\n" + "mulflt.exit72.bb10.i58_crit_edge: ; preds = %bb3.i50, %mulflt.exit72\n" + " br label %bb10.i58\n" + "bb3.i50: ; preds = %mulflt.exit72\n" + " br i1 false, label %mulflt.exit72.bb10.i58_crit_edge, label %bb5.i51\n" + "bb5.i51: ; preds = %bb3.i50\n" + " br i1 false, label %bb5.i51.bb9.i56_crit_edge, label %bb6.i52\n" + "bb5.i51.bb9.i56_crit_edge: ; preds = %bb5.i51\n" + " br label %bb9.i56\n" + "bb6.i52: ; preds = %bb5.i51\n" + " br i1 false, label %bb6.i52.bb10.i58_crit_edge, label %bb8.i53\n" + "bb6.i52.bb10.i58_crit_edge: ; preds = %bb6.i52\n" + " br label %bb10.i58\n" + "bb8.i53: ; preds = %bb6.i52\n" + " br label %bb9.i56\n" + "bb9.i56: ; preds = %bb8.i53, %bb5.i51.bb9.i56_crit_edge\n" + " br label %bb15.preheader\n" + "bb10.i58: ; preds = %bb6.i52.bb10.i58_crit_edge, %mulflt.exit72.bb10.i58_crit_edge\n" + " br label %bb15.preheader\n" + "bb15.preheader: ; preds = %bb10.i58, %bb9.i56\n" + " br label %bb15\n" + "bb15: ; preds = %addflt.exit, %bb15.preheader\n" + " br i1 false, label %bb15.bb18.loopexit_crit_edge, label %bb12\n" + "bb15.bb18.loopexit_crit_edge: ; preds = %bb15\n" + " br label %bb18.loopexit\n" + "bb12: ; preds = %bb15\n" + " br i1 false, label %bb12.bb18.loopexit_crit_edge, label %bb1.i21\n" + "bb12.bb18.loopexit_crit_edge: ; preds = %bb12\n" + " br label %bb18.loopexit\n" + "bb1.i21: ; preds = %bb12\n" + " br i1 false, label %bb1.i21.mulflt.exit47_crit_edge, label %bb3.i37\n" + "bb1.i21.mulflt.exit47_crit_edge: ; preds = %bb5.i38, %bb1.i21\n" + " br label %mulflt.exit47\n" + "bb3.i37: ; preds = %bb1.i21\n" + " br i1 false, label %bb3.i37.mulflt.exit47_crit_edge, label %bb5.i38\n" + "bb3.i37.mulflt.exit47_crit_edge: ; preds = %bb8.i40, %bb3.i37\n" + " br label %mulflt.exit47\n" + "bb5.i38: ; preds = %bb3.i37\n" + " br i1 false, label %bb1.i21.mulflt.exit47_crit_edge, label %bb7.i39\n" + "bb7.i39: ; preds = %bb5.i38\n" + " br i1 false, label %bb8.i40, label %bb7.i39.bb12.i44_crit_edge\n" + "bb7.i39.bb12.i44_crit_edge: ; preds = %bb7.i39\n" + " br label %bb12.i44\n" + "bb8.i40: ; preds = %bb7.i39\n" + " br i1 false, label %bb3.i37.mulflt.exit47_crit_edge, label %bb10.i41\n" + "bb10.i41: ; preds = %bb8.i40\n" + " br label %bb12.i44\n" + "bb12.i44: ; preds = %bb10.i41, %bb7.i39.bb12.i44_crit_edge\n" + " br label %mulflt.exit47\n" + "mulflt.exit47: ; preds = %bb12.i44, %bb3.i37.mulflt.exit47_crit_edge, %bb1.i21.mulflt.exit47_crit_edge\n" + " br i1 false, label %mulflt.exit47.base2flt.exit34_crit_edge, label %bb1.i15\n" + "mulflt.exit47.base2flt.exit34_crit_edge.loopexit: ; preds = %bb2.i20\n" + " br label %mulflt.exit47.base2flt.exit34_crit_edge\n" + "mulflt.exit47.base2flt.exit34_crit_edge: ; preds = %mulflt.exit47.base2flt.exit34_crit_edge.loopexit, %mulflt.exit47\n" + " br label %base2flt.exit34\n" + "bb1.i15: ; preds = %mulflt.exit47\n" + " br i1 false, label %bb1.i15.bb10.i31_crit_edge, label %bb1.i15.bb2.i20_crit_edge\n" + "bb1.i15.bb2.i20_crit_edge: ; preds = %bb1.i15\n" + " br label %bb2.i20\n" + "bb1.i15.bb10.i31_crit_edge: ; preds = %bb1.i15\n" + " br label %bb10.i31\n" + "bb2.i20: ; preds = %bb4.i22.bb2.i20_crit_edge, %bb1.i15.bb2.i20_crit_edge\n" + " br i1 false, label %bb4.i22, label %mulflt.exit47.base2flt.exit34_crit_edge.loopexit\n" + "bb4.i22: ; preds = %bb2.i20\n" + " br i1 false, label %bb4.i22.bb11.i28_crit_edge, label %bb4.i22.bb2.i20_crit_edge\n" + "bb4.i22.bb2.i20_crit_edge: ; preds = %bb4.i22\n" + " br label %bb2.i20\n" + "bb4.i22.bb11.i28_crit_edge: ; preds = %bb4.i22\n" + " br label %bb11.i28\n" + "bb11.i28: ; preds = %bb10.i31.bb11.i28_crit_edge, %bb4.i22.bb11.i28_crit_edge\n" + " br label %base2flt.exit34\n" + "bb10.i31: ; preds = %bb9.i33, %bb1.i15.bb10.i31_crit_edge\n" + " br i1 false, label %bb7.i32, label %bb10.i31.bb11.i28_crit_edge\n" + "bb10.i31.bb11.i28_crit_edge: ; preds = %bb10.i31\n" + " br label %bb11.i28\n" + "bb7.i32: ; preds = %bb10.i31\n" + " br i1 false, label %bb7.i32.base2flt.exit34_crit_edge, label %bb9.i33\n" + "bb7.i32.base2flt.exit34_crit_edge: ; preds = %bb7.i32\n" + " br label %base2flt.exit34\n" + "bb9.i33: ; preds = %bb7.i32\n" + " br label %bb10.i31\n" + "base2flt.exit34: ; preds = %bb7.i32.base2flt.exit34_crit_edge, %bb11.i28, %mulflt.exit47.base2flt.exit34_crit_edge\n" + " br i1 false, label %base2flt.exit34.mulflt.exit_crit_edge, label %bb3.i9\n" + "base2flt.exit34.mulflt.exit_crit_edge: ; preds = %bb5.i10, %base2flt.exit34\n" + " br label %mulflt.exit\n" + "bb3.i9: ; preds = %base2flt.exit34\n" + " br i1 false, label %bb3.i9.mulflt.exit_crit_edge, label %bb5.i10\n" + "bb3.i9.mulflt.exit_crit_edge: ; preds = %bb8.i11, %bb3.i9\n" + " br label %mulflt.exit\n" + "bb5.i10: ; preds = %bb3.i9\n" + " br i1 false, label %base2flt.exit34.mulflt.exit_crit_edge, label %bb7.i\n" + "bb7.i: ; preds = %bb5.i10\n" + " br i1 false, label %bb8.i11, label %bb7.i.bb12.i_crit_edge\n" + "bb7.i.bb12.i_crit_edge: ; preds = %bb7.i\n" + " br label %bb12.i\n" + "bb8.i11: ; preds = %bb7.i\n" + " br i1 false, label %bb3.i9.mulflt.exit_crit_edge, label %bb10.i12\n" + "bb10.i12: ; preds = %bb8.i11\n" + " br label %bb12.i\n" + "bb12.i: ; preds = %bb10.i12, %bb7.i.bb12.i_crit_edge\n" + " br label %mulflt.exit\n" + "mulflt.exit: ; preds = %bb12.i, %bb3.i9.mulflt.exit_crit_edge, %base2flt.exit34.mulflt.exit_crit_edge\n" + " br i1 false, label %mulflt.exit.addflt.exit_crit_edge, label %bb3.i\n" + "mulflt.exit.addflt.exit_crit_edge: ; preds = %bb3.i, %mulflt.exit\n" + " br label %addflt.exit\n" + "bb3.i: ; preds = %mulflt.exit\n" + " br i1 false, label %mulflt.exit.addflt.exit_crit_edge, label %bb5.i\n" + "bb5.i: ; preds = %bb3.i\n" + " br i1 false, label %bb5.i.bb9.i_crit_edge, label %bb6.i\n" + "bb5.i.bb9.i_crit_edge: ; preds = %bb5.i\n" + " br label %bb9.i\n" + "bb6.i: ; preds = %bb5.i\n" + " br i1 false, label %bb6.i.addflt.exit_crit_edge, label %bb8.i\n" + "bb6.i.addflt.exit_crit_edge: ; preds = %bb6.i\n" + " br label %addflt.exit\n" + "bb8.i: ; preds = %bb6.i\n" + " br label %bb9.i\n" + "bb9.i: ; preds = %bb8.i, %bb5.i.bb9.i_crit_edge\n" + " br label %addflt.exit\n" + "addflt.exit: ; preds = %bb9.i, %bb6.i.addflt.exit_crit_edge, %mulflt.exit.addflt.exit_crit_edge\n" + " br label %bb15\n" + "bb18.loopexit: ; preds = %bb12.bb18.loopexit_crit_edge, %bb15.bb18.loopexit_crit_edge\n" + " ret i32 0\n" + "}\n"); + runWithDomTree( + *M, "f", [&](Function &F, DominatorTree *DT) { + for (Function::iterator I = F.begin(), E = F.end(); I != E;) { + BasicBlock *BB = &*I++; + BasicBlock *SinglePred = BB->getSinglePredecessor(); + if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) continue; + BranchInst *Term = dyn_cast(SinglePred->getTerminator()); + if (Term && !Term->isConditional()) + MergeBasicBlockIntoOnlyPred(BB, DT); + } + EXPECT_TRUE(DT->verify()); + }); +}