1; REQUIRES: x86_64-linux 2; RUN: rm -rf %t 3; RUN: split-file %s %t 4; RUN: llvm-ctxprof-util fromYAML --input=%t/profile.yaml --output=%t/profile.ctxprofdata 5 6; RUN: opt -passes='module-inline,print<ctx-prof-analysis>' -ctx-profile-printer-level=everything %t/module.ll -S \ 7; RUN: -use-ctx-profile=%t/profile.ctxprofdata -ctx-profile-printer-level=yaml \ 8; RUN: -o - 2> %t/profile-final.yaml | FileCheck %s 9; RUN: diff %t/profile-final.yaml %t/expected.yaml 10 11; There are 2 calls to @a from @entrypoint. We only inline the one callsite 12; marked as alwaysinline, the rest are blocked (marked noinline). After the inline, 13; the updated contextual profile should still have the same tree for the non-inlined case. 14; For the inlined case, we should observe, for the @entrypoint context: 15; - an empty callsite where the inlined one was (first one, i.e. 0) 16; - more counters appended to the old counter list (because we ingested the 17; ones from @a). The values are copied. 18; - a new callsite to @b 19; CHECK-LABEL: @entrypoint 20; CHECK-LABEL: yes: 21; CHECK: call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 1) 22; CHECK-NEXT: br label %loop.i 23; CHECK-LABEL: loop.i: 24; CHECK-NEXT: %indvar.i = phi i32 [ %indvar.next.i, %loop.i ], [ 0, %yes ] 25; CHECK-NEXT: call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 2, i32 3) 26; CHECK-NEXT: %b.i = add i32 %x, %indvar.i 27; CHECK-NEXT: call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 1, i32 2, ptr @b) 28; CHECK-NEXT: %call3.i = call i32 @b() #1 29; CHECK-LABEL: no: 30; CHECK-NEXT: call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 2) 31; CHECK-NEXT: call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 2, i32 1, ptr @a) 32; CHECK-NEXT: %call2 = call i32 @a(i32 %x) #1 33; CHECK-NEXT: br label %exit 34 35; Make sure the postlink thinlto pipeline is aware of ctxprof 36; RUN: opt -passes='thinlto<O2>' -use-ctx-profile=%t/profile.ctxprofdata \ 37; RUN: %t/module.ll -S -o - | FileCheck %s --check-prefix=PIPELINE 38 39; PIPELINE-LABEL: define i32 @entrypoint 40; PIPELINE-SAME: !prof ![[ENTRYPOINT_COUNT:[0-9]+]] 41; PIPELINE-LABEL: loop.i: 42; PIPELINE: br i1 %cond.i, label %loop.i, label %exit, !prof ![[LOOP_BW_INL:[0-9]+]] 43; PIPELINE-LABEL: define i32 @a 44; PIPELINE-LABEL: loop: 45; PIPELINE: br i1 %cond, label %loop, label %exit, !prof ![[LOOP_BW_ORIG:[0-9]+]] 46 47; PIPELINE: ![[ENTRYPOINT_COUNT]] = !{!"function_entry_count", i64 10} 48; These are the weights of the inlined @a, where the counters were 2, 100 (2 for entry, 100 for loop) 49; PIPELINE: ![[LOOP_BW_INL]] = !{!"branch_weights", i32 98, i32 2} 50; These are the weights of the un-inlined @a, where the counters were 8, 500 (8 for entry, 500 for loop) 51; PIPELINE: ![[LOOP_BW_ORIG]] = !{!"branch_weights", i32 492, i32 8} 52 53;--- module.ll 54define i32 @entrypoint(i32 %x) !guid !0 { 55 call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 0) 56 %t = icmp eq i32 %x, 0 57 br i1 %t, label %yes, label %no 58yes: 59 call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 1) 60 call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 2, i32 0, ptr @a) 61 %call1 = call i32 @a(i32 %x) alwaysinline 62 br label %exit 63no: 64 call void @llvm.instrprof.increment(ptr @entrypoint, i64 0, i32 3, i32 2) 65 call void @llvm.instrprof.callsite(ptr @entrypoint, i64 0, i32 2, i32 1, ptr @a) 66 %call2 = call i32 @a(i32 %x) noinline 67 br label %exit 68exit: 69 %ret = phi i32 [%call1, %yes], [%call2, %no] 70 ret i32 %ret 71} 72 73define i32 @a(i32 %x) !guid !1 { 74entry: 75 call void @llvm.instrprof.increment(ptr @a, i64 0, i32 2, i32 0) 76 br label %loop 77loop: 78 %indvar = phi i32 [%indvar.next, %loop], [0, %entry] 79 call void @llvm.instrprof.increment(ptr @a, i64 0, i32 2, i32 1) 80 %b = add i32 %x, %indvar 81 call void @llvm.instrprof.callsite(ptr @a, i64 0, i32 1, i32 0, ptr @b) 82 %call3 = call i32 @b() noinline 83 %indvar.next = add i32 %indvar, %call3 84 %cond = icmp slt i32 %indvar.next, %x 85 br i1 %cond, label %loop, label %exit 86exit: 87 ret i32 8 88} 89 90define i32 @b() !guid !2 { 91 call void @llvm.instrprof.increment(ptr @b, i64 0, i32 1, i32 0) 92 ret i32 1 93} 94 95!0 = !{i64 1000} 96!1 = !{i64 1001} 97!2 = !{i64 1002} 98;--- profile.yaml 99- Guid: 1000 100 Counters: [10, 2, 8] 101 Callsites: - 102 - Guid: 1001 103 Counters: [2, 100] 104 Callsites: - 105 - Guid: 1002 106 Counters: [100] 107 - 108 - Guid: 1001 109 Counters: [8, 500] 110 Callsites: - 111 - Guid: 1002 112 Counters: [500] 113;--- expected.yaml 114 115- Guid: 1000 116 Counters: [ 10, 2, 8, 100 ] 117 Callsites: 118 - [ ] 119 - - Guid: 1001 120 Counters: [ 8, 500 ] 121 Callsites: 122 - - Guid: 1002 123 Counters: [ 500 ] 124 - - Guid: 1002 125 Counters: [ 100 ] 126