brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.7 KiB · 20c66b9 Raw
430 lines · cpp
1//===- unittests/IR/DroppedVariableStatsIRTest.cpp ------------------------===//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/AsmParser/Parser.h"10#include "llvm/IR/Function.h"11#include "llvm/IR/InstIterator.h"12#include "llvm/IR/LegacyPassManager.h"13#include "llvm/IR/Module.h"14#include "llvm/Pass.h"15#include "llvm/PassRegistry.h"16#include "llvm/Passes/StandardInstrumentations.h"17#include "llvm/Support/SourceMgr.h"18#include "gtest/gtest.h"19#include <llvm/ADT/SmallString.h>20#include <llvm/IR/LLVMContext.h>21#include <llvm/IR/PassInstrumentation.h>22#include <llvm/IR/PassManager.h>23#include <llvm/IR/PassTimingInfo.h>24#include <llvm/Support/raw_ostream.h>25 26using namespace llvm;27namespace llvm {28void initializePassTest1Pass(PassRegistry &);29 30static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {31  SMDiagnostic Err;32  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);33  if (!Mod)34    Err.print("AbstractCallSiteTests", errs());35  return Mod;36}37} // namespace llvm38 39namespace {40 41// This test ensures that if a #dbg_value and an instruction that exists in the42// same scope as that #dbg_value are both deleted as a result of an optimization43// pass, debug information is considered not dropped.44TEST(DroppedVariableStatsIR, BothDeleted) {45  PassInstrumentationCallbacks PIC;46  PassInstrumentation PI(&PIC);47 48  LLVMContext C;49 50  const char *IR =51      R"(52      ; Function Attrs: mustprogress nounwind ssp uwtable(sync)53      define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {54      entry:55        #dbg_value(i32 %x, !15, !DIExpression(), !16)56        %add = add nsw i32 %x, 1, !dbg !1757        ret i32 058      }59      !llvm.dbg.cu = !{!0}60      !llvm.module.flags = !{!3}61      !llvm.ident = !{!8}62      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")63      !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")64      !3 = !{i32 2, !"Debug Info Version", i32 3}65      !8 = !{!"clang"}66      !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)67      !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")68      !11 = !DISubroutineType(types: !12)69      !12 = !{!13, !13}70      !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)71      !14 = !{!15}72      !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)73      !16 = !DILocation(line: 0, scope: !9)74      !17 = !DILocation(line: 2, column: 11, scope: !9))";75 76  std::unique_ptr<llvm::Module> M = parseIR(C, IR);77  ASSERT_TRUE(M);78 79  DroppedVariableStatsIR Stats(true);80  Stats.runBeforePass("", llvm::Any(const_cast<const llvm::Module *>(M.get())));81 82  // This loop simulates an IR pass that drops debug information.83  for (auto &F : *M) {84    for (auto &I : instructions(&F)) {85      I.dropDbgRecords();86      I.eraseFromParent();87      break;88    }89    break;90  }91  Stats.runAfterPass("Test",92                     llvm::Any(const_cast<const llvm::Module *>(M.get())));93  ASSERT_EQ(Stats.getPassDroppedVariables(), false);94}95 96// This test ensures that if a #dbg_value is dropped after an optimization pass,97// but an instruction that shares the same scope as the #dbg_value still exists,98// debug information is conisdered dropped.99TEST(DroppedVariableStatsIR, DbgValLost) {100  PassInstrumentationCallbacks PIC;101  PassInstrumentation PI(&PIC);102 103  LLVMContext C;104 105  const char *IR =106      R"(107      ; Function Attrs: mustprogress nounwind ssp uwtable(sync)108      define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {109      entry:110        #dbg_value(i32 %x, !15, !DIExpression(), !16)111        %add = add nsw i32 %x, 1, !dbg !17112        ret i32 0113      }114      !llvm.dbg.cu = !{!0}115      !llvm.module.flags = !{!3}116      !llvm.ident = !{!8}117      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")118      !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")119      !3 = !{i32 2, !"Debug Info Version", i32 3}120      !8 = !{!"clang"}121      !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)122      !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")123      !11 = !DISubroutineType(types: !12)124      !12 = !{!13, !13}125      !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)126      !14 = !{!15}127      !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)128      !16 = !DILocation(line: 0, scope: !9)129      !17 = !DILocation(line: 2, column: 11, scope: !9))";130 131  std::unique_ptr<llvm::Module> M = parseIR(C, IR);132  ASSERT_TRUE(M);133 134  DroppedVariableStatsIR Stats(true);135  Stats.runBeforePass("", llvm::Any(const_cast<const llvm::Module *>(M.get())));136 137  // This loop simulates an IR pass that drops debug information.138  for (auto &F : *M) {139    for (auto &I : instructions(&F)) {140      I.dropDbgRecords();141      break;142    }143    break;144  }145  Stats.runAfterPass("Test",146                     llvm::Any(const_cast<const llvm::Module *>(M.get())));147  ASSERT_EQ(Stats.getPassDroppedVariables(), true);148}149 150// This test ensures that if a #dbg_value is dropped after an optimization pass,151// but an instruction that has an unrelated scope as the #dbg_value still152// exists, debug information is conisdered not dropped.153TEST(DroppedVariableStatsIR, UnrelatedScopes) {154  PassInstrumentationCallbacks PIC;155  PassInstrumentation PI(&PIC);156 157  LLVMContext C;158 159  const char *IR =160      R"(161      ; Function Attrs: mustprogress nounwind ssp uwtable(sync)162      define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {163      entry:164        #dbg_value(i32 %x, !15, !DIExpression(), !16)165        %add = add nsw i32 %x, 1, !dbg !17166        ret i32 0167      }168      !llvm.dbg.cu = !{!0}169      !llvm.module.flags = !{!3}170      !llvm.ident = !{!8}171      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")172      !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")173      !3 = !{i32 2, !"Debug Info Version", i32 3}174      !8 = !{!"clang"}175      !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)176      !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")177      !11 = !DISubroutineType(types: !12)178      !12 = !{!13, !13}179      !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)180      !14 = !{!15}181      !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)182      !16 = !DILocation(line: 0, scope: !9)183      !17 = !DILocation(line: 2, column: 11, scope: !18)184      !18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3bari", scope: !10, file: !10, line: 11, type: !11, scopeLine: 1,  unit: !0, retainedNodes: !14))";185 186  std::unique_ptr<llvm::Module> M = parseIR(C, IR);187  ASSERT_TRUE(M);188 189  DroppedVariableStatsIR Stats(true);190  Stats.runBeforePass("", llvm::Any(const_cast<const llvm::Module *>(M.get())));191 192  // This loop simulates an IR pass that drops debug information.193  for (auto &F : *M) {194    for (auto &I : instructions(&F)) {195      I.dropDbgRecords();196      break;197    }198    break;199  }200  Stats.runAfterPass("Test",201                     llvm::Any(const_cast<const llvm::Module *>(M.get())));202  ASSERT_EQ(Stats.getPassDroppedVariables(), false);203}204 205// This test ensures that if a #dbg_value is dropped after an optimization pass,206// but an instruction that has a scope which is a child of the #dbg_value scope207// still exists, debug information is conisdered dropped.208TEST(DroppedVariableStatsIR, ChildScopes) {209  PassInstrumentationCallbacks PIC;210  PassInstrumentation PI(&PIC);211 212  LLVMContext C;213 214  const char *IR =215      R"(216      ; Function Attrs: mustprogress nounwind ssp uwtable(sync)217      define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {218      entry:219        #dbg_value(i32 %x, !15, !DIExpression(), !16)220        %add = add nsw i32 %x, 1, !dbg !17221        ret i32 0222      }223      !llvm.dbg.cu = !{!0}224      !llvm.module.flags = !{!3}225      !llvm.ident = !{!8}226      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")227      !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")228      !3 = !{i32 2, !"Debug Info Version", i32 3}229      !8 = !{!"clang"}230      !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)231      !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")232      !11 = !DISubroutineType(types: !12)233      !12 = !{!13, !13}234      !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)235      !14 = !{!15}236      !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)237      !16 = !DILocation(line: 0, scope: !9)238      !17 = !DILocation(line: 2, column: 11, scope: !18)239      !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28))";240 241  std::unique_ptr<llvm::Module> M = parseIR(C, IR);242  ASSERT_TRUE(M);243 244  DroppedVariableStatsIR Stats(true);245  Stats.runBeforePass("", llvm::Any(const_cast<const llvm::Module *>(M.get())));246 247  // This loop simulates an IR pass that drops debug information.248  for (auto &F : *M) {249    for (auto &I : instructions(&F)) {250      I.dropDbgRecords();251      break;252    }253    break;254  }255  Stats.runAfterPass("Test",256                     llvm::Any(const_cast<const llvm::Module *>(M.get())));257  ASSERT_EQ(Stats.getPassDroppedVariables(), true);258}259 260// This test ensures that if a #dbg_value is dropped after an optimization pass,261// but an instruction that has a scope which is a child of the #dbg_value scope262// still exists, and the #dbg_value is inlined at another location, debug263// information is conisdered not dropped.264TEST(DroppedVariableStatsIR, InlinedAt) {265  PassInstrumentationCallbacks PIC;266  PassInstrumentation PI(&PIC);267 268  LLVMContext C;269 270  const char *IR =271      R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)272      define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {273      entry:274        #dbg_value(i32 %x, !15, !DIExpression(), !16)275        %add = add nsw i32 %x, 1, !dbg !17276        ret i32 0277      }278      !llvm.dbg.cu = !{!0}279      !llvm.module.flags = !{!3}280      !llvm.ident = !{!8}281      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")282      !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")283      !3 = !{i32 2, !"Debug Info Version", i32 3}284      !8 = !{!"clang"}285      !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)286      !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")287      !11 = !DISubroutineType(types: !12)288      !12 = !{!13, !13}289      !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)290      !14 = !{!15}291      !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)292      !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)293      !17 = !DILocation(line: 2, column: 11, scope: !18)294      !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)295      !19 = !DILocation(line: 3, column: 2, scope: !9))";296 297  std::unique_ptr<llvm::Module> M = parseIR(C, IR);298  ASSERT_TRUE(M);299 300  DroppedVariableStatsIR Stats(true);301  Stats.runBeforePass("", llvm::Any(const_cast<const llvm::Module *>(M.get())));302 303  // This loop simulates an IR pass that drops debug information.304  for (auto &F : *M) {305    for (auto &I : instructions(&F)) {306      I.dropDbgRecords();307      break;308    }309    break;310  }311  Stats.runAfterPass("Test",312                     llvm::Any(const_cast<const llvm::Module *>(M.get())));313  ASSERT_EQ(Stats.getPassDroppedVariables(), false);314}315 316// This test ensures that if a #dbg_value is dropped after an optimization pass,317// but an instruction that has a scope which is a child of the #dbg_value scope318// still exists, and the #dbg_value and the instruction are inlined at another319// location, debug information is conisdered dropped.320TEST(DroppedVariableStatsIR, InlinedAtShared) {321  PassInstrumentationCallbacks PIC;322  PassInstrumentation PI(&PIC);323 324  LLVMContext C;325 326  const char *IR =327      R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)328      define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {329      entry:330        #dbg_value(i32 %x, !15, !DIExpression(), !16)331        %add = add nsw i32 %x, 1, !dbg !17332        ret i32 0333      }334      !llvm.dbg.cu = !{!0}335      !llvm.module.flags = !{!3}336      !llvm.ident = !{!8}337      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")338      !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")339      !3 = !{i32 2, !"Debug Info Version", i32 3}340      !8 = !{!"clang"}341      !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)342      !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")343      !11 = !DISubroutineType(types: !12)344      !12 = !{!13, !13}345      !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)346      !14 = !{!15}347      !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)348      !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)349      !17 = !DILocation(line: 2, column: 11, scope: !18, inlinedAt: !19)350      !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)351      !19 = !DILocation(line: 3, column: 2, scope: !9))";352 353  std::unique_ptr<llvm::Module> M = parseIR(C, IR);354  ASSERT_TRUE(M);355 356  DroppedVariableStatsIR Stats(true);357  Stats.runBeforePass("", llvm::Any(const_cast<const llvm::Module *>(M.get())));358 359  // This loop simulates an IR pass that drops debug information.360  for (auto &F : *M) {361    for (auto &I : instructions(&F)) {362      I.dropDbgRecords();363      break;364    }365    break;366  }367  Stats.runAfterPass("Test",368                     llvm::Any(const_cast<const llvm::Module *>(M.get())));369  ASSERT_EQ(Stats.getPassDroppedVariables(), true);370}371 372// This test ensures that if a #dbg_value is dropped after an optimization pass,373// but an instruction that has a scope which is a child of the #dbg_value scope374// still exists, and the instruction is inlined at a location that is the375// #dbg_value's inlined at location, debug information is conisdered dropped.376TEST(DroppedVariableStatsIR, InlinedAtChild) {377  PassInstrumentationCallbacks PIC;378  PassInstrumentation PI(&PIC);379 380  LLVMContext C;381 382  const char *IR =383      R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)384      define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {385      entry:386        #dbg_value(i32 %x, !15, !DIExpression(), !16)387        %add = add nsw i32 %x, 1, !dbg !17388        ret i32 0389      }390      !llvm.dbg.cu = !{!0}391      !llvm.module.flags = !{!3}392      !llvm.ident = !{!8}393      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")394      !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")395      !3 = !{i32 2, !"Debug Info Version", i32 3}396      !8 = !{!"clang"}397      !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)398      !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")399      !11 = !DISubroutineType(types: !12)400      !12 = !{!13, !13}401      !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)402      !14 = !{!15}403      !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)404      !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)405      !17 = !DILocation(line: 2, column: 11, scope: !18, inlinedAt: !20)406      !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)407      !19 = !DILocation(line: 3, column: 2, scope: !9);408      !20 = !DILocation(line: 4, column: 5, scope: !18, inlinedAt: !19))";409 410  std::unique_ptr<llvm::Module> M = parseIR(C, IR);411  ASSERT_TRUE(M);412 413  DroppedVariableStatsIR Stats(true);414  Stats.runBeforePass("", llvm::Any(const_cast<const llvm::Module *>(M.get())));415 416  // This loop simulates an IR pass that drops debug information.417  for (auto &F : *M) {418    for (auto &I : instructions(&F)) {419      I.dropDbgRecords();420      break;421    }422    break;423  }424  Stats.runAfterPass("Test",425                     llvm::Any(const_cast<const llvm::Module *>(M.get())));426  ASSERT_EQ(Stats.getPassDroppedVariables(), true);427}428 429} // end anonymous namespace430