|
6 | 6 | //
|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 |
|
| 9 | +#include "llvm/Analysis/TargetLibraryInfo.h" |
9 | 10 | #include "llvm/AsmParser/Parser.h"
|
10 | 11 | #include "llvm/IR/LLVMContext.h"
|
11 | 12 | #include "llvm/IR/Module.h"
|
| 13 | +#include "llvm/Passes/PassBuilder.h" |
12 | 14 | #include "llvm/ProfileData/MemProf.h"
|
13 | 15 | #include "llvm/Support/SourceMgr.h"
|
14 | 16 | #include "llvm/Transforms/Instrumentation/MemProfiler.h"
|
@@ -80,7 +82,12 @@ declare !dbg !19 void @_Z2f3v()
|
80 | 82 | std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Ctx);
|
81 | 83 | ASSERT_TRUE(M);
|
82 | 84 |
|
83 |
| - auto Calls = extractCallsFromIR(*M); |
| 85 | + auto *F = M->getFunction("_Z3foov"); |
| 86 | + ASSERT_NE(F, nullptr); |
| 87 | + |
| 88 | + TargetLibraryInfoWrapperPass WrapperPass; |
| 89 | + auto &TLI = WrapperPass.getTLI(*F); |
| 90 | + auto Calls = extractCallsFromIR(*M, TLI); |
84 | 91 |
|
85 | 92 | // Expect exactly one caller.
|
86 | 93 | ASSERT_THAT(Calls, SizeIs(1));
|
@@ -177,7 +184,12 @@ declare !dbg !25 void @_Z2g2v() local_unnamed_addr
|
177 | 184 | std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Ctx);
|
178 | 185 | ASSERT_TRUE(M);
|
179 | 186 |
|
180 |
| - auto Calls = extractCallsFromIR(*M); |
| 187 | + auto *F = M->getFunction("_Z3foov"); |
| 188 | + ASSERT_NE(F, nullptr); |
| 189 | + |
| 190 | + TargetLibraryInfoWrapperPass WrapperPass; |
| 191 | + auto &TLI = WrapperPass.getTLI(*F); |
| 192 | + auto Calls = extractCallsFromIR(*M, TLI); |
181 | 193 |
|
182 | 194 | // Expect exactly 4 callers.
|
183 | 195 | ASSERT_THAT(Calls, SizeIs(4));
|
@@ -220,4 +232,70 @@ declare !dbg !25 void @_Z2g2v() local_unnamed_addr
|
220 | 232 | EXPECT_THAT(G3CallSites[1],
|
221 | 233 | Pair(FieldsAre(2U, 3U), IndexedMemProfRecord::getGUID("_Z2g2v")));
|
222 | 234 | }
|
| 235 | + |
| 236 | +TEST(MemProf, ExtractDirectCallsFromIRCallingNew) { |
| 237 | + // The following IR is generated from: |
| 238 | + // |
| 239 | + // int *foo() { |
| 240 | + // return ::new (int); |
| 241 | + // } |
| 242 | + StringRef IR = R"IR( |
| 243 | +define dso_local noundef ptr @_Z3foov() #0 !dbg !10 { |
| 244 | +entry: |
| 245 | + %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) #2, !dbg !13 |
| 246 | + ret ptr %call, !dbg !14 |
| 247 | +} |
| 248 | +
|
| 249 | +; Function Attrs: nobuiltin allocsize(0) |
| 250 | +declare noundef nonnull ptr @_Znwm(i64 noundef) #1 |
| 251 | +
|
| 252 | +attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
| 253 | +attributes #1 = { nobuiltin allocsize(0) "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
| 254 | +attributes #2 = { builtin allocsize(0) } |
| 255 | +
|
| 256 | +!llvm.dbg.cu = !{!0} |
| 257 | +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} |
| 258 | +!llvm.ident = !{!9} |
| 259 | +
|
| 260 | +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, debugInfoForProfiling: true, nameTableKind: None) |
| 261 | +!1 = !DIFile(filename: "foobar.cc", directory: "/") |
| 262 | +!2 = !{i32 7, !"Dwarf Version", i32 5} |
| 263 | +!3 = !{i32 2, !"Debug Info Version", i32 3} |
| 264 | +!4 = !{i32 1, !"wchar_size", i32 4} |
| 265 | +!5 = !{i32 1, !"MemProfProfileFilename", !"memprof.profraw"} |
| 266 | +!6 = !{i32 8, !"PIC Level", i32 2} |
| 267 | +!7 = !{i32 7, !"PIE Level", i32 2} |
| 268 | +!8 = !{i32 7, !"uwtable", i32 2} |
| 269 | +!9 = !{!"clang"} |
| 270 | +!10 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) |
| 271 | +!11 = !DISubroutineType(types: !12) |
| 272 | +!12 = !{} |
| 273 | +!13 = !DILocation(line: 2, column: 10, scope: !10) |
| 274 | +!14 = !DILocation(line: 2, column: 3, scope: !10) |
| 275 | +)IR"; |
| 276 | + |
| 277 | + LLVMContext Ctx; |
| 278 | + SMDiagnostic Err; |
| 279 | + std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Ctx); |
| 280 | + ASSERT_TRUE(M); |
| 281 | + |
| 282 | + auto *F = M->getFunction("_Z3foov"); |
| 283 | + ASSERT_NE(F, nullptr); |
| 284 | + |
| 285 | + TargetLibraryInfoWrapperPass WrapperPass; |
| 286 | + auto &TLI = WrapperPass.getTLI(*F); |
| 287 | + auto Calls = extractCallsFromIR(*M, TLI); |
| 288 | + |
| 289 | + // Expect exactly one caller. |
| 290 | + ASSERT_THAT(Calls, SizeIs(1)); |
| 291 | + |
| 292 | + // Verify each key-value pair. |
| 293 | + |
| 294 | + auto FooIt = Calls.find(IndexedMemProfRecord::getGUID("_Z3foov")); |
| 295 | + ASSERT_NE(FooIt, Calls.end()); |
| 296 | + const auto &[FooCallerGUID, FooCallSites] = *FooIt; |
| 297 | + EXPECT_EQ(FooCallerGUID, IndexedMemProfRecord::getGUID("_Z3foov")); |
| 298 | + ASSERT_THAT(FooCallSites, SizeIs(1)); |
| 299 | + EXPECT_THAT(FooCallSites[0], Pair(FieldsAre(1U, 10U), 0)); |
| 300 | +} |
223 | 301 | } // namespace
|
0 commit comments