| ;; Test that correct clones are generated and reached when we need to |
| ;; re-merge clone nodes before function assignment. |
| ;; |
| ;; The code is similar to that of mergenodes.ll, but with two additional |
| ;; contexts sharing the same two allocations. This tests that we correctly |
| ;; share the merged nodes when possible. |
| |
| ; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \ |
| ;; Disable merge iteration for now as it causes spurious diffs due to different |
| ;; iteration order (but the same ultimate hinting of the contexts). |
| ; RUN: -memprof-merge-iteration=false \ |
| ; RUN: -memprof-verify-ccg -memprof-dump-ccg %s -S 2>&1 | FileCheck %s \ |
| ; RUN: --check-prefix=IR --check-prefix=DUMP |
| |
| target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" |
| target triple = "x86_64-unknown-linux-gnu" |
| |
| define i32 @main() { |
| entry: |
| ;; Ultimately calls bar and allocates notcold memory from first call to new |
| ;; and cold memory from second call to new. |
| %call = call noundef ptr @_Z3foov(), !callsite !0 |
| ;; Ultimately calls bar and allocates cold memory from first call to new |
| ;; and notcold memory from second call to new. |
| %call1 = call noundef ptr @_Z3foov(), !callsite !1 |
| ;; Same allocation pattern as the first call to foo above, should end up |
| ;; sharing the same merge nodes. |
| %call2 = call noundef ptr @_Z3foov(), !callsite !19 |
| ;; Same allocation pattern as the second call to foo above, should end up |
| ;; sharing the same merge nodes. |
| %call3 = call noundef ptr @_Z3foov(), !callsite !20 |
| ret i32 0 |
| } |
| |
| define internal ptr @_Z3barv() { |
| entry: |
| ;; notcold when called from first and third calls to foo from main, cold when |
| ;; called from second and fourth. |
| %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0, !memprof !2, !callsite !7 |
| ;; cold when called from first and third calls to foo from main, notcold when |
| ;; called from second and fourth. |
| %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0, !memprof !13, !callsite !18 |
| ret ptr null |
| } |
| |
| declare ptr @_Znam(i64) |
| |
| define internal ptr @_Z3bazv() { |
| entry: |
| %call = call noundef ptr @_Z3barv(), !callsite !8 |
| ret ptr null |
| } |
| |
| ; Function Attrs: noinline |
| define internal ptr @_Z3foov() { |
| entry: |
| %call = call noundef ptr @_Z3bazv(), !callsite !9 |
| ret ptr null |
| } |
| |
| attributes #0 = { builtin } |
| |
| !0 = !{i64 8632435727821051414} |
| !1 = !{i64 -3421689549917153178} |
| !19 = !{i64 8910} |
| !20 = !{i64 91011} |
| !2 = !{!3, !5, !21, !23} |
| !3 = !{!4, !"notcold"} |
| !4 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 8632435727821051414} |
| !5 = !{!6, !"cold"} |
| !6 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 -3421689549917153178} |
| !21 = !{!22, !"notcold"} |
| !22 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 8910} |
| !23 = !{!24, !"cold"} |
| !24 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 91011} |
| !7 = !{i64 9086428284934609951} |
| !8 = !{i64 -5964873800580613432} |
| !9 = !{i64 2732490490862098848} |
| !13 = !{!14, !16, !25, !27} |
| !14 = !{!15, !"cold"} |
| !15 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 8632435727821051414} |
| !16 = !{!17, !"notcold"} |
| !17 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 -3421689549917153178} |
| !25 = !{!26, !"cold"} |
| !26 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 8910} |
| !27 = !{!28, !"notcold"} |
| !28 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 91011} |
| !18 = !{i64 123} |
| |
| ;; After cloning, each callsite in main calls different clones of foo with |
| ;; different allocaton types, and ditto all the way through the leaf |
| ;; allocation callsites. The single allocation-type clones are shared between |
| ;; the four callsites in main. This would lead to incorrect assignment of |
| ;; the leaf allocations to function clones as is, since we have lost the |
| ;; information that each callsite in main ultimately reaches two allocation |
| ;; callsites with *different* allocation types. |
| ; DUMP: CCG after cloning: |
| ; DUMP: Callsite Context Graph: |
| ; DUMP: Node [[BAR1ALLOC1:0x[a-f0-9]+]] |
| ; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 1 3 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ1:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 1 3 |
| ; DUMP: Clones: [[BAR2ALLOC1:0x[a-f0-9]+]] |
| |
| ; DUMP: Node [[BAZ1]] |
| ; DUMP: %call = call noundef ptr @_Z3barv() (clone 0) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 1 3 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ1]] AllocTypes: NotCold ContextIds: 1 3 |
| ; DUMP: Edge from Callee [[BAR1ALLOC2:0x[a-f0-9]+]] to Caller: [[BAZ1]] AllocTypes: NotCold ContextIds: 6 8 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAZ1]] to Caller: [[FOO1:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 1 3 6 8 |
| ; DUMP: Clones: [[BAZ2:0x[a-f0-9]+]] |
| |
| ; DUMP: Node [[FOO1]] |
| ; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 1 3 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAZ1]] to Caller: [[FOO1]] AllocTypes: NotCold ContextIds: 1 3 6 8 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN1:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 1 |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN3:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 3 |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN2:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 6 |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN4:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 8 |
| ; DUMP: Clones: [[FOO2:0x[a-f0-9]+]] |
| |
| ; DUMP: Node [[MAIN1]] |
| ; DUMP: %call = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 1 5 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN1]] AllocTypes: NotCold ContextIds: 1 |
| ; DUMP: Edge from Callee [[FOO2:0x[a-f0-9]+]] to Caller: [[MAIN1]] AllocTypes: Cold ContextIds: 5 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN2]] |
| ; DUMP: %call1 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 2 6 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN2]] AllocTypes: NotCold ContextIds: 6 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: Cold ContextIds: 2 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN3]] |
| ; DUMP: %call2 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 3 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN3]] AllocTypes: NotCold ContextIds: 3 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN3]] AllocTypes: Cold ContextIds: 7 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN4]] |
| ; DUMP: %call3 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 4 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN4]] AllocTypes: NotCold ContextIds: 8 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN4]] AllocTypes: Cold ContextIds: 4 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[BAR1ALLOC2]] |
| ; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ1]] AllocTypes: NotCold ContextIds: 6 8 |
| ; DUMP: Clones: [[BAR2ALLOC2:0x[a-f0-9]+]] |
| |
| ; DUMP: Node [[FOO2]] |
| ; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 2 4 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO2]] AllocTypes: Cold ContextIds: 2 4 5 7 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: Cold ContextIds: 2 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN4]] AllocTypes: Cold ContextIds: 4 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN1]] AllocTypes: Cold ContextIds: 5 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN3]] AllocTypes: Cold ContextIds: 7 |
| ; DUMP: Clone of [[FOO1]] |
| |
| ; DUMP: Node [[BAZ2]] |
| ; DUMP: %call = call noundef ptr @_Z3barv() (clone 0) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 2 4 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 2 4 |
| ; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 5 7 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO2]] AllocTypes: Cold ContextIds: 2 4 5 7 |
| ; DUMP: Clone of [[BAZ1]] |
| |
| ; DUMP: Node [[BAR2ALLOC1]] |
| ; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 2 4 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 2 4 |
| ; DUMP: Clone of [[BAR1ALLOC1]] |
| |
| ; DUMP: Node [[BAR2ALLOC2]] |
| ; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 5 7 |
| ; DUMP: Clone of [[BAR1ALLOC2]] |
| |
| ;; After merging, each pair of callsites in main with the same allocation |
| ;; pattern call a different single clone of foo with both cold and not cold |
| ;; allocation types, but ultimately reach two single allocation type |
| ;; allocation callsite clones of the correct combination. The graph after |
| ;; assigning function clones is the same, but with function calls updated to |
| ;; the new function clones. |
| ; DUMP: CCG after merging: |
| ; DUMP: Callsite Context Graph: |
| ; DUMP: Node [[BAR1ALLOC1]] |
| ; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 1 3 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1 3 |
| ; DUMP: Clones: [[BAR2ALLOC1]] |
| |
| ; DUMP: Node [[MAIN1]] |
| ; DUMP: %call = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 1 5 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO3:0x[a-f0-9]+]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 5 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN2]] |
| ; DUMP: %call1 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 2 6 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 6 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN3]] |
| ; DUMP: %call2 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 3 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN3]] AllocTypes: NotColdCold ContextIds: 3 7 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN4]] |
| ; DUMP: %call3 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 4 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN4]] AllocTypes: NotColdCold ContextIds: 4 8 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[BAR1ALLOC2]] |
| ; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 6 8 |
| ; DUMP: Clones: [[BAR2ALLOC2]] |
| |
| ; DUMP: Node [[FOO2]] |
| ; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 2 4 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 6 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN4]] AllocTypes: NotColdCold ContextIds: 4 8 |
| ; DUMP: Clone of [[FOO1]] |
| |
| ; DUMP: Node [[BAZ2]] |
| ; DUMP: %call = call noundef ptr @_Z3barv() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 1 3 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 5 7 |
| ; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1 3 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3 5 7 |
| ; DUMP: Clone of [[BAZ1]] |
| |
| ; DUMP: Node [[BAR2ALLOC1]] |
| ; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 2 4 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2 4 |
| ; DUMP: Clone of [[BAR1ALLOC1]] |
| |
| ; DUMP: Node [[BAR2ALLOC2]] |
| ; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 5 7 |
| ; DUMP: Clone of [[BAR1ALLOC2]] |
| |
| ; DUMP: Node [[FOO3]] |
| ; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 1 3 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3 5 7 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 5 |
| ; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN3]] AllocTypes: NotColdCold ContextIds: 3 7 |
| ; DUMP: Clone of [[FOO1]] |
| |
| ; DUMP: Node [[BAZ3]] |
| ; DUMP: %call = call noundef ptr @_Z3barv() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 2 4 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2 4 |
| ; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3]] AllocTypes: NotCold ContextIds: 6 8 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4 6 8 |
| ; DUMP: Clone of [[BAZ1]] |
| |
| ; DUMP: CCG after assigning function clones: |
| ; DUMP: Callsite Context Graph: |
| ; DUMP: Node [[BAR1ALLOC1]] |
| ; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 1 3 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1 3 |
| ; DUMP: Clones: [[BAR2ALLOC1]] |
| |
| ; DUMP: Node [[MAIN1]] |
| ; DUMP: %call = call noundef ptr @_Z3foov.memprof.1() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 1 5 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 5 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN2]] |
| ; DUMP: %call1 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 2 6 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 6 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN3]] |
| ; DUMP: %call2 = call noundef ptr @_Z3foov.memprof.1() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 3 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN3]] AllocTypes: NotColdCold ContextIds: 3 7 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[MAIN4]] |
| ; DUMP: %call3 = call noundef ptr @_Z3foov() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 4 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN4]] AllocTypes: NotColdCold ContextIds: 4 8 |
| ; DUMP: CallerEdges: |
| |
| ; DUMP: Node [[BAR1ALLOC2]] |
| ; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #1 (clone 1) |
| ; DUMP: AllocTypes: NotCold |
| ; DUMP: ContextIds: 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3]] AllocTypes: NotCold ContextIds: 6 8 |
| ; DUMP: Clones: [[BAR2ALLOC2]] |
| |
| ; DUMP: Node [[FOO2]] |
| ; DUMP: %call = call noundef ptr @_Z3bazv.memprof.1() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 2 4 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 6 |
| ; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN4]] AllocTypes: NotColdCold ContextIds: 4 8 |
| ; DUMP: Clone of [[FOO1]] |
| |
| ; DUMP: Node [[BAZ2]] |
| ; DUMP: %call = call noundef ptr @_Z3barv() (clone 0) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 1 3 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 5 7 |
| ; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1 3 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3 5 7 |
| ; DUMP: Clone of [[BAZ1]] |
| |
| ; DUMP: Node [[BAR2ALLOC1]] |
| ; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 1) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 2 4 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2 4 |
| ; DUMP: Clone of [[BAR1ALLOC1]] |
| |
| ; DUMP: Node [[BAR2ALLOC2]] |
| ; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #1 (clone 0) |
| ; DUMP: AllocTypes: Cold |
| ; DUMP: ContextIds: 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 5 7 |
| ; DUMP: Clone of [[BAR1ALLOC2]] |
| |
| ; DUMP: Node [[FOO3]] |
| ; DUMP: %call = call noundef ptr @_Z3bazv() (clone 1) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 1 3 5 7 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3 5 7 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 5 |
| ; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN3]] AllocTypes: NotColdCold ContextIds: 3 7 |
| ; DUMP: Clone of [[FOO1]] |
| |
| ; DUMP: Node [[BAZ3]] |
| ; DUMP: %call = call noundef ptr @_Z3barv.memprof.1() (clone 1) |
| ; DUMP: AllocTypes: NotColdCold |
| ; DUMP: ContextIds: 2 4 6 8 |
| ; DUMP: CalleeEdges: |
| ; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2 4 |
| ; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3]] AllocTypes: NotCold ContextIds: 6 8 |
| ; DUMP: CallerEdges: |
| ; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4 6 8 |
| ; DUMP: Clone of [[BAZ1]] |
| |
| ; IR: define {{.*}} @main |
| ;; The first call to foo should now call foo.memprof.1 that ultimately |
| ;; calls bar with the first allocation hinted notcold and the second cold |
| ;; (via call chain foo.memprof.1 -> baz -> bar). |
| ; IR: call {{.*}} @_Z3foov.memprof.1() |
| ;; The second call to foo still calls the original foo, but ultimately |
| ;; reaches a clone of bar with the first allocation hinted cold and the |
| ;; second notcold. |
| ; IR: call {{.*}} @_Z3foov() |
| ; IR: define internal {{.*}} @_Z3barv() |
| ; IR: call {{.*}} @_Znam(i64 noundef 10) #[[NOTCOLD:[0-9]+]] |
| ; IR: call {{.*}} @_Znam(i64 noundef 10) #[[COLD:[0-9]+]] |
| ; IR: define internal {{.*}} @_Z3bazv() |
| ; IR: call {{.*}} @_Z3barv() |
| ; IR: define internal {{.*}} @_Z3foov() |
| ; IR: call {{.*}} @_Z3bazv.memprof.1() |
| ; IR: define internal {{.*}} @_Z3barv.memprof.1() |
| ; IR: call {{.*}} @_Znam(i64 noundef 10) #[[COLD]] |
| ; IR: call {{.*}} @_Znam(i64 noundef 10) #[[NOTCOLD]] |
| ; IR: define internal {{.*}} @_Z3bazv.memprof.1() |
| ; IR: call {{.*}} @_Z3barv.memprof.1() |
| ; IR: define internal {{.*}} @_Z3foov.memprof.1() |
| ; IR: call {{.*}} @_Z3bazv() |
| ; IR: attributes #[[NOTCOLD]] = { builtin "memprof"="notcold" } |
| ; IR: attributes #[[COLD]] = { builtin "memprof"="cold" } |