1*f061b131SAdityaK; Check that the unlikely branch is outlined. Override internal branch thresholds with -hotcoldsplit-cold-probability-denom 2*f061b131SAdityaK 3*f061b131SAdityaK; RUN: opt -S -passes=hotcoldsplit < %s | FileCheck %s --check-prefixes=CHECK-OUTLINE,CHECK-NOOUTLINE-BAZ 4*f061b131SAdityaK; RUN: opt -S -passes=hotcoldsplit -hotcoldsplit-cold-probability-denom=50 < %s | FileCheck --check-prefixes=CHECK-OUTLINE,CHECK-PROB %s 5*f061b131SAdityaK 6*f061b131SAdityaK; int cold(const char*); 7*f061b131SAdityaK; int hot(const char*); 8*f061b131SAdityaK; void foo(int a, int b) { 9*f061b131SAdityaK; if (a == b) [[unlikely]] { // Should be outlined. 10*f061b131SAdityaK; cold("same"); 11*f061b131SAdityaK; cold("same"); 12*f061b131SAdityaK; } else { 13*f061b131SAdityaK; hot("different"); 14*f061b131SAdityaK; } 15*f061b131SAdityaK; } 16*f061b131SAdityaK 17*f061b131SAdityaK; void bar(int a, int b) { 18*f061b131SAdityaK; if (a == b) [[likely]] { 19*f061b131SAdityaK; hot("same"); 20*f061b131SAdityaK; } else { // Should be outlined. 21*f061b131SAdityaK; cold("different"); 22*f061b131SAdityaK; cold("different"); 23*f061b131SAdityaK; } 24*f061b131SAdityaK; } 25*f061b131SAdityaK 26*f061b131SAdityaK; void baz(int a, int b) { 27*f061b131SAdityaK; if (a == b) [[likely]] { 28*f061b131SAdityaK; hot("same"); 29*f061b131SAdityaK; } else { // Should be outlined. 30*f061b131SAdityaK; cold("different"); 31*f061b131SAdityaK; cold("different"); 32*f061b131SAdityaK; } 33*f061b131SAdityaK; } 34*f061b131SAdityaK 35*f061b131SAdityaK; All the outlined cold functions are emitted after the hot functions. 36*f061b131SAdityaK; CHECK-OUTLINE: @foo 37*f061b131SAdityaK; CHECK-OUTLINE: @bar 38*f061b131SAdityaK; CHECK-OUTLINE: @baz 39*f061b131SAdityaK 40*f061b131SAdityaK; CHECK-OUTLINE: internal void @foo.cold.1() #[[ATTR0:[0-9]+]] 41*f061b131SAdityaK; CHECK-OUTLINE-NEXT: newFuncRoot 42*f061b131SAdityaK; CHECK-OUTLINE: tail call noundef i32 @cold 43*f061b131SAdityaK; CHECK-OUTLINE: tail call noundef i32 @cold 44*f061b131SAdityaK 45*f061b131SAdityaK; CHECK-OUTLINE: internal void @bar.cold.1() #[[ATTR0:[0-9]+]] 46*f061b131SAdityaK; CHECK-OUTLINE-NEXT: newFuncRoot 47*f061b131SAdityaK; CHECK-OUTLINE: tail call noundef i32 @cold 48*f061b131SAdityaK; CHECK-OUTLINE: tail call noundef i32 @cold 49*f061b131SAdityaK 50*f061b131SAdityaK; CHECK-NOOUTLINE-BAZ-NOT: internal void @baz.cold.1() 51*f061b131SAdityaK 52*f061b131SAdityaK; CHECK-PROB: internal void @baz.cold.1() #[[ATTR0:[0-9]+]] 53*f061b131SAdityaK; CHECK-PROB-NEXT: newFuncRoot 54*f061b131SAdityaK; CHECK-PROB: tail call noundef i32 @cold 55*f061b131SAdityaK; CHECK-PROB: tail call noundef i32 @cold 56*f061b131SAdityaK; CHECK-OUTLINE: attributes #[[ATTR0]] = { cold minsize } 57*f061b131SAdityaK 58*f061b131SAdityaKsource_filename = "/app/example.cpp" 59*f061b131SAdityaKtarget datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 60*f061b131SAdityaKtarget triple = "x86_64-unknown-linux-gnu" 61*f061b131SAdityaK 62*f061b131SAdityaK@.str = private unnamed_addr constant [5 x i8] c"same\00", align 1 63*f061b131SAdityaK@.str.1 = private unnamed_addr constant [10 x i8] c"different\00", align 1 64*f061b131SAdityaK 65*f061b131SAdityaKdefine dso_local void @foo(i32 noundef %a, i32 noundef %b) local_unnamed_addr { 66*f061b131SAdityaKentry: 67*f061b131SAdityaK %cmp = icmp eq i32 %a, %b 68*f061b131SAdityaK br i1 %cmp, label %if.then, label %if.else, !prof !1 69*f061b131SAdityaK 70*f061b131SAdityaKif.then: 71*f061b131SAdityaK %call = tail call noundef i32 @cold(ptr noundef nonnull @.str) 72*f061b131SAdityaK %call1 = tail call noundef i32 @cold(ptr noundef nonnull @.str) 73*f061b131SAdityaK br label %if.end 74*f061b131SAdityaK 75*f061b131SAdityaKif.else: 76*f061b131SAdityaK %call2 = tail call noundef i32 @hot(ptr noundef nonnull @.str.1) 77*f061b131SAdityaK br label %if.end 78*f061b131SAdityaK 79*f061b131SAdityaKif.end: 80*f061b131SAdityaK ret void 81*f061b131SAdityaK} 82*f061b131SAdityaK 83*f061b131SAdityaKdeclare noundef i32 @cold(ptr noundef) local_unnamed_addr #1 84*f061b131SAdityaK 85*f061b131SAdityaKdeclare noundef i32 @hot(ptr noundef) local_unnamed_addr #1 86*f061b131SAdityaK 87*f061b131SAdityaKdefine dso_local void @bar(i32 noundef %a, i32 noundef %b) local_unnamed_addr { 88*f061b131SAdityaKentry: 89*f061b131SAdityaK %cmp = icmp eq i32 %a, %b 90*f061b131SAdityaK br i1 %cmp, label %if.then, label %if.else, !prof !2 91*f061b131SAdityaK 92*f061b131SAdityaKif.then: 93*f061b131SAdityaK %call = tail call noundef i32 @hot(ptr noundef nonnull @.str) 94*f061b131SAdityaK br label %if.end 95*f061b131SAdityaK 96*f061b131SAdityaKif.else: 97*f061b131SAdityaK %call1 = tail call noundef i32 @cold(ptr noundef nonnull @.str.1) 98*f061b131SAdityaK %call2 = tail call noundef i32 @cold(ptr noundef nonnull @.str.1) 99*f061b131SAdityaK br label %if.end 100*f061b131SAdityaK 101*f061b131SAdityaKif.end: 102*f061b131SAdityaK ret void 103*f061b131SAdityaK} 104*f061b131SAdityaK 105*f061b131SAdityaKdefine dso_local void @baz(i32 noundef %a, i32 noundef %b) local_unnamed_addr { 106*f061b131SAdityaKentry: 107*f061b131SAdityaK %cmp = icmp eq i32 %a, %b 108*f061b131SAdityaK br i1 %cmp, label %if.then, label %if.else, !prof !3 109*f061b131SAdityaK 110*f061b131SAdityaKif.then: 111*f061b131SAdityaK %call = tail call noundef i32 @hot(ptr noundef nonnull @.str) 112*f061b131SAdityaK br label %if.end 113*f061b131SAdityaK 114*f061b131SAdityaKif.else: 115*f061b131SAdityaK %call1 = tail call noundef i32 @cold(ptr noundef nonnull @.str.1) 116*f061b131SAdityaK %call2 = tail call noundef i32 @cold(ptr noundef nonnull @.str.1) 117*f061b131SAdityaK br label %if.end 118*f061b131SAdityaK 119*f061b131SAdityaKif.end: 120*f061b131SAdityaK ret void 121*f061b131SAdityaK} 122*f061b131SAdityaK 123*f061b131SAdityaK!1 = !{!"branch_weights", i32 1, i32 2000} 124*f061b131SAdityaK!2 = !{!"branch_weights", i32 2000, i32 1} 125*f061b131SAdityaK!3 = !{!"branch_weights", i32 50, i32 1} 126