1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4declare void @use(i1) 5 6; Check that we fold the condition of branches of the 7; form: br <condition> dest1, dest2, where dest1 == dest2. 8define i32 @test(i32 %x) { 9; CHECK-LABEL: @test( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: br i1 false, label [[MERGE:%.*]], label [[MERGE]] 12; CHECK: merge: 13; CHECK-NEXT: ret i32 [[X:%.*]] 14; 15entry: 16 %cmp = icmp ult i32 %x, 7 17 br i1 %cmp, label %merge, label %merge 18merge: 19 ret i32 %x 20} 21 22@global = global i8 0 23 24define i32 @pat(i32 %x) { 25; CHECK-LABEL: @pat( 26; CHECK-NEXT: br i1 false, label [[PATATINO:%.*]], label [[PATATINO]] 27; CHECK: patatino: 28; CHECK-NEXT: ret i32 [[X:%.*]] 29; 30 %y = icmp eq i32 27, ptrtoint(ptr @global to i32) 31 br i1 %y, label %patatino, label %patatino 32patatino: 33 ret i32 %x 34} 35 36define i1 @test01(i1 %cond) { 37; CHECK-LABEL: @test01( 38; CHECK-NEXT: entry: 39; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]] 40; CHECK: if.true.1: 41; CHECK-NEXT: br label [[MERGE_1:%.*]] 42; CHECK: if.false.1: 43; CHECK-NEXT: br label [[MERGE_1]] 44; CHECK: merge.1: 45; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]] 46; CHECK: if.true.2: 47; CHECK-NEXT: br label [[MERGE_2:%.*]] 48; CHECK: if.false.2: 49; CHECK-NEXT: br label [[MERGE_2]] 50; CHECK: merge.2: 51; CHECK-NEXT: ret i1 [[COND]] 52; 53entry: 54 br i1 %cond, label %if.true.1, label %if.false.1 55 56if.true.1: 57 br label %merge.1 58 59if.false.1: 60 br label %merge.1 61 62merge.1: 63 %merge.cond.1 = phi i1 [true, %if.true.1], [false, %if.false.1] 64 br i1 %merge.cond.1, label %if.true.2, label %if.false.2 65 66if.true.2: 67 br label %merge.2 68 69if.false.2: 70 br label %merge.2 71 72merge.2: 73 %merge.cond.2 = phi i1 [true, %if.true.2], [false, %if.false.2] 74 ret i1 %merge.cond.2 75} 76 77define i1 @test02(i1 %cond) { 78; CHECK-LABEL: @test02( 79; CHECK-NEXT: entry: 80; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]] 81; CHECK: if.true.1: 82; CHECK-NEXT: br label [[MERGE_1:%.*]] 83; CHECK: if.false.1: 84; CHECK-NEXT: br label [[MERGE_1]] 85; CHECK: merge.1: 86; CHECK-NEXT: br i1 [[COND]], label [[IF_FALSE_2:%.*]], label [[IF_TRUE_2:%.*]] 87; CHECK: if.true.2: 88; CHECK-NEXT: br label [[MERGE_2:%.*]] 89; CHECK: if.false.2: 90; CHECK-NEXT: br label [[MERGE_2]] 91; CHECK: merge.2: 92; CHECK-NEXT: ret i1 [[COND]] 93; 94entry: 95 br i1 %cond, label %if.true.1, label %if.false.1 96 97if.true.1: 98 br label %merge.1 99 100if.false.1: 101 br label %merge.1 102 103merge.1: 104 %merge.cond.1 = phi i1 [false, %if.true.1], [true, %if.false.1] 105 br i1 %merge.cond.1, label %if.true.2, label %if.false.2 106 107if.true.2: 108 br label %merge.2 109 110if.false.2: 111 br label %merge.2 112 113merge.2: 114 %merge.cond.2 = phi i1 [false, %if.true.2], [true, %if.false.2] 115 ret i1 %merge.cond.2 116} 117 118; if (x && !y) ret 42; ret 3 --> if (!x || y) ret 3; ret 42 119 120define i32 @logical_and_not(i1 %x, i1 %y) { 121; CHECK-LABEL: @logical_and_not( 122; CHECK-NEXT: entry: 123; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true 124; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]] 125; CHECK-NEXT: br i1 [[TMP0]], label [[F:%.*]], label [[T:%.*]] 126; CHECK: t: 127; CHECK-NEXT: ret i32 42 128; CHECK: f: 129; CHECK-NEXT: ret i32 3 130; 131entry: 132 %noty = xor i1 %y, true 133 %and = select i1 %x, i1 %noty, i1 false 134 br i1 %and, label %t, label %f 135 136t: 137 ret i32 42 138 139f: 140 ret i32 3 141} 142 143; if (x && y || !x) ret 3; ret 42 --> if (!x || y) ret 3; ret 42 144 145define i32 @logical_and_or(i1 %x, i1 %y) { 146; CHECK-LABEL: @logical_and_or( 147; CHECK-NEXT: entry: 148; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true 149; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]] 150; CHECK-NEXT: br i1 [[AND]], label [[F:%.*]], label [[T:%.*]] 151; CHECK: t: 152; CHECK-NEXT: ret i32 42 153; CHECK: f: 154; CHECK-NEXT: ret i32 3 155; 156entry: 157 %and = select i1 %x, i1 %y, i1 true 158 br i1 %and, label %f, label %t 159 160t: 161 ret i32 42 162 163f: 164 ret i32 3 165} 166 167; if (!x || y) ret 3; ret 42 168 169define i32 @logical_or_not(i1 %x, i1 %y) { 170; CHECK-LABEL: @logical_or_not( 171; CHECK-NEXT: entry: 172; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true 173; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOTX]], i1 true, i1 [[Y:%.*]] 174; CHECK-NEXT: br i1 [[AND]], label [[F:%.*]], label [[T:%.*]] 175; CHECK: t: 176; CHECK-NEXT: ret i32 42 177; CHECK: f: 178; CHECK-NEXT: ret i32 3 179; 180entry: 181 %notx = xor i1 %x, true 182 %and = select i1 %notx, i1 true, i1 %y 183 br i1 %and, label %f, label %t 184 185t: 186 ret i32 42 187 188f: 189 ret i32 3 190} 191 192; negative test 193 194define i32 @logical_and_not_use1(i1 %x, i1 %y) { 195; CHECK-LABEL: @logical_and_not_use1( 196; CHECK-NEXT: entry: 197; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true 198; CHECK-NEXT: call void @use(i1 [[NOTY]]) 199; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false 200; CHECK-NEXT: br i1 [[AND]], label [[T:%.*]], label [[F:%.*]] 201; CHECK: t: 202; CHECK-NEXT: ret i32 42 203; CHECK: f: 204; CHECK-NEXT: ret i32 3 205; 206entry: 207 %noty = xor i1 %y, true 208 call void @use(i1 %noty) 209 %and = select i1 %x, i1 %noty, i1 false 210 br i1 %and, label %t, label %f 211 212t: 213 ret i32 42 214 215f: 216 ret i32 3 217} 218 219; negative test 220 221define i32 @logical_and_not_use2(i1 %x, i1 %y) { 222; CHECK-LABEL: @logical_and_not_use2( 223; CHECK-NEXT: entry: 224; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true 225; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false 226; CHECK-NEXT: call void @use(i1 [[AND]]) 227; CHECK-NEXT: br i1 [[AND]], label [[T:%.*]], label [[F:%.*]] 228; CHECK: t: 229; CHECK-NEXT: ret i32 42 230; CHECK: f: 231; CHECK-NEXT: ret i32 3 232; 233entry: 234 %noty = xor i1 %y, true 235 %and = select i1 %x, i1 %noty, i1 false 236 call void @use(i1 %and) 237 br i1 %and, label %t, label %f 238 239t: 240 ret i32 42 241 242f: 243 ret i32 3 244} 245 246define i32 @dom_true(i1 %cmp) { 247; CHECK-LABEL: @dom_true( 248; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 249; CHECK: if.then: 250; CHECK-NEXT: ret i32 1 251; CHECK: if.else: 252; CHECK-NEXT: ret i32 0 253; 254 br i1 %cmp, label %if.then, label %if.else 255 256if.then: 257 %zext = zext i1 %cmp to i32 258 ret i32 %zext 259 260if.else: 261 ret i32 0 262} 263 264define i32 @dom_false(i1 %cmp) { 265; CHECK-LABEL: @dom_false( 266; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] 267; CHECK: if.then: 268; CHECK-NEXT: ret i32 0 269; CHECK: if.else: 270; CHECK-NEXT: ret i32 0 271; 272 br i1 %cmp, label %if.else, label %if.then 273 274if.then: 275 %zext = zext i1 %cmp to i32 276 ret i32 %zext 277 278if.else: 279 ret i32 0 280} 281 282define i32 @dom_true_phi(i1 %cmp) { 283; CHECK-LABEL: @dom_true_phi( 284; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 285; CHECK: if.then: 286; CHECK-NEXT: br label [[IF_END:%.*]] 287; CHECK: if.else: 288; CHECK-NEXT: br label [[IF_END]] 289; CHECK: if.end: 290; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32 291; CHECK-NEXT: ret i32 [[ZEXT]] 292; 293 br i1 %cmp, label %if.then, label %if.else 294 295if.then: 296 br label %if.end 297 298if.else: 299 br label %if.end 300 301if.end: 302 %phi = phi i1 [ true, %if.then ], [ %cmp, %if.else ] 303 %zext = zext i1 %phi to i32 304 ret i32 %zext 305} 306 307; Negative tests 308 309define i32 @same_dest(i1 %cmp) { 310; CHECK-LABEL: @same_dest( 311; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_THEN]] 312; CHECK: if.then: 313; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP:%.*]] to i32 314; CHECK-NEXT: ret i32 [[ZEXT]] 315; 316 br i1 %cmp, label %if.then, label %if.then 317 318if.then: 319 %zext = zext i1 %cmp to i32 320 ret i32 %zext 321} 322 323define i32 @not_dom(i1 %cmp) { 324; CHECK-LABEL: @not_dom( 325; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 326; CHECK: if.then: 327; CHECK-NEXT: br label [[IF_ELSE]] 328; CHECK: if.else: 329; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32 330; CHECK-NEXT: ret i32 [[ZEXT]] 331; 332 br i1 %cmp, label %if.then, label %if.else 333 334if.then: 335 br label %if.else 336 337if.else: 338 %zext = zext i1 %cmp to i32 339 ret i32 %zext 340} 341