brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.0 KiB · 00d9e9f Raw
748 lines · cpp
1//===- BasicBlockUtils.cpp - Unit tests for BasicBlockUtils ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Transforms/Utils/BasicBlockUtils.h"10#include "llvm/Analysis/AssumptionCache.h"11#include "llvm/Analysis/BasicAliasAnalysis.h"12#include "llvm/Analysis/BlockFrequencyInfo.h"13#include "llvm/Analysis/BranchProbabilityInfo.h"14#include "llvm/Analysis/CFG.h"15#include "llvm/Analysis/DomTreeUpdater.h"16#include "llvm/Analysis/LoopInfo.h"17#include "llvm/Analysis/MemorySSA.h"18#include "llvm/Analysis/MemorySSAUpdater.h"19#include "llvm/Analysis/PostDominators.h"20#include "llvm/Analysis/TargetLibraryInfo.h"21#include "llvm/AsmParser/Parser.h"22#include "llvm/IR/BasicBlock.h"23#include "llvm/IR/Dominators.h"24#include "llvm/IR/LLVMContext.h"25#include "llvm/IR/Module.h"26#include "llvm/Support/SourceMgr.h"27#include "gtest/gtest.h"28 29using namespace llvm;30 31static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {32  SMDiagnostic Err;33  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);34  if (!Mod)35    Err.print("BasicBlockUtilsTests", errs());36  return Mod;37}38 39static BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {40  for (BasicBlock &BB : F)41    if (BB.getName() == Name)42      return &BB;43  llvm_unreachable("Expected to find basic block!");44}45 46TEST(BasicBlockUtils, EliminateUnreachableBlocks) {47  LLVMContext C;48  std::unique_ptr<Module> M = parseIR(C, R"IR(49define i32 @has_unreachable(i1 %cond) {50entry:51  br i1 %cond, label %bb0, label %bb152bb0:53  br label %bb154bb1:55  %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]56  ret i32 %phi57bb2:58  ret i32 4259}60)IR");61  Function *F = M->getFunction("has_unreachable");62  DominatorTree DT(*F);63  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);64 65  EXPECT_EQ(F->size(), (size_t)4);66  bool Result = EliminateUnreachableBlocks(*F, &DTU);67  EXPECT_TRUE(Result);68  EXPECT_EQ(F->size(), (size_t)3);69  EXPECT_TRUE(DT.verify());70}71 72TEST(BasicBlockUtils, SplitEdge_ex1) {73  LLVMContext C;74  std::unique_ptr<Module> M = parseIR(C, R"IR(75define void @foo(i1 %cond0) {76entry:77  br i1 %cond0, label %bb0, label %bb178bb0:79 %0 = mul i32 1, 280  br label %bb181bb1:82  br label %bb283bb2:84  ret void85}86)IR");87  Function *F = M->getFunction("foo");88  DominatorTree DT(*F);89  BasicBlock *SrcBlock;90  BasicBlock *DestBlock;91  BasicBlock *NewBB;92 93  SrcBlock = getBasicBlockByName(*F, "entry");94  DestBlock = getBasicBlockByName(*F, "bb0");95  NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);96 97  EXPECT_TRUE(DT.verify());98  EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);99  EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);100  EXPECT_EQ(NewBB->getParent(), F);101 102  bool BBFlag = false;103  for (BasicBlock &BB : *F) {104    if (BB.getName() == NewBB->getName()) {105      BBFlag = true;106    }107  }108  EXPECT_TRUE(BBFlag);109}110 111TEST(BasicBlockUtils, SplitEdge_ex2) {112  LLVMContext C;113  std::unique_ptr<Module> M = parseIR(C, R"IR(114define void @foo() {115bb0:116  br label %bb2117bb1:118  br label %bb2119bb2:120  ret void121}122)IR");123  Function *F = M->getFunction("foo");124  DominatorTree DT(*F);125 126  BasicBlock *SrcBlock;127  BasicBlock *DestBlock;128  BasicBlock *NewBB;129 130  SrcBlock = getBasicBlockByName(*F, "bb0");131  DestBlock = getBasicBlockByName(*F, "bb2");132  NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);133 134  EXPECT_TRUE(DT.verify());135  EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);136  EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);137  EXPECT_EQ(NewBB->getParent(), F);138 139  bool BBFlag = false;140  for (BasicBlock &BB : *F) {141    if (BB.getName() == NewBB->getName()) {142      BBFlag = true;143    }144  }145  EXPECT_TRUE(BBFlag);146}147 148TEST(BasicBlockUtils, SplitEdge_ex3) {149  LLVMContext C;150  std::unique_ptr<Module> M = parseIR(C, R"IR(151define i32 @foo(i32 %n) {152entry:153 br label %header154header:155 %sum.02 = phi i32 [ 0, %entry ], [ %sum.1, %bb3 ]156 %0 = phi i32 [ 0, %entry ], [ %4, %bb3 ]157 %1 = icmp slt i32 %0, %n158 br i1 %1, label %bb0, label %bb1159bb0:160  %2 = add nsw i32 %sum.02, 2161  br label %bb2162bb1:163  %3 = add nsw i32 %sum.02, 1164  br label %bb2165bb2:166  %sum.1 = phi i32 [ %2, %bb0 ], [ %3, %bb1 ]167  br label %bb3168bb3:169  %4 = add nsw i32 %0, 1170  %5 = icmp slt i32 %4, 100171  br i1 %5, label %header, label %bb4172bb4:173 %sum.0.lcssa = phi i32 [ %sum.1, %bb3 ]174 ret i32 %sum.0.lcssa175}176)IR");177  Function *F = M->getFunction("foo");178  DominatorTree DT(*F);179 180  LoopInfo LI(DT);181 182  DataLayout DL("e-i64:64-f80:128-n8:16:32:64-S128");183  TargetLibraryInfoImpl TLII(M->getTargetTriple());184  TargetLibraryInfo TLI(TLII);185  AssumptionCache AC(*F);186  AAResults AA(TLI);187 188  BasicAAResult BAA(DL, *F, TLI, AC, &DT);189  AA.addAAResult(BAA);190 191  MemorySSA MSSA(*F, &AA, &DT);192  MemorySSAUpdater Updater(&MSSA);193 194  BasicBlock *SrcBlock;195  BasicBlock *DestBlock;196  BasicBlock *NewBB;197 198  SrcBlock = getBasicBlockByName(*F, "header");199  DestBlock = getBasicBlockByName(*F, "bb0");200  NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &Updater);201 202  Updater.getMemorySSA()->verifyMemorySSA();203  EXPECT_TRUE(DT.verify());204  EXPECT_NE(LI.getLoopFor(SrcBlock), nullptr);205  EXPECT_NE(LI.getLoopFor(DestBlock), nullptr);206  EXPECT_NE(LI.getLoopFor(NewBB), nullptr);207  EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);208  EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);209  EXPECT_EQ(NewBB->getParent(), F);210 211  bool BBFlag = false;212  for (BasicBlock &BB : *F) {213    if (BB.getName() == NewBB->getName()) {214      BBFlag = true;215    }216  }217  EXPECT_TRUE(BBFlag);218}219 220TEST(BasicBlockUtils, SplitEdge_ex4) {221  LLVMContext C;222  std::unique_ptr<Module> M = parseIR(C, R"IR(223define void @bar(i32 %cond) personality i8 0 {224entry:225  switch i32 %cond, label %exit [226    i32 -1, label %continue227    i32 0, label %continue228    i32 1, label %continue_alt229    i32 2, label %continue_alt230  ]231exit:232  ret void233continue:234  invoke void @sink() to label %normal unwind label %exception235continue_alt:236  invoke void @sink_alt() to label %normal unwind label %exception237exception:238  %cleanup = landingpad i8 cleanup239  br label %trivial-eh-handler240trivial-eh-handler:241  call void @sideeffect(i32 1)242  br label %normal243normal:244  call void @sideeffect(i32 0)245  ret void246}247 248declare void @sideeffect(i32)249declare void @sink() cold250declare void @sink_alt() cold251)IR");252  Function *F = M->getFunction("bar");253 254  DominatorTree DT(*F);255 256  LoopInfo LI(DT);257 258  TargetLibraryInfoImpl TLII(M->getTargetTriple());259  TargetLibraryInfo TLI(TLII);260 261  AAResults AA(TLI);262 263  MemorySSA MSSA(*F, &AA, &DT);264  MemorySSAUpdater MSSAU(&MSSA);265 266  BasicBlock *SrcBlock;267  BasicBlock *DestBlock;268 269  SrcBlock = getBasicBlockByName(*F, "continue");270  DestBlock = getBasicBlockByName(*F, "exception");271 272  unsigned SuccNum = GetSuccessorNumber(SrcBlock, DestBlock);273  Instruction *LatchTerm = SrcBlock->getTerminator();274 275  const CriticalEdgeSplittingOptions Options =276      CriticalEdgeSplittingOptions(&DT, &LI, &MSSAU);277 278  // Check that the following edge is both critical and the destination block is279  // an exception block. These must be handled differently by SplitEdge280  bool CriticalEdge =281      isCriticalEdge(LatchTerm, SuccNum, Options.MergeIdenticalEdges);282  EXPECT_TRUE(CriticalEdge);283 284  bool Ehpad = DestBlock->isEHPad();285  EXPECT_TRUE(Ehpad);286 287  BasicBlock *NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &MSSAU, "");288  // SplitEdge cannot split an eh pad edge.289  EXPECT_EQ(NewBB, nullptr);290}291 292TEST(BasicBlockUtils, splitBasicBlockBefore_ex1) {293  LLVMContext C;294  std::unique_ptr<Module> M = parseIR(C, R"IR(295define void @foo() {296bb0:297 %0 = mul i32 1, 2298  br label %bb2299bb1:300  br label %bb3301bb2:302  %1 = phi  i32 [ %0, %bb0 ]303  br label %bb3304bb3:305  ret void306}307)IR");308  Function *F = M->getFunction("foo");309  DominatorTree DT(*F);310 311  BasicBlock *DestBlock;312  BasicBlock *NewBB;313 314  DestBlock = getBasicBlockByName(*F, "bb2");315 316  NewBB = DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),317                                           "test");318 319  PHINode *PN = dyn_cast<PHINode>(&(DestBlock->front()));320  EXPECT_EQ(PN->getIncomingBlock(0), NewBB);321  EXPECT_EQ(NewBB->getName(), "test");322  EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);323  EXPECT_EQ(DestBlock->getSinglePredecessor(), NewBB);324}325 326#ifndef NDEBUG327TEST(BasicBlockUtils, splitBasicBlockBefore_ex2) {328  LLVMContext C;329  std::unique_ptr<Module> M = parseIR(C, R"IR(330define void @foo() {331bb0:332 %0 = mul i32 1, 2333  br label %bb2334bb1:335  br label %bb2336bb2:337  %1 = phi  i32 [ %0, %bb0 ], [ 1, %bb1 ]338  br label %bb3339bb3:340  ret void341}342)IR");343  Function *F = M->getFunction("foo");344  DominatorTree DT(*F);345 346  BasicBlock *DestBlock = getBasicBlockByName(*F, "bb2");347 348  ASSERT_DEATH(349      {350        DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),351                                         "test");352      },353      "cannot split on multi incoming phis");354}355#endif356 357TEST(BasicBlockUtils, NoUnreachableBlocksToEliminate) {358  LLVMContext C;359  std::unique_ptr<Module> M = parseIR(C, R"IR(360define i32 @no_unreachable(i1 %cond) {361entry:362  br i1 %cond, label %bb0, label %bb1363bb0:364  br label %bb1365bb1:366  %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]367  ret i32 %phi368}369)IR");370  Function *F = M->getFunction("no_unreachable");371  DominatorTree DT(*F);372  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);373 374  EXPECT_EQ(F->size(), (size_t)3);375  bool Result = EliminateUnreachableBlocks(*F, &DTU);376  EXPECT_FALSE(Result);377  EXPECT_EQ(F->size(), (size_t)3);378  EXPECT_TRUE(DT.verify());379}380 381TEST(BasicBlockUtils, SplitBlockPredecessors) {382  LLVMContext C;383  std::unique_ptr<Module> M = parseIR(C, R"IR(384define i32 @basic_func(i1 %cond) {385entry:386  br i1 %cond, label %bb0, label %bb1387bb0:388  br label %bb1389bb1:390  %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]391  ret i32 %phi392}393)IR");394  Function *F = M->getFunction("basic_func");395  DominatorTree DT(*F);396 397  // Make sure the dominator tree is properly updated if calling this on the398  // entry block.399  SplitBlockPredecessors(&F->getEntryBlock(), {}, "split.entry", &DT);400  EXPECT_TRUE(DT.verify());401}402 403TEST(BasicBlockUtils, SplitCriticalEdge) {404  LLVMContext C;405  std::unique_ptr<Module> M = parseIR(C, R"IR(406define void @crit_edge(i1 %cond0, i1 %cond1) {407entry:408  br i1 %cond0, label %bb0, label %bb1409bb0:410  br label %bb1411bb1:412  br label %bb2413bb2:414  ret void415}416)IR");417  Function *F = M->getFunction("crit_edge");418  DominatorTree DT(*F);419  PostDominatorTree PDT(*F);420 421  CriticalEdgeSplittingOptions CESO(&DT, nullptr, nullptr, &PDT);422  EXPECT_EQ(1u, SplitAllCriticalEdges(*F, CESO));423  EXPECT_TRUE(DT.verify());424  EXPECT_TRUE(PDT.verify());425}426 427TEST(BasicBlockUtils, SplitLoopCriticalEdge) {428  LLVMContext C;429  std::unique_ptr<Module> M = parseIR(C, R"IR(430declare i1 @predicate(ptr %p)431 432define ptr @Parse(ptr %gp) {433entry:434  br label %for.inc435 436for.inc:437  %phi = phi ptr [ %gp, %entry ], [ %cp, %while.cond ], [ %cp, %while.cond ]438  %cond = call i1 @predicate(ptr %phi)439  %inc= getelementptr inbounds i8, ptr %phi, i64 1440  br i1 %cond, label %while.cond, label %exit441 442while.cond:443  %cp = phi ptr [ %inc, %for.inc ], [ %incdec, %while.body ]444  %val = load i8, ptr %cp, align 1445  switch i8 %val, label %while.body [446    i8 10, label %for.inc447    i8 0, label %for.inc448  ]449 450while.body:451  %incdec = getelementptr inbounds i8, ptr %cp, i64 1452  br label %while.cond453 454exit:455  ret ptr %phi456}457)IR");458  Function *F = M->getFunction("Parse");459  DominatorTree DT(*F);460  LoopInfo LI(DT);461 462  CriticalEdgeSplittingOptions CESO =463      CriticalEdgeSplittingOptions(nullptr, &LI, nullptr)464          .setMergeIdenticalEdges()465          .setPreserveLCSSA();466  EXPECT_EQ(2u, SplitAllCriticalEdges(*F, CESO));467 468  BasicBlock *WhileBB = getBasicBlockByName(*F, "while.cond");469  BasicBlock *SplitBB = WhileBB->getTerminator()->getSuccessor(1);470  // The only 1 successor of SplitBB is %for.inc471  EXPECT_EQ(1u, SplitBB->getTerminator()->getNumSuccessors());472  // MergeIdenticalEdges: SplitBB has two identical predecessors, %while.cond.473  EXPECT_EQ(WhileBB, SplitBB->getUniquePredecessor());474  EXPECT_TRUE(SplitBB->hasNPredecessors(2));475 476  auto *PN = dyn_cast<PHINode>(&SplitBB->front());477  // PreserveLCSSA: should insert a PHI node in front of SplitBB478  EXPECT_NE(nullptr, PN);479  // The PHI node should have 2 identical incoming blocks.480  EXPECT_EQ(2u, PN->getNumIncomingValues());481  EXPECT_EQ(PN->getIncomingBlock(0), PN->getIncomingBlock(1));482}483 484TEST(BasicBlockUtils, SplitIndirectBrCriticalEdgesIgnorePHIs) {485  LLVMContext C;486  std::unique_ptr<Module> M = parseIR(C, R"IR(487define void @crit_edge(ptr %tgt, i1 %cond0, i1 %cond1) {488entry:489  indirectbr ptr %tgt, [label %bb0, label %bb1, label %bb2]490bb0:491  br i1 %cond0, label %bb1, label %bb2492bb1:493  %p = phi i32 [0, %bb0], [0, %entry]494  br i1 %cond1, label %bb3, label %bb4495bb2:496  ret void497bb3:498  ret void499bb4:500  ret void501}502)IR");503  Function *F = M->getFunction("crit_edge");504  DominatorTree DT(*F);505  LoopInfo LI(DT);506  BranchProbabilityInfo BPI(*F, LI);507  BlockFrequencyInfo BFI(*F, BPI, LI);508 509  ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/true,510                                           &BPI, &BFI));511 512  // Check that successors of the split block get their probability correct.513  BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");514  BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);515  ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());516  EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));517  EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));518 519  // bb2 has no PHI, so we shouldn't split bb0 -> bb2520  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");521  ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());522  EXPECT_EQ(BB0->getTerminator()->getSuccessor(1),523            getBasicBlockByName(*F, "bb2"));524}525 526TEST(BasicBlockUtils, SplitIndirectBrCriticalEdges) {527  LLVMContext C;528  std::unique_ptr<Module> M = parseIR(C, R"IR(529define void @crit_edge(ptr %tgt, i1 %cond0, i1 %cond1) {530entry:531  indirectbr ptr %tgt, [label %bb0, label %bb1, label %bb2]532bb0:533  br i1 %cond0, label %bb1, label %bb2534bb1:535  %p = phi i32 [0, %bb0], [0, %entry]536  br i1 %cond1, label %bb3, label %bb4537bb2:538  ret void539bb3:540  ret void541bb4:542  ret void543}544)IR");545  Function *F = M->getFunction("crit_edge");546  DominatorTree DT(*F);547  LoopInfo LI(DT);548  BranchProbabilityInfo BPI(*F, LI);549  BlockFrequencyInfo BFI(*F, BPI, LI);550 551  ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/false,552                                           &BPI, &BFI));553 554  // Check that successors of the split block get their probability correct.555  BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");556  BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);557  ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());558  EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));559  EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));560 561  // Should split, resulting in:562  //   bb0 -> bb2.clone; bb2 -> split1; bb2.clone -> split,563  BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");564  ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());565  BasicBlock *BB2Clone = BB0->getTerminator()->getSuccessor(1);566  BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");567  EXPECT_NE(BB2Clone, BB2);568  ASSERT_EQ(1u, BB2->getTerminator()->getNumSuccessors());569  ASSERT_EQ(1u, BB2Clone->getTerminator()->getNumSuccessors());570  EXPECT_EQ(BB2->getTerminator()->getSuccessor(0),571            BB2Clone->getTerminator()->getSuccessor(0));572}573 574TEST(BasicBlockUtils, SetEdgeProbability) {575  LLVMContext C;576  std::unique_ptr<Module> M = parseIR(C, R"IR(577define void @edge_probability(i32 %0) {578entry:579switch i32 %0, label %LD [580  i32 700, label %L0581  i32 701, label %L1582  i32 702, label %L2583  i32 703, label %L3584  i32 704, label %L4585  i32 705, label %L5586  i32 706, label %L6587  i32 707, label %L7588  i32 708, label %L8589  i32 709, label %L9590  i32 710, label %L10591  i32 711, label %L11592  i32 712, label %L12593  i32 713, label %L13594  i32 714, label %L14595  i32 715, label %L15596  i32 716, label %L16597  i32 717, label %L17598  i32 718, label %L18599  i32 719, label %L19600], !prof !{!"branch_weights", i32 1, i32 1, i32 1, i32 1, i32 1, i32 451, i32 1,601           i32 12, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1,602           i32 1, i32 1, i32 1, i32 1, i32 1}603LD:604  unreachable605L0:606  ret void607L1:608  ret void609L2:610  ret void611L3:612  ret void613L4:614  ret void615L5:616  ret void617L6:618  ret void619L7:620  ret void621L8:622  ret void623L9:624  ret void625L10:626  ret void627L11:628  ret void629L12:630  ret void631L13:632  ret void633L14:634  ret void635L15:636  ret void637L16:638  ret void639L17:640  ret void641L18:642  ret void643L19:644  ret void645}646)IR");647  Function *F = M->getFunction("edge_probability");648  DominatorTree DT(*F);649  LoopInfo LI(DT);650  BranchProbabilityInfo BPI(*F, LI);651 652  // Check that the unreachable block has the minimal probability.653  const BasicBlock *EntryBB = getBasicBlockByName(*F, "entry");654  const BasicBlock *UnreachableBB = getBasicBlockByName(*F, "LD");655  EXPECT_EQ(BranchProbability::getRaw(1),656            BPI.getEdgeProbability(EntryBB, UnreachableBB));657}658 659TEST(BasicBlockUtils, IsPresplitCoroSuspendExitTest) {660  LLVMContext C;661  std::unique_ptr<Module> M = parseIR(C, R"IR(662define void @positive_case(i32 %0) #0 {663entry:664  %save = call token @llvm.coro.save(ptr null)665  %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)666  switch i8 %suspend, label %exit [667    i8 0, label %resume668    i8 1, label %destroy669  ]670resume:671  ret void672destroy:673  ret void674exit:675  call void @llvm.coro.end(ptr null, i1 false, token none)676  ret void677}678 679define void @notpresplit(i32 %0) {680entry:681  %save = call token @llvm.coro.save(ptr null)682  %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)683  switch i8 %suspend, label %exit [684    i8 0, label %resume685    i8 1, label %destroy686  ]687resume:688  ret void689destroy:690  ret void691exit:692  call void @llvm.coro.end(ptr null, i1 false, token none)693  ret void694}695 696declare token @llvm.coro.save(ptr)697declare i8 @llvm.coro.suspend(token, i1)698declare void @llvm.coro.end(ptr, i1, token)699 700attributes #0 = { presplitcoroutine }701)IR");702 703  auto FindExit = [](const Function &F) -> const BasicBlock * {704    for (const auto &BB : F)705      if (BB.getName() == "exit")706        return &BB;707    return nullptr;708  };709  Function *P = M->getFunction("positive_case");710  const auto &ExitP = *FindExit(*P);711  EXPECT_TRUE(llvm::isPresplitCoroSuspendExitEdge(*ExitP.getSinglePredecessor(),712                                                  ExitP));713 714  Function *N = M->getFunction("notpresplit");715  const auto &ExitN = *FindExit(*N);716  EXPECT_FALSE(llvm::isPresplitCoroSuspendExitEdge(717      *ExitN.getSinglePredecessor(), ExitN));718}719 720TEST(BasicBlockUtils, BasicBlockPrintable) {721  std::string S;722  std::string SCheck;723  llvm::raw_string_ostream OS{S};724  llvm::raw_string_ostream OSCheck{SCheck};725 726  LLVMContext C;727  std::unique_ptr<Module> M = parseIR(C, R"IR(728define void @foo() {729  br label %bb0730bb0:731  br label %.exit732.exit:733  ret void734}735)IR");736 737  Function *F = M->getFunction("foo");738  for (const BasicBlock &BB : *F) {739    OS << printBasicBlock(&BB);740    BB.printAsOperand(OSCheck);741    EXPECT_EQ(OS.str(), OSCheck.str());742    S.clear();743    SCheck.clear();744  }745  OS << printBasicBlock(nullptr);746  EXPECT_EQ(OS.str(), "<nullptr>");747}748