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