1; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s 2 3 4@gvar = external global i32 5 6; dupbb has two predecessors, p1 and p2. p1 is hot, p2 is cold. So dupbb 7; should be placed after p1, and not duplicated into p2. 8; 9; CHECK-LABEL: test1 10; CHECK: %p1 11; CHECK: .LBB0_4: # %dupbb 12; CHECK: %p2 13; CHECK: jmp .LBB0_4 14 15define void @test1(i32* %p) !prof !1 { 16entry: 17 br label %header 18 19header: 20 %call = call zeroext i1 @a() 21 br i1 %call, label %p1, label %p2, !prof !2 22 23p1: 24 call void @b() 25 br label %dupbb 26 27p2: 28 call void @c() 29 br label %dupbb 30 31dupbb: 32 %cond = icmp eq i32* @gvar, %p 33 br i1 %cond, label %header, label %latch, !prof !3 34 35latch: 36 %call3 = call zeroext i1 @a() 37 br i1 %call3, label %header, label %end, !prof !2 38 39end: 40 ret void 41} 42 43 44; dupbb has four predecessors p1, p2, p3 and p4. p1 and p2 are hot, p3 and p4 45; are cold. So dupbb should be placed after p1, duplicated into p2. p3 and p4 46; should jump to dupbb. 47; 48; CHECK-LABEL: test2 49; CHECK: %p1 50; CHECK: .LBB1_8: # %dupbb 51; 52; CHECK: %p2 53; CHECK: callq c 54; CHECK-NEXT: cmpq 55; CHECK-NEXT: je 56; CHECK-NEXT: jmp 57; 58; CHECK: %p3 59; CHECK: jmp .LBB1_8 60; CHECK: %p4 61; CHECK: jmp .LBB1_8 62 63define void @test2(i32* %p) !prof !1 { 64entry: 65 br label %header 66 67header: 68 %call = call zeroext i1 @a() 69 br i1 %call, label %bb1, label %bb2, !prof !2 70 71bb1: 72 %call1 = call zeroext i1 @a() 73 br i1 %call1, label %p1, label %p2, !prof !4 74 75bb2: 76 %call2 = call zeroext i1 @a() 77 br i1 %call2, label %p3, label %p4, !prof !4 78 79p1: 80 call void @b() 81 br label %dupbb 82 83p2: 84 call void @c() 85 br label %dupbb 86 87p3: 88 call void @d() 89 br label %dupbb 90 91p4: 92 call void @e() 93 br label %dupbb 94 95dupbb: 96 %cond = icmp eq i32* @gvar, %p 97 br i1 %cond, label %bb3, label %bb4, !prof !4 98 99bb3: 100 call void @b() 101 br label %bb4 102 103bb4: 104 %call4 = call zeroext i1 @a() 105 br i1 %call4, label %header, label %latch, !prof !3 106 107latch: 108 %call3 = call zeroext i1 @a() 109 br i1 %call3, label %header, label %end, !prof !2 110 111end: 112 ret void 113} 114 115 116; dupbb has three predecessors p1, p2 and p3. p3 has two successors, so dupbb 117; can't be duplicated into p3, but it should not block it to be duplicated into 118; other predecessors. 119; 120; CHECK-LABEL: test3 121; CHECK: %p1 122; CHECK: .LBB2_6: # %dupbb 123; 124; CHECK: %p2 125; CHECK: callq c 126; CHECK: cmpq 127; CHECK-NEXT: je 128; CHECK-NEXT: jmp 129; 130; CHECK: %p3 131; CHECK: jne .LBB2_6 132 133define void @test3(i32* %p) !prof !1 { 134entry: 135 br label %header 136 137header: 138 %call = call zeroext i1 @a() 139 br i1 %call, label %bb1, label %p3, !prof !2 140 141bb1: 142 %call1 = call zeroext i1 @a() 143 br i1 %call1, label %p1, label %p2, !prof !4 144 145p1: 146 call void @b() 147 br label %dupbb 148 149p2: 150 call void @c() 151 br label %dupbb 152 153p3: 154 %call2 = call zeroext i1 @a() 155 br i1 %call2, label %dupbb, label %bb4, !prof !4 156 157dupbb: 158 %cond = icmp eq i32* @gvar, %p 159 br i1 %cond, label %bb3, label %bb4, !prof !4 160 161bb3: 162 call void @b() 163 br label %bb4 164 165bb4: 166 %call4 = call zeroext i1 @a() 167 br i1 %call4, label %header, label %latch, !prof !3 168 169latch: 170 %call3 = call zeroext i1 @a() 171 br i1 %call3, label %header, label %end, !prof !2 172 173end: 174 ret void 175} 176 177declare zeroext i1 @a() 178declare void @b() 179declare void @c() 180declare void @d() 181declare void @e() 182declare void @f() 183 184!1 = !{!"function_entry_count", i64 1000} 185!2 = !{!"branch_weights", i32 100, i32 1} 186!3 = !{!"branch_weights", i32 1, i32 100} 187!4 = !{!"branch_weights", i32 60, i32 40} 188