1; RUN: opt -S -passes='function(lower-expect),strip-dead-prototypes' -likely-branch-weight=2147483647 -unlikely-branch-weight=1 < %s | FileCheck %s 2 3; The C case 4; if (__builtin_expect_with_probability(((a0 == 1) || (a1 == 1) || (a2 == 1)), 1, 0)) 5; For the above case, all 3 branches should be annotated 6; which should be equivalent to if (__builtin_expect(((a0 == 1) || (a1 == 1) || (a2 == 1)), 0)) 7 8; The C case 9; if (__builtin_expect_with_probability(((a0 == 1) || (a1 == 1) || (a2 == 1)), 1, 1)) 10; For the above case, we do not have enough information, so only the last branch could be annotated 11; which should be equivalent to if (__builtin_expect(((a0 == 1) || (a1 == 1) || (a2 == 1)), 1)) 12 13declare void @foo() 14 15declare i64 @llvm.expect.i64(i64, i64) nounwind readnone 16declare i64 @llvm.expect.with.probability.i64(i64, i64, double) nounwind readnone 17 18; CHECK-LABEL: @test1_expect_1( 19; CHECK: block0: 20; CHECK-NOT: prof 21; CHECK: block1: 22; CHECK-NOT: prof 23; CHECK: block3: 24; CHECK: br i1 %tobool, label %block4, label %block5, !prof !0 25define void @test1_expect_1(i8 %a0, i8 %a1, i8 %a2) { 26block0: 27 %c0 = icmp eq i8 %a0, 1 28 br i1 %c0, label %block3, label %block1 29 30block1: 31 %c1 = icmp eq i8 %a1, 1 32 br i1 %c1, label %block3, label %block2 33 34block2: 35 %c2 = icmp eq i8 %a2, 1 36 br label %block3 37 38block3: 39 %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ] 40 %cond1 = zext i1 %cond0 to i32 41 %cond2 = sext i32 %cond1 to i64 42 %expval = call i64 @llvm.expect.i64(i64 %cond2, i64 1) 43 %tobool = icmp ne i64 %expval, 0 44 br i1 %tobool, label %block4, label %block5 45 46block4: 47 call void @foo() 48 br label %block5 49 50block5: 51 ret void 52} 53 54; should have exactly the same behavior as test1 55; CHECK-LABEL: @test2_expect_with_prob_1_1( 56; CHECK: block0: 57; CHECK-NOT: prof 58; CHECK: block1: 59; CHECK-NOT: prof 60; CHECK: block3: 61; CHECK: br i1 %tobool, label %block4, label %block5, !prof !0 62define void @test2_expect_with_prob_1_1(i8 %a0, i8 %a1, i8 %a2) { 63block0: 64 %c0 = icmp eq i8 %a0, 1 65 br i1 %c0, label %block3, label %block1 66 67block1: 68 %c1 = icmp eq i8 %a1, 1 69 br i1 %c1, label %block3, label %block2 70 71block2: 72 %c2 = icmp eq i8 %a2, 1 73 br label %block3 74 75block3: 76 %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ] 77 %cond1 = zext i1 %cond0 to i32 78 %cond2 = sext i32 %cond1 to i64 79 %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 1, double 1.0) 80 %tobool = icmp ne i64 %expval, 0 81 br i1 %tobool, label %block4, label %block5 82 83block4: 84 call void @foo() 85 br label %block5 86 87block5: 88 ret void 89} 90 91; should have exactly the same behavior as test1 92; CHECK-LABEL: @test3_expect_with_prob_0_0( 93; CHECK: block0: 94; CHECK-NOT: prof 95; CHECK: block1: 96; CHECK-NOT: prof 97; CHECK: block3: 98; CHECK: br i1 %tobool, label %block4, label %block5, !prof !0 99define void @test3_expect_with_prob_0_0(i8 %a0, i8 %a1, i8 %a2) { 100block0: 101 %c0 = icmp eq i8 %a0, 1 102 br i1 %c0, label %block3, label %block1 103 104block1: 105 %c1 = icmp eq i8 %a1, 1 106 br i1 %c1, label %block3, label %block2 107 108block2: 109 %c2 = icmp eq i8 %a2, 1 110 br label %block3 111 112block3: 113 %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ] 114 %cond1 = zext i1 %cond0 to i32 115 %cond2 = sext i32 %cond1 to i64 116 %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 0, double 0.0) 117 %tobool = icmp ne i64 %expval, 0 118 br i1 %tobool, label %block4, label %block5 119 120block4: 121 call void @foo() 122 br label %block5 123 124block5: 125 ret void 126} 127 128; CHECK-LABEL: @test4_expect_0( 129; CHECK: block0: 130; CHECK: br i1 %c0, label %block3, label %block1, !prof !1 131; CHECK: block1: 132; CHECK: br i1 %c1, label %block3, label %block2, !prof !1 133; CHECK: block3: 134; CHECK: br i1 %tobool, label %block4, label %block5, !prof !1 135define void @test4_expect_0(i8 %a0, i8 %a1, i8 %a2) { 136block0: 137 %c0 = icmp eq i8 %a0, 1 138 br i1 %c0, label %block3, label %block1 139 140block1: 141 %c1 = icmp eq i8 %a1, 1 142 br i1 %c1, label %block3, label %block2 143 144block2: 145 %c2 = icmp eq i8 %a2, 1 146 br label %block3 147 148block3: 149 %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ] 150 %cond1 = zext i1 %cond0 to i32 151 %cond2 = sext i32 %cond1 to i64 152 %expval = call i64 @llvm.expect.i64(i64 %cond2, i64 0) 153 %tobool = icmp ne i64 %expval, 0 154 br i1 %tobool, label %block4, label %block5 155 156block4: 157 call void @foo() 158 br label %block5 159 160block5: 161 ret void 162} 163 164; should have exactly the same behavior as test4 165; CHECK-LABEL: @test5_expect_with_prob_1_0( 166; CHECK: block0: 167; CHECK: br i1 %c0, label %block3, label %block1, !prof !1 168; CHECK: block1: 169; CHECK: br i1 %c1, label %block3, label %block2, !prof !1 170; CHECK: block3: 171; CHECK: br i1 %tobool, label %block4, label %block5, !prof !1 172define void @test5_expect_with_prob_1_0(i8 %a0, i8 %a1, i8 %a2) { 173block0: 174 %c0 = icmp eq i8 %a0, 1 175 br i1 %c0, label %block3, label %block1 176 177block1: 178 %c1 = icmp eq i8 %a1, 1 179 br i1 %c1, label %block3, label %block2 180 181block2: 182 %c2 = icmp eq i8 %a2, 1 183 br label %block3 184 185block3: 186 %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ] 187 %cond1 = zext i1 %cond0 to i32 188 %cond2 = sext i32 %cond1 to i64 189 %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 1, double 0.0) 190 %tobool = icmp ne i64 %expval, 0 191 br i1 %tobool, label %block4, label %block5 192 193block4: 194 call void @foo() 195 br label %block5 196 197block5: 198 ret void 199} 200 201; should have exactly the same behavior as test4 202; CHECK-LABEL: @test6_expect_with_prob_0_1( 203; CHECK: block0: 204; CHECK: br i1 %c0, label %block3, label %block1, !prof !1 205; CHECK: block1: 206; CHECK: br i1 %c1, label %block3, label %block2, !prof !1 207; CHECK: block3: 208; CHECK: br i1 %tobool, label %block4, label %block5, !prof !1 209define void @test6_expect_with_prob_0_1(i8 %a0, i8 %a1, i8 %a2) { 210block0: 211 %c0 = icmp eq i8 %a0, 1 212 br i1 %c0, label %block3, label %block1 213 214block1: 215 %c1 = icmp eq i8 %a1, 1 216 br i1 %c1, label %block3, label %block2 217 218block2: 219 %c2 = icmp eq i8 %a2, 1 220 br label %block3 221 222block3: 223 %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ] 224 %cond1 = zext i1 %cond0 to i32 225 %cond2 = sext i32 %cond1 to i64 226 %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 0, double 1.0) 227 %tobool = icmp ne i64 %expval, 0 228 br i1 %tobool, label %block4, label %block5 229 230block4: 231 call void @foo() 232 br label %block5 233 234block5: 235 ret void 236} 237 238; CHECK: !0 = !{!"branch_weights", !"expected", i32 2147483647, i32 1} 239; CHECK: !1 = !{!"branch_weights", !"expected", i32 1, i32 2147483647} 240