brintos

brintos / llvm-project-archived public Read only

0
0
Text · 44.7 KiB · 896e1de Raw
1305 lines · cpp
1//===- Local.cpp - Unit tests for Local -----------------------------------===//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/Local.h"10#include "llvm/ADT/ScopeExit.h"11#include "llvm/Analysis/DomTreeUpdater.h"12#include "llvm/Analysis/InstructionSimplify.h"13#include "llvm/Analysis/PostDominators.h"14#include "llvm/Analysis/TargetTransformInfo.h"15#include "llvm/AsmParser/Parser.h"16#include "llvm/IR/BasicBlock.h"17#include "llvm/IR/DIBuilder.h"18#include "llvm/IR/DebugInfo.h"19#include "llvm/IR/DebugProgramInstruction.h"20#include "llvm/IR/IRBuilder.h"21#include "llvm/IR/Instructions.h"22#include "llvm/IR/IntrinsicInst.h"23#include "llvm/IR/LLVMContext.h"24#include "llvm/IR/Module.h"25#include "llvm/IR/Verifier.h"26#include "llvm/Support/SourceMgr.h"27#include "gtest/gtest.h"28 29using namespace llvm;30 31TEST(Local, RecursivelyDeleteDeadPHINodes) {32  LLVMContext C;33 34  IRBuilder<> builder(C);35 36  // Make blocks37  BasicBlock *bb0 = BasicBlock::Create(C);38  BasicBlock *bb1 = BasicBlock::Create(C);39 40  builder.SetInsertPoint(bb0);41  PHINode    *phi = builder.CreatePHI(Type::getInt32Ty(C), 2);42  BranchInst *br0 = builder.CreateCondBr(builder.getTrue(), bb0, bb1);43 44  builder.SetInsertPoint(bb1);45  BranchInst *br1 = builder.CreateBr(bb0);46 47  phi->addIncoming(phi, bb0);48  phi->addIncoming(phi, bb1);49 50  // The PHI will be removed51  EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));52 53  // Make sure the blocks only contain the branches54  EXPECT_EQ(&bb0->front(), br0);55  EXPECT_EQ(&bb1->front(), br1);56 57  builder.SetInsertPoint(bb0);58  phi = builder.CreatePHI(Type::getInt32Ty(C), 0);59 60  EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));61 62  builder.SetInsertPoint(bb0);63  phi = builder.CreatePHI(Type::getInt32Ty(C), 0);64  builder.CreateAdd(phi, phi);65 66  EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));67 68  bb0->dropAllReferences();69  bb1->dropAllReferences();70  delete bb0;71  delete bb1;72}73 74TEST(Local, RemoveDuplicatePHINodes) {75  LLVMContext C;76  IRBuilder<> B(C);77 78  std::unique_ptr<Function> F(79      Function::Create(FunctionType::get(B.getVoidTy(), false),80                       GlobalValue::ExternalLinkage, "F"));81  BasicBlock *Entry(BasicBlock::Create(C, "", F.get()));82  BasicBlock *BB(BasicBlock::Create(C, "", F.get()));83  BranchInst::Create(BB, Entry);84 85  B.SetInsertPoint(BB);86 87  AssertingVH<PHINode> P1 = B.CreatePHI(Type::getInt32Ty(C), 2);88  P1->addIncoming(B.getInt32(42), Entry);89 90  PHINode *P2 = B.CreatePHI(Type::getInt32Ty(C), 2);91  P2->addIncoming(B.getInt32(42), Entry);92 93  AssertingVH<PHINode> P3 = B.CreatePHI(Type::getInt32Ty(C), 2);94  P3->addIncoming(B.getInt32(42), Entry);95  P3->addIncoming(B.getInt32(23), BB);96 97  PHINode *P4 = B.CreatePHI(Type::getInt32Ty(C), 2);98  P4->addIncoming(B.getInt32(42), Entry);99  P4->addIncoming(B.getInt32(23), BB);100 101  P1->addIncoming(P3, BB);102  P2->addIncoming(P4, BB);103  BranchInst::Create(BB, BB);104 105  // Verify that we can eliminate PHIs that become duplicates after chaning PHIs106  // downstream.107  EXPECT_TRUE(EliminateDuplicatePHINodes(BB));108  EXPECT_EQ(3U, BB->size());109}110 111static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {112  SMDiagnostic Err;113  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);114  if (!Mod)115    Err.print("UtilsTests", errs());116  return Mod;117}118 119TEST(Local, ReplaceDbgDeclare) {120  LLVMContext C;121  // Original C source to get debug info for a local variable:122  // void f() { int x; }123  std::unique_ptr<Module> M = parseIR(C,124                                      R"(125      define void @f() !dbg !8 {126      entry:127        %x = alloca i32, align 4128          #dbg_declare(ptr %x, !11, !DIExpression(), !13)129          #dbg_declare(ptr %x, !11, !DIExpression(), !13)130        ret void, !dbg !14131      }132 133      !llvm.dbg.cu = !{!0}134      !llvm.module.flags = !{!3, !4}135      !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)136      !1 = !DIFile(filename: "t2.c", directory: "foo")137      !2 = !{}138      !3 = !{i32 2, !"Dwarf Version", i32 4}139      !4 = !{i32 2, !"Debug Info Version", i32 3}140      !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2)141      !9 = !DISubroutineType(types: !10)142      !10 = !{null}143      !11 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !12)144      !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)145      !13 = !DILocation(line: 2, column: 7, scope: !8)146      !14 = !DILocation(line: 3, column: 1, scope: !8)147      )");148  auto *GV = M->getNamedValue("f");149  ASSERT_TRUE(GV);150  auto *F = dyn_cast<Function>(GV);151  ASSERT_TRUE(F);152  Instruction *Inst = &F->front().front();153  auto *AI = dyn_cast<AllocaInst>(Inst);154  ASSERT_TRUE(AI);155 156  Value *NewBase = Constant::getNullValue(PointerType::getUnqual(C));157  DIBuilder DIB(*M);158  replaceDbgDeclare(AI, NewBase, DIB, DIExpression::ApplyOffset, 0);159 160  // There should be exactly two dbg.declares, attached to the terminator.161  Inst = F->front().getTerminator();162  ASSERT_TRUE(Inst);163  EXPECT_TRUE(Inst->hasDbgRecords());164  EXPECT_EQ(range_size(Inst->getDbgRecordRange()), 2u);165  for (DbgVariableRecord &DVR : filterDbgVars(Inst->getDbgRecordRange()))166    EXPECT_EQ(DVR.getAddress(), NewBase);167}168 169/// Build the dominator tree for the function and run the Test.170static void runWithDomTree(171    Module &M, StringRef FuncName,172    function_ref<void(Function &F, DominatorTree *DT)> Test) {173  auto *F = M.getFunction(FuncName);174  ASSERT_NE(F, nullptr) << "Could not find " << FuncName;175  // Compute the dominator tree for the function.176  DominatorTree DT(*F);177  Test(*F, &DT);178}179 180TEST(Local, MergeBasicBlockIntoOnlyPred) {181  LLVMContext C;182  std::unique_ptr<Module> M;183  auto resetIR = [&]() {184    M = parseIR(C,185                R"(186      define i32 @f(ptr %str) {187      entry:188        br label %bb2.i189      bb2.i:                                            ; preds = %bb4.i, %entry190        br i1 false, label %bb4.i, label %base2flt.exit204191      bb4.i:                                            ; preds = %bb2.i192        br i1 false, label %base2flt.exit204, label %bb2.i193      bb10.i196.bb7.i197_crit_edge:                     ; No predecessors!194        br label %bb7.i197195      bb7.i197:                                         ; preds = %bb10.i196.bb7.i197_crit_edge196        %.reg2mem.0 = phi i32 [ %.reg2mem.0, %bb10.i196.bb7.i197_crit_edge ]197        br i1 undef, label %base2flt.exit204, label %base2flt.exit204198      base2flt.exit204:                                 ; preds = %bb7.i197, %bb7.i197, %bb2.i, %bb4.i199        ret i32 0200      }201      )");202  };203 204  auto resetIRReplaceEntry = [&]() {205    M = parseIR(C,206                R"(207      define i32 @f() {208      entry:209        br label %bb2.i210      bb2.i:                                            ; preds = %entry211        ret i32 0212      }213      )");214  };215 216  auto Test = [&](Function &F, DomTreeUpdater &DTU) {217    for (Function::iterator I = F.begin(), E = F.end(); I != E;) {218      BasicBlock *BB = &*I++;219      BasicBlock *SinglePred = BB->getSinglePredecessor();220      if (!SinglePred || SinglePred == BB || BB->hasAddressTaken())221        continue;222      BranchInst *Term = dyn_cast<BranchInst>(SinglePred->getTerminator());223      if (Term && !Term->isConditional())224        MergeBasicBlockIntoOnlyPred(BB, &DTU);225    }226    if (DTU.hasDomTree()) {227      EXPECT_TRUE(DTU.getDomTree().verify());228    }229    if (DTU.hasPostDomTree()) {230      EXPECT_TRUE(DTU.getPostDomTree().verify());231    }232  };233 234  // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with235  // both DT and PDT.236  resetIR();237  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {238    PostDominatorTree PDT = PostDominatorTree(F);239    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);240    Test(F, DTU);241  });242 243  // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with244  // DT.245  resetIR();246  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {247    DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Eager);248    Test(F, DTU);249  });250 251  // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with252  // PDT.253  resetIR();254  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {255    PostDominatorTree PDT = PostDominatorTree(F);256    DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Eager);257    Test(F, DTU);258  });259 260  // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with261  // both DT and PDT.262  resetIR();263  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {264    PostDominatorTree PDT = PostDominatorTree(F);265    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);266    Test(F, DTU);267  });268 269  // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with270  // PDT.271  resetIR();272  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {273    PostDominatorTree PDT = PostDominatorTree(F);274    DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Lazy);275    Test(F, DTU);276  });277 278  // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with DT.279  resetIR();280  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {281    DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Lazy);282    Test(F, DTU);283  });284 285  // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with286  // both DT and PDT.287  resetIRReplaceEntry();288  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {289    PostDominatorTree PDT = PostDominatorTree(F);290    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);291    Test(F, DTU);292  });293 294  // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with295  // DT.296  resetIRReplaceEntry();297  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {298    DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Eager);299    Test(F, DTU);300  });301 302  // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with303  // PDT.304  resetIRReplaceEntry();305  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {306    PostDominatorTree PDT = PostDominatorTree(F);307    DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Eager);308    Test(F, DTU);309  });310 311  // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with312  // both DT and PDT.313  resetIRReplaceEntry();314  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {315    PostDominatorTree PDT = PostDominatorTree(F);316    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);317    Test(F, DTU);318  });319 320  // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with321  // PDT.322  resetIRReplaceEntry();323  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {324    PostDominatorTree PDT = PostDominatorTree(F);325    DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Lazy);326    Test(F, DTU);327  });328 329  // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with DT.330  resetIRReplaceEntry();331  runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) {332    DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Lazy);333    Test(F, DTU);334  });335}336 337TEST(Local, ConstantFoldTerminator) {338  LLVMContext C;339 340  std::unique_ptr<Module> M = parseIR(C,341                                      R"(342      define void @br_same_dest() {343      entry:344        br i1 false, label %bb0, label %bb0345      bb0:346        ret void347      }348 349      define void @br_different_dest() {350      entry:351        br i1 true, label %bb0, label %bb1352      bb0:353        br label %exit354      bb1:355        br label %exit356      exit:357        ret void358      }359 360      define void @switch_2_different_dest() {361      entry:362        switch i32 0, label %default [ i32 0, label %bb0 ]363      default:364        ret void365      bb0:366        ret void367      }368      define void @switch_2_different_dest_default() {369      entry:370        switch i32 1, label %default [ i32 0, label %bb0 ]371      default:372        ret void373      bb0:374        ret void375      }376      define void @switch_3_different_dest() {377      entry:378        switch i32 0, label %default [ i32 0, label %bb0379                                       i32 1, label %bb1 ]380      default:381        ret void382      bb0:383        ret void384      bb1:385        ret void386      }387 388      define void @switch_variable_2_default_dest(i32 %arg) {389      entry:390        switch i32 %arg, label %default [ i32 0, label %default ]391      default:392        ret void393      }394 395      define void @switch_constant_2_default_dest() {396      entry:397        switch i32 1, label %default [ i32 0, label %default ]398      default:399        ret void400      }401 402      define void @switch_constant_3_repeated_dest() {403      entry:404        switch i32 0, label %default [ i32 0, label %bb0405                                       i32 1, label %bb0 ]406       bb0:407         ret void408      default:409        ret void410      }411 412      define void @indirectbr() {413      entry:414        indirectbr ptr blockaddress(@indirectbr, %bb0), [label %bb0, label %bb1]415      bb0:416        ret void417      bb1:418        ret void419      }420 421      define void @indirectbr_repeated() {422      entry:423        indirectbr ptr blockaddress(@indirectbr_repeated, %bb0), [label %bb0, label %bb0]424      bb0:425        ret void426      }427 428      define void @indirectbr_unreachable() {429      entry:430        indirectbr ptr blockaddress(@indirectbr_unreachable, %bb0), [label %bb1]431      bb0:432        ret void433      bb1:434        ret void435      }436        )");437 438  auto CFAllTerminatorsEager = [&](Function &F, DominatorTree *DT) {439    PostDominatorTree PDT = PostDominatorTree(F);440    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);441    for (Function::iterator I = F.begin(), E = F.end(); I != E;) {442      BasicBlock *BB = &*I++;443      ConstantFoldTerminator(BB, true, nullptr, &DTU);444    }445 446    EXPECT_TRUE(DTU.getDomTree().verify());447    EXPECT_TRUE(DTU.getPostDomTree().verify());448  };449 450  auto CFAllTerminatorsLazy = [&](Function &F, DominatorTree *DT) {451    PostDominatorTree PDT = PostDominatorTree(F);452    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);453    for (Function::iterator I = F.begin(), E = F.end(); I != E;) {454      BasicBlock *BB = &*I++;455      ConstantFoldTerminator(BB, true, nullptr, &DTU);456    }457 458    EXPECT_TRUE(DTU.getDomTree().verify());459    EXPECT_TRUE(DTU.getPostDomTree().verify());460  };461 462  // Test ConstantFoldTerminator under Eager UpdateStrategy.463  runWithDomTree(*M, "br_same_dest", CFAllTerminatorsEager);464  runWithDomTree(*M, "br_different_dest", CFAllTerminatorsEager);465  runWithDomTree(*M, "switch_2_different_dest", CFAllTerminatorsEager);466  runWithDomTree(*M, "switch_2_different_dest_default", CFAllTerminatorsEager);467  runWithDomTree(*M, "switch_3_different_dest", CFAllTerminatorsEager);468  runWithDomTree(*M, "switch_variable_2_default_dest", CFAllTerminatorsEager);469  runWithDomTree(*M, "switch_constant_2_default_dest", CFAllTerminatorsEager);470  runWithDomTree(*M, "switch_constant_3_repeated_dest", CFAllTerminatorsEager);471  runWithDomTree(*M, "indirectbr", CFAllTerminatorsEager);472  runWithDomTree(*M, "indirectbr_repeated", CFAllTerminatorsEager);473  runWithDomTree(*M, "indirectbr_unreachable", CFAllTerminatorsEager);474 475  // Test ConstantFoldTerminator under Lazy UpdateStrategy.476  runWithDomTree(*M, "br_same_dest", CFAllTerminatorsLazy);477  runWithDomTree(*M, "br_different_dest", CFAllTerminatorsLazy);478  runWithDomTree(*M, "switch_2_different_dest", CFAllTerminatorsLazy);479  runWithDomTree(*M, "switch_2_different_dest_default", CFAllTerminatorsLazy);480  runWithDomTree(*M, "switch_3_different_dest", CFAllTerminatorsLazy);481  runWithDomTree(*M, "switch_variable_2_default_dest", CFAllTerminatorsLazy);482  runWithDomTree(*M, "switch_constant_2_default_dest", CFAllTerminatorsLazy);483  runWithDomTree(*M, "switch_constant_3_repeated_dest", CFAllTerminatorsLazy);484  runWithDomTree(*M, "indirectbr", CFAllTerminatorsLazy);485  runWithDomTree(*M, "indirectbr_repeated", CFAllTerminatorsLazy);486  runWithDomTree(*M, "indirectbr_unreachable", CFAllTerminatorsLazy);487}488 489struct SalvageDebugInfoTest : ::testing::Test {490  LLVMContext C;491  std::unique_ptr<Module> M;492  Function *F = nullptr;493 494  void SetUp() override {495    M = parseIR(C,496                R"(497      define void @f() !dbg !8 {498      entry:499        %x = add i32 0, 1500        %y = add i32 %x, 2501          #dbg_value(i32 %x, !11, !DIExpression(), !13)502          #dbg_value(i32 %y, !11, !DIExpression(), !13)503        ret void, !dbg !14504      }505      !llvm.dbg.cu = !{!0}506      !llvm.module.flags = !{!3, !4}507      !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)508      !1 = !DIFile(filename: "t2.c", directory: "foo")509      !2 = !{}510      !3 = !{i32 2, !"Dwarf Version", i32 4}511      !4 = !{i32 2, !"Debug Info Version", i32 3}512      !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2)513      !9 = !DISubroutineType(types: !10)514      !10 = !{null}515      !11 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !12)516      !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)517      !13 = !DILocation(line: 2, column: 7, scope: !8)518      !14 = !DILocation(line: 3, column: 1, scope: !8)519      )");520 521    auto *GV = M->getNamedValue("f");522    ASSERT_TRUE(GV);523    F = dyn_cast<Function>(GV);524    ASSERT_TRUE(F);525  }526 527  bool doesDebugValueDescribeX(const DbgVariableRecord &DVR) {528    if (DVR.getNumVariableLocationOps() != 1u)529      return false;530    const auto &CI = *cast<ConstantInt>(DVR.getValue(0));531    if (CI.isZero())532      return DVR.getExpression()->getElements().equals(533          {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_stack_value});534    else if (CI.isOneValue())535      return DVR.getExpression()->getElements().empty();536    return false;537  }538 539  bool doesDebugValueDescribeY(const DbgVariableRecord &DVR) {540    if (DVR.getNumVariableLocationOps() != 1u)541      return false;542    const auto &CI = *cast<ConstantInt>(DVR.getVariableLocationOp(0));543    if (CI.isZero())544      return DVR.getExpression()->getElements().equals(545          {dwarf::DW_OP_plus_uconst, 3, dwarf::DW_OP_stack_value});546    else if (CI.isOneValue())547      return DVR.getExpression()->getElements().equals(548          {dwarf::DW_OP_plus_uconst, 2, dwarf::DW_OP_stack_value});549    return false;550  }551 552  void verifyDebugValuesAreSalvaged() {553    // The function should only contain debug values and a terminator.554    EXPECT_EQ(F->size(), 1u);555    EXPECT_TRUE(F->begin()->begin()->isTerminator());556 557    // Check that the debug values for %x and %y are preserved.558    bool FoundX = false;559    bool FoundY = false;560    for (DbgVariableRecord &DVR :561         filterDbgVars(F->begin()->begin()->getDbgRecordRange())) {562      EXPECT_EQ(DVR.getVariable()->getName(), "x");563      FoundX |= doesDebugValueDescribeX(DVR);564      FoundY |= doesDebugValueDescribeY(DVR);565    }566    EXPECT_TRUE(FoundX);567    EXPECT_TRUE(FoundY);568  }569};570 571TEST_F(SalvageDebugInfoTest, RecursiveInstDeletion) {572  Instruction *Inst = &F->front().front();573  Inst = Inst->getNextNode(); // Get %y = add ...574  ASSERT_TRUE(Inst);575  bool Deleted = RecursivelyDeleteTriviallyDeadInstructions(Inst);576  ASSERT_TRUE(Deleted);577  verifyDebugValuesAreSalvaged();578}579 580TEST_F(SalvageDebugInfoTest, RecursiveBlockSimplification) {581  BasicBlock *BB = &F->front();582  ASSERT_TRUE(BB);583  bool Deleted = SimplifyInstructionsInBlock(BB);584  ASSERT_TRUE(Deleted);585  verifyDebugValuesAreSalvaged();586}587 588TEST(Local, ChangeToUnreachable) {589  LLVMContext Ctx;590 591  std::unique_ptr<Module> M = parseIR(Ctx,592                                      R"(593    define internal void @foo() !dbg !6 {594    entry:595      ret void, !dbg !8596    }597 598    !llvm.dbg.cu = !{!0}599    !llvm.debugify = !{!3, !4}600    !llvm.module.flags = !{!5}601 602    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)603    !1 = !DIFile(filename: "test.ll", directory: "/")604    !2 = !{}605    !3 = !{i32 1}606    !4 = !{i32 0}607    !5 = !{i32 2, !"Debug Info Version", i32 3}608    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, isLocal: true, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2)609    !7 = !DISubroutineType(types: !2)610    !8 = !DILocation(line: 1, column: 1, scope: !6)611  )");612 613  bool BrokenDebugInfo = true;614  verifyModule(*M, &errs(), &BrokenDebugInfo);615  ASSERT_FALSE(BrokenDebugInfo);616 617  Function &F = *cast<Function>(M->getNamedValue("foo"));618 619  BasicBlock &BB = F.front();620  Instruction &A = BB.front();621  DebugLoc DLA = A.getDebugLoc();622 623  ASSERT_TRUE(isa<ReturnInst>(&A));624  // One instruction should be affected.625  EXPECT_EQ(changeToUnreachable(&A), 1U);626 627  Instruction &B = BB.front();628 629  // There should be an uncreachable instruction.630  ASSERT_TRUE(isa<UnreachableInst>(&B));631 632  DebugLoc DLB = B.getDebugLoc();633  EXPECT_EQ(DLA, DLB);634}635 636TEST(Local, FindDbgRecords) {637  // DbgRecord copy of the FindDbgUsers test above.638  LLVMContext Ctx;639  std::unique_ptr<Module> M = parseIR(Ctx,640                                      R"(641  define dso_local void @fun(ptr %a) #0 !dbg !11 {642  entry:643      #dbg_assign(ptr %a, !16, !DIExpression(), !15, ptr %a, !DIExpression(), !19)644    ret void645  }646 647  !llvm.dbg.cu = !{!0}648  !llvm.module.flags = !{!2, !3, !9}649  !llvm.ident = !{!10}650 651  !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 17.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)652  !1 = !DIFile(filename: "test.cpp", directory: "/")653  !2 = !{i32 7, !"Dwarf Version", i32 5}654  !3 = !{i32 2, !"Debug Info Version", i32 3}655  !4 = !{i32 1, !"wchar_size", i32 4}656  !9 = !{i32 7, !"debug-info-assignment-tracking", i1 true}657  !10 = !{!"clang version 17.0.0"}658  !11 = distinct !DISubprogram(name: "fun", linkageName: "fun", scope: !1, file: !1, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)659  !12 = !DISubroutineType(types: !13)660  !13 = !{null}661  !14 = !{}662  !15 = distinct !DIAssignID()663  !16 = !DILocalVariable(name: "x", scope: !11, file: !1, line: 2, type: !17)664  !17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)665  !18 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)666  !19 = !DILocation(line: 0, scope: !11)667  )");668 669  bool BrokenDebugInfo = true;670  verifyModule(*M, &errs(), &BrokenDebugInfo);671  ASSERT_FALSE(BrokenDebugInfo);672 673  Function &Fun = *cast<Function>(M->getNamedValue("fun"));674  Value *Arg = Fun.getArg(0);675 676  SmallVector<DbgVariableRecord *> Records;677  // Arg (%a) is used twice by a single dbg_assign. Check findDbgUsers returns678  // only 1 pointer to it rather than 2.679  findDbgUsers(Arg, Records);680  EXPECT_EQ(Records.size(), 1u);681 682  Records.clear();683  // Arg (%a) is used twice by a single dbg_assign. Check findDbgValues returns684  // only 1 pointer to it rather than 2.685  findDbgValues(Arg, Records);686  EXPECT_EQ(Records.size(), 1u);687}688 689TEST(Local, ReplaceAllDbgUsesWith) {690  using namespace llvm::dwarf;691  LLVMContext Ctx;692 693  // Note: The datalayout simulates Darwin/x86_64.694  std::unique_ptr<Module> M = parseIR(Ctx,695                                      R"(696    target datalayout = "e-m:o-i63:64-f80:128-n8:16:32:64-S128"697 698    declare i32 @escape(i32)699 700    define void @f() !dbg !6 {701    entry:702      %a = add i32 0, 1, !dbg !15703 704        #dbg_value(i32 %a, !9, !DIExpression(), !15)705      %b = add i64 0, 1, !dbg !16706 707        #dbg_value(i64 %b, !11, !DIExpression(), !16)708        #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul), !16)709        #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value), !16)710        #dbg_value(i64 %b, !11, !DIExpression(DW_OP_LLVM_fragment, 0, 8), !16)711        #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_fragment, 0, 8), !16)712        #dbg_value(i64 %b, !11, !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8), !16)713      %c = inttoptr i64 0 to ptr, !dbg !17714 715        #dbg_declare(ptr %c, !13, !DIExpression(), !17)716      %d = inttoptr i64 0 to ptr, !dbg !18717 718        #dbg_declare(ptr %d,  !20,  !DIExpression(), !18)719      %e = add <2 x i16> zeroinitializer, zeroinitializer720 721        #dbg_value(<2 x i16> %e, !14, !DIExpression(), !18)722      %f = call i32 @escape(i32 0)723 724        #dbg_value(i32 %f, !9, !DIExpression(), !15)725      %barrier = call i32 @escape(i32 0)726 727      %g = call i32 @escape(i32 %f)728 729        #dbg_value(i32 %g, !9, !DIExpression(), !15)730      ret void, !dbg !19731    }732 733    !llvm.dbg.cu = !{!0}734    !llvm.module.flags = !{!5}735 736    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)737    !1 = !DIFile(filename: "/Users/vsk/Desktop/foo.ll", directory: "/")738    !2 = !{}739    !5 = !{i32 2, !"Debug Info Version", i32 3}740    !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)741    !7 = !DISubroutineType(types: !2)742    !8 = !{!9, !11, !13, !14}743    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)744    !10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_signed)745    !11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !12)746    !12 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_signed)747    !13 = !DILocalVariable(name: "3", scope: !6, file: !1, line: 3, type: !12)748    !14 = !DILocalVariable(name: "4", scope: !6, file: !1, line: 4, type: !10)749    !15 = !DILocation(line: 1, column: 1, scope: !6)750    !16 = !DILocation(line: 2, column: 1, scope: !6)751    !17 = !DILocation(line: 3, column: 1, scope: !6)752    !18 = !DILocation(line: 4, column: 1, scope: !6)753    !19 = !DILocation(line: 5, column: 1, scope: !6)754    !20 = !DILocalVariable(name: "5", scope: !6, file: !1, line: 5, type: !10)755  )");756 757  bool BrokenDebugInfo = true;758  verifyModule(*M, &errs(), &BrokenDebugInfo);759  ASSERT_FALSE(BrokenDebugInfo);760 761  Function &F = *cast<Function>(M->getNamedValue("f"));762  DominatorTree DT{F};763 764  BasicBlock &BB = F.front();765  Instruction &A = BB.front();766  Instruction &B = *A.getNextNode();767  Instruction &C = *B.getNextNode();768  Instruction &D = *C.getNextNode();769  Instruction &E = *D.getNextNode();770  Instruction &F_ = *E.getNextNode();771  Instruction &Barrier = *F_.getNextNode();772  Instruction &G = *Barrier.getNextNode();773 774  // Simulate i32 <-> i64* conversion. Expect no updates: the datalayout says775  // pointers are 64 bits, so the conversion would be lossy.776  EXPECT_FALSE(replaceAllDbgUsesWith(A, C, C, DT));777  EXPECT_FALSE(replaceAllDbgUsesWith(C, A, A, DT));778 779  // Simulate i32 <-> <2 x i16> conversion. This is unsupported.780  EXPECT_FALSE(replaceAllDbgUsesWith(E, A, A, DT));781  EXPECT_FALSE(replaceAllDbgUsesWith(A, E, E, DT));782 783  // Simulate i32* <-> i64* conversion.784  EXPECT_TRUE(replaceAllDbgUsesWith(D, C, C, DT));785 786  SmallVector<DbgVariableRecord *, 2> CDbgRecords;787  findDbgUsers(&C, CDbgRecords);788  EXPECT_EQ(2U, CDbgRecords.size());789  EXPECT_TRUE(all_of(790      CDbgRecords, [](DbgVariableRecord *DVR) { return DVR->isDbgDeclare(); }));791 792  EXPECT_TRUE(replaceAllDbgUsesWith(C, D, D, DT));793 794  SmallVector<DbgVariableRecord *, 2> DDbgRecords;795  findDbgUsers(&D, DDbgRecords);796  EXPECT_EQ(2U, DDbgRecords.size());797  EXPECT_TRUE(all_of(798      DDbgRecords, [](DbgVariableRecord *DVR) { return DVR->isDbgDeclare(); }));799 800  // Introduce a use-before-def. Check that the dbg.value for %a is salvaged.801  EXPECT_TRUE(replaceAllDbgUsesWith(A, F_, F_, DT));802 803  EXPECT_FALSE(A.hasDbgRecords());804  EXPECT_TRUE(B.hasDbgRecords());805  DbgVariableRecord *BDbgVal =806      cast<DbgVariableRecord>(&*B.getDbgRecordRange().begin());807  EXPECT_EQ(BDbgVal->getNumVariableLocationOps(), 1u);808  EXPECT_EQ(ConstantInt::get(A.getType(), 0),809            BDbgVal->getVariableLocationOp(0));810 811  // Introduce a use-before-def. Check that the dbg.values for %f become undef.812  EXPECT_TRUE(replaceAllDbgUsesWith(F_, G, G, DT));813 814  DbgVariableRecord *BarrierDbgVal =815      cast<DbgVariableRecord>(&*Barrier.getDbgRecordRange().begin());816  EXPECT_EQ(BarrierDbgVal->getNumVariableLocationOps(), 1u);817  EXPECT_TRUE(BarrierDbgVal->isKillLocation());818 819  SmallVector<DbgVariableRecord *, 8> BarrierDbgRecs;820  findDbgValues(&F_, BarrierDbgRecs);821  EXPECT_EQ(0U, BarrierDbgRecs.size());822 823  // Simulate i32 -> i64 conversion to test sign-extension. Here are some824  // interesting cases to handle:825  //  1) debug user has empty DIExpression826  //  2) debug user has non-empty, non-stack-value'd DIExpression827  //  3) debug user has non-empty, stack-value'd DIExpression828  //  4-6) like (1-3), but with a fragment829  EXPECT_TRUE(replaceAllDbgUsesWith(B, A, A, DT));830 831  SmallVector<DbgVariableRecord *, 8> BDbgRecs;832  findDbgValues(&A, BDbgRecs);833  EXPECT_EQ(6U, BDbgRecs.size());834 835  // Check that %a has a dbg.value with a DIExpression matching \p Ops.836  auto hasADbgVal = [&](ArrayRef<uint64_t> Ops) {837    return any_of(BDbgRecs, [&](DbgVariableRecord *DVI) {838      assert(DVI->getVariable()->getName() == "2");839      return DVI->getExpression()->getElements() == Ops;840    });841  };842 843  // Case 1: The original expr is empty, so no deref is needed.844  EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_convert, 32, DW_ATE_signed,845                         DW_OP_LLVM_convert, 64, DW_ATE_signed,846                         DW_OP_stack_value}));847 848  // Case 2: Perform an address calculation with the original expr, deref it,849  // then sign-extend the result.850  EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref,851                         DW_OP_LLVM_convert, 32, DW_ATE_signed,852                         DW_OP_LLVM_convert, 64, DW_ATE_signed,853                         DW_OP_stack_value}));854 855  // Case 3: Insert the sign-extension logic before the DW_OP_stack_value.856  EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_convert, 32,857                         DW_ATE_signed, DW_OP_LLVM_convert, 64, DW_ATE_signed,858                         DW_OP_stack_value}));859 860  // Cases 4-6: Just like cases 1-3, but preserve the fragment at the end.861  EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_convert, 32, DW_ATE_signed,862                         DW_OP_LLVM_convert, 64, DW_ATE_signed,863                         DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8}));864 865  EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref,866                         DW_OP_LLVM_convert, 32, DW_ATE_signed,867                         DW_OP_LLVM_convert, 64, DW_ATE_signed,868                         DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8}));869 870  EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_convert, 32,871                         DW_ATE_signed, DW_OP_LLVM_convert, 64, DW_ATE_signed,872                         DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8}));873 874  verifyModule(*M, &errs(), &BrokenDebugInfo);875  ASSERT_FALSE(BrokenDebugInfo);876}877 878TEST(Local, RemoveUnreachableBlocks) {879  LLVMContext C;880 881  std::unique_ptr<Module> M = parseIR(C,882                                      R"(883      define void @br_simple() {884      entry:885        br label %bb0886      bb0:887        ret void888      bb1:889        ret void890      }891 892      define void @br_self_loop() {893      entry:894        br label %bb0895      bb0:896        br i1 true, label %bb1, label %bb0897      bb1:898        br i1 true, label %bb0, label %bb2899      bb2:900        br label %bb2901      }902 903      define void @br_constant() {904      entry:905        br label %bb0906      bb0:907        br i1 true, label %bb1, label %bb2908      bb1:909        br i1 true, label %bb0, label %bb2910      bb2:911        br label %bb2912      }913 914      define void @br_loop() {915      entry:916        br label %bb0917      bb0:918        br label %bb0919      bb1:920        br label %bb2921      bb2:922        br label %bb1923      }924 925      declare i32 @__gxx_personality_v0(...)926 927      define void @invoke_terminator() personality ptr @__gxx_personality_v0 {928      entry:929        br i1 undef, label %invoke.block, label %exit930 931      invoke.block:932        %cond = invoke zeroext i1 @invokable()933                to label %continue.block unwind label %lpad.block934 935      continue.block:936        br i1 %cond, label %if.then, label %if.end937 938      if.then:939        unreachable940 941      if.end:942        unreachable943 944      lpad.block:945        %lp = landingpad { ptr, i32 }946                catch ptr null947        br label %exit948 949      exit:950        ret void951      }952 953      declare i1 @invokable()954      )");955 956  auto runEager = [&](Function &F, DominatorTree *DT) {957    PostDominatorTree PDT = PostDominatorTree(F);958    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);959    removeUnreachableBlocks(F, &DTU);960    EXPECT_TRUE(DTU.getDomTree().verify());961    EXPECT_TRUE(DTU.getPostDomTree().verify());962  };963 964  auto runLazy = [&](Function &F, DominatorTree *DT) {965    PostDominatorTree PDT = PostDominatorTree(F);966    DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);967    removeUnreachableBlocks(F, &DTU);968    EXPECT_TRUE(DTU.getDomTree().verify());969    EXPECT_TRUE(DTU.getPostDomTree().verify());970  };971 972  // Test removeUnreachableBlocks under Eager UpdateStrategy.973  runWithDomTree(*M, "br_simple", runEager);974  runWithDomTree(*M, "br_self_loop", runEager);975  runWithDomTree(*M, "br_constant", runEager);976  runWithDomTree(*M, "br_loop", runEager);977  runWithDomTree(*M, "invoke_terminator", runEager);978 979  // Test removeUnreachableBlocks under Lazy UpdateStrategy.980  runWithDomTree(*M, "br_simple", runLazy);981  runWithDomTree(*M, "br_self_loop", runLazy);982  runWithDomTree(*M, "br_constant", runLazy);983  runWithDomTree(*M, "br_loop", runLazy);984  runWithDomTree(*M, "invoke_terminator", runLazy);985 986  M = parseIR(C,987              R"(988      define void @f() {989      entry:990        ret void991      bb0:992        ret void993      }994        )");995 996  auto checkRUBlocksRetVal = [&](Function &F, DominatorTree *DT) {997    DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);998    EXPECT_TRUE(removeUnreachableBlocks(F, &DTU));999    EXPECT_FALSE(removeUnreachableBlocks(F, &DTU));1000    EXPECT_TRUE(DTU.getDomTree().verify());1001  };1002 1003  runWithDomTree(*M, "f", checkRUBlocksRetVal);1004}1005 1006TEST(Local, SimplifyCFGWithNullAC) {1007  LLVMContext Ctx;1008 1009  std::unique_ptr<Module> M = parseIR(Ctx, R"(1010    declare void @true_path()1011    declare void @false_path()1012    declare void @llvm.assume(i1 %cond);1013 1014    define i32 @foo(i1, i32) {1015    entry:1016      %cmp = icmp sgt i32 %1, 01017      br i1 %cmp, label %if.bb1, label %then.bb11018    if.bb1:1019      call void @true_path()1020      br label %test.bb1021    then.bb1:1022      call void @false_path()1023      br label %test.bb1024    test.bb:1025      %phi = phi i1 [1, %if.bb1], [%0, %then.bb1]1026      call void @llvm.assume(i1 %0)1027      br i1 %phi, label %if.bb2, label %then.bb21028    if.bb2:1029      ret i32 %11030    then.bb2:1031      ret i32 01032    }1033  )");1034 1035  Function &F = *cast<Function>(M->getNamedValue("foo"));1036  TargetTransformInfo TTI(M->getDataLayout());1037 1038  SimplifyCFGOptions Options{};1039  Options.setAssumptionCache(nullptr);1040 1041  // Obtain BasicBlock of interest to this test, %test.bb.1042  BasicBlock *TestBB = nullptr;1043  for (BasicBlock &BB : F) {1044    if (BB.getName() == "test.bb") {1045      TestBB = &BB;1046      break;1047    }1048  }1049  ASSERT_TRUE(TestBB);1050 1051  DominatorTree DT(F);1052  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);1053 1054  // %test.bb is expected to be simplified by FoldCondBranchOnPHI.1055  EXPECT_TRUE(simplifyCFG(TestBB, TTI,1056                          RequireAndPreserveDomTree ? &DTU : nullptr, Options));1057}1058 1059TEST(LocalTest, TargetTypeInfoHasNoReplacementProperty) {1060  LLVMContext Ctx;1061  SmallVector<unsigned, 3> Ints = {};1062  auto *TT = llvm::TargetExtType::get(Ctx, "dx.RawBuffer", {}, Ints);1063 1064  EXPECT_TRUE(TT->hasProperty(TargetExtType::Property::IsTokenLike));1065}1066 1067TEST(Local, CanReplaceOperandWithVariable) {1068  LLVMContext Ctx;1069  Module M("test_module", Ctx);1070  IRBuilder<> B(Ctx);1071 1072  FunctionType *FnType =1073    FunctionType::get(Type::getVoidTy(Ctx), {}, false);1074 1075  FunctionType *VarArgFnType =1076    FunctionType::get(Type::getVoidTy(Ctx), {B.getInt32Ty()}, true);1077 1078  Function *TestBody = Function::Create(FnType, GlobalValue::ExternalLinkage,1079                                        0, "", &M);1080 1081  BasicBlock *BB0 = BasicBlock::Create(Ctx, "", TestBody);1082  B.SetInsertPoint(BB0);1083 1084  FunctionCallee Intrin = M.getOrInsertFunction("llvm.foo", FnType);1085  FunctionCallee Func = M.getOrInsertFunction("foo", FnType);1086  FunctionCallee VarArgFunc1087    = M.getOrInsertFunction("foo.vararg", VarArgFnType);1088  FunctionCallee VarArgIntrin1089    = M.getOrInsertFunction("llvm.foo.vararg", VarArgFnType);1090 1091  auto *CallToIntrin = B.CreateCall(Intrin);1092  auto *CallToFunc = B.CreateCall(Func);1093 1094  // Test if it's valid to replace the callee operand.1095  EXPECT_FALSE(canReplaceOperandWithVariable(CallToIntrin, 0));1096  EXPECT_TRUE(canReplaceOperandWithVariable(CallToFunc, 0));1097 1098  // That it's invalid to replace an argument in the variadic argument list for1099  // an intrinsic, but OK for a normal function.1100  auto *CallToVarArgFunc = B.CreateCall(1101    VarArgFunc, {B.getInt32(0), B.getInt32(1), B.getInt32(2)});1102  EXPECT_TRUE(canReplaceOperandWithVariable(CallToVarArgFunc, 0));1103  EXPECT_TRUE(canReplaceOperandWithVariable(CallToVarArgFunc, 1));1104  EXPECT_TRUE(canReplaceOperandWithVariable(CallToVarArgFunc, 2));1105  EXPECT_TRUE(canReplaceOperandWithVariable(CallToVarArgFunc, 3));1106 1107  auto *CallToVarArgIntrin = B.CreateCall(1108    VarArgIntrin, {B.getInt32(0), B.getInt32(1), B.getInt32(2)});1109  EXPECT_TRUE(canReplaceOperandWithVariable(CallToVarArgIntrin, 0));1110  EXPECT_FALSE(canReplaceOperandWithVariable(CallToVarArgIntrin, 1));1111  EXPECT_FALSE(canReplaceOperandWithVariable(CallToVarArgIntrin, 2));1112  EXPECT_FALSE(canReplaceOperandWithVariable(CallToVarArgIntrin, 3));1113 1114  // Test that it's invalid to replace gcroot operands, even though it can't use1115  // immarg.1116  Type *PtrPtr = B.getPtrTy(0);1117  Value *Alloca = B.CreateAlloca(PtrPtr, (unsigned)0);1118  CallInst *GCRoot = B.CreateIntrinsic(1119      Intrinsic::gcroot, {Alloca, Constant::getNullValue(PtrPtr)});1120  EXPECT_TRUE(canReplaceOperandWithVariable(GCRoot, 0)); // Alloca1121  EXPECT_FALSE(canReplaceOperandWithVariable(GCRoot, 1));1122  EXPECT_FALSE(canReplaceOperandWithVariable(GCRoot, 2));1123 1124  BB0->dropAllReferences();1125}1126 1127TEST(Local, ExpressionForConstant) {1128  LLVMContext Context;1129  Module M("test_module", Context);1130  DIBuilder DIB(M);1131  DIExpression *Expr = nullptr;1132 1133  auto createExpression = [&](Constant *C, Type *Ty) -> DIExpression * {1134    EXPECT_NE(C, nullptr);1135    EXPECT_NE(Ty, nullptr);1136    EXPECT_EQ(C->getType(), Ty);1137    std::unique_ptr<GlobalVariable> GV = std::make_unique<GlobalVariable>(1138        Ty, false, GlobalValue::ExternalLinkage, C, "GV");1139    EXPECT_NE(GV, nullptr);1140 1141    DIExpression *Expr = getExpressionForConstant(DIB, *GV->getInitializer(),1142                                                  *GV->getValueType());1143    if (Expr) {1144      EXPECT_EQ(Expr->getNumElements(), 3u);1145      EXPECT_EQ(Expr->getElement(0), dwarf::DW_OP_constu);1146      EXPECT_EQ(Expr->getElement(2), dwarf::DW_OP_stack_value);1147    }1148    return Expr;1149  };1150 1151  // Integer.1152  IntegerType *Int1Ty = Type::getInt1Ty(Context);1153  Expr = createExpression(ConstantInt::getTrue(Context), Int1Ty);1154  EXPECT_NE(Expr, nullptr);1155  EXPECT_EQ(Expr->getElement(1), 1U);1156 1157  Expr = createExpression(ConstantInt::getFalse(Context), Int1Ty);1158  EXPECT_NE(Expr, nullptr);1159  EXPECT_EQ(Expr->getElement(1), 0U);1160 1161  IntegerType *Int8Ty = Type::getInt8Ty(Context);1162  Expr = createExpression(ConstantInt::get(Int8Ty, 100), Int8Ty);1163  EXPECT_NE(Expr, nullptr);1164  EXPECT_EQ(Expr->getElement(1), 100U);1165 1166  IntegerType *Int16Ty = Type::getInt16Ty(Context);1167  Expr = createExpression(ConstantInt::getSigned(Int16Ty, -50), Int16Ty);1168  EXPECT_NE(Expr, nullptr);1169  EXPECT_EQ(Expr->getElement(1), -50ULL);1170 1171  IntegerType *Int32Ty = Type::getInt32Ty(Context);1172  Expr = createExpression(ConstantInt::get(Int32Ty, 0x7FFFFFFF), Int32Ty);1173  EXPECT_NE(Expr, nullptr);1174  EXPECT_EQ(Expr->getElement(1), 0x7FFFFFFFU);1175 1176  IntegerType *Int64Ty = Type::getInt64Ty(Context);1177  Expr =1178      createExpression(ConstantInt::get(Int64Ty, 0x7FFFFFFFFFFFFFFF), Int64Ty);1179  EXPECT_NE(Expr, nullptr);1180  EXPECT_EQ(Expr->getElement(1), 0x7FFFFFFFFFFFFFFFU);1181 1182  IntegerType *Int128Ty = Type::getInt128Ty(Context);1183  Expr = createExpression(ConstantInt::get(Int128Ty, 0x7FFFFFFFFFFFFFFF),1184                          Int128Ty);1185  EXPECT_NE(Expr, nullptr);1186  EXPECT_EQ(Expr->getElement(1), 0x7FFFFFFFFFFFFFFFU);1187 1188  GlobalVariable *String =1189      IRBuilder<>(Context).CreateGlobalString("hello", "hello", 0, &M);1190  Expr = createExpression(ConstantExpr::getPtrToInt(String, Int32Ty), Int32Ty);1191  EXPECT_EQ(Expr, nullptr);1192 1193  // Float.1194  Type *FloatTy = Type::getFloatTy(Context);1195  Expr = createExpression(ConstantFP::get(FloatTy, 5.55), FloatTy);1196  EXPECT_NE(Expr, nullptr);1197  EXPECT_EQ(Expr->getElement(1), 1085381018U);1198 1199  // Double.1200  Type *DoubleTy = Type::getDoubleTy(Context);1201  Expr = createExpression(ConstantFP::get(DoubleTy, -5.55), DoubleTy);1202  EXPECT_NE(Expr, nullptr);1203  EXPECT_EQ(Expr->getElement(1), 13841306799765140275U);1204 1205  // Half.1206  Type *HalfTy = Type::getHalfTy(Context);1207  Expr = createExpression(ConstantFP::get(HalfTy, 5.55), HalfTy);1208  EXPECT_NE(Expr, nullptr);1209  EXPECT_EQ(Expr->getElement(1), 17805U);1210 1211  // BFloat.1212  Type *BFloatTy = Type::getBFloatTy(Context);1213  Expr = createExpression(ConstantFP::get(BFloatTy, -5.55), BFloatTy);1214  EXPECT_NE(Expr, nullptr);1215  EXPECT_EQ(Expr->getElement(1), 49330U);1216 1217  // Pointer.1218  PointerType *PtrTy = PointerType::get(Context, 0);1219  Expr = createExpression(ConstantPointerNull::get(PtrTy), PtrTy);1220  EXPECT_NE(Expr, nullptr);1221  EXPECT_EQ(Expr->getElement(1), 0U);1222 1223  ConstantInt *K1 = ConstantInt::get(Type::getInt32Ty(Context), 1234);1224  Expr = createExpression(ConstantExpr::getIntToPtr(K1, PtrTy), PtrTy);1225  EXPECT_NE(Expr, nullptr);1226  EXPECT_EQ(Expr->getElement(1), 1234U);1227 1228  ConstantInt *K2 = ConstantInt::get(Type::getInt64Ty(Context), 5678);1229  Expr = createExpression(ConstantExpr::getIntToPtr(K2, PtrTy), PtrTy);1230  EXPECT_NE(Expr, nullptr);1231  EXPECT_EQ(Expr->getElement(1), 5678U);1232 1233  Type *FP128Ty = Type::getFP128Ty(Context);1234  Expr = createExpression(ConstantFP::get(FP128Ty, 32), FP128Ty);1235  EXPECT_EQ(Expr, nullptr);1236 1237  Type *X86_FP80Ty = Type::getX86_FP80Ty(Context);1238  Expr = createExpression(ConstantFP::get(X86_FP80Ty, 32), X86_FP80Ty);1239  EXPECT_EQ(Expr, nullptr);1240 1241  Type *PPC_FP128Ty = Type::getPPC_FP128Ty(Context);1242  Expr = createExpression(ConstantFP::get(PPC_FP128Ty, 32), PPC_FP128Ty);1243  EXPECT_EQ(Expr, nullptr);1244}1245 1246TEST(Local, ReplaceDbgVariableRecord) {1247  LLVMContext C;1248 1249  // Test that RAUW also replaces the operands of DbgVariableRecord objects,1250  // i.e. non-instruction stored debugging information.1251  std::unique_ptr<Module> M = parseIR(C,1252                                      R"(1253      declare void @llvm.dbg.value(metadata, metadata, metadata)1254      define void @f(i32 %a) !dbg !8 {1255      entry:1256        %foo = add i32 %a, 1, !dbg !131257        %bar = add i32 %foo, 0, !dbg !131258          #dbg_value(i32 %bar, !11, !DIExpression(), !13)1259        ret void, !dbg !141260      }1261      !llvm.dbg.cu = !{!0}1262      !llvm.module.flags = !{!3, !4}1263      !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)1264      !1 = !DIFile(filename: "t2.c", directory: "foo")1265      !2 = !{}1266      !3 = !{i32 2, !"Dwarf Version", i32 4}1267      !4 = !{i32 2, !"Debug Info Version", i32 3}1268      !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2)1269      !9 = !DISubroutineType(types: !10)1270      !10 = !{null}1271      !11 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !12)1272      !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)1273      !13 = !DILocation(line: 2, column: 7, scope: !8)1274      !14 = !DILocation(line: 3, column: 1, scope: !8)1275      )");1276  auto *GV = M->getNamedValue("f");1277  ASSERT_TRUE(GV);1278  auto *F = dyn_cast<Function>(GV);1279  ASSERT_TRUE(F);1280  BasicBlock::iterator It = F->front().begin();1281  Instruction *FooInst = &*It;1282  It = std::next(It);1283  Instruction *BarInst = &*It;1284  It = std::next(It);1285  Instruction *RetInst = &*It;1286 1287  // There should be a DbgVariableRecord on the return.1288  auto Range = RetInst->getDbgRecordRange();1289  ASSERT_FALSE(Range.empty());1290  DbgVariableRecord *DVR = dyn_cast<DbgVariableRecord>(&*Range.begin());1291  ASSERT_NE(DVR, nullptr);1292 1293  // DVR should originally refer to %bar,1294  EXPECT_EQ(DVR->getVariableLocationOp(0), BarInst);1295 1296  // Now try to replace the computation of %bar with %foo -- this should cause1297  // the DbgVariableRecord's to have it's operand updated beneath it.1298  BarInst->replaceAllUsesWith(FooInst);1299  // Check DVR now points at %foo.1300  EXPECT_EQ(DVR->getVariableLocationOp(0), FooInst);1301 1302  // Teardown.1303  RetInst->DebugMarker->eraseFromParent();1304}1305