1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=simplifycfg,instcombine -simplifycfg-require-and-preserve-domtree=1 < %s -simplifycfg-merge-cond-stores=true -simplifycfg-merge-cond-stores-aggressively=false -phi-node-folding-threshold=2 -S | FileCheck %s 3 4; This test should succeed and end up if-converted. 5define void @test_simple(ptr %p, i32 %a, i32 %b) { 6; CHECK-LABEL: @test_simple( 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B:%.*]] 9; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP0]], 0 10; CHECK-NEXT: br i1 [[DOTNOT]], label [[TMP2:%.*]], label [[TMP1:%.*]] 11; CHECK: 1: 12; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0 13; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32 14; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[P:%.*]], align 4 15; CHECK-NEXT: br label [[TMP2]] 16; CHECK: 2: 17; CHECK-NEXT: ret void 18; 19entry: 20 %x1 = icmp eq i32 %a, 0 21 br i1 %x1, label %fallthrough, label %yes1 22 23yes1: 24 store i32 0, ptr %p 25 br label %fallthrough 26 27fallthrough: 28 %x2 = icmp eq i32 %b, 0 29 br i1 %x2, label %end, label %yes2 30 31yes2: 32 store i32 1, ptr %p 33 br label %end 34 35end: 36 ret void 37} 38 39; This is the same as test_simple, but the branch target order has been swapped 40define void @test_simple_commuted(ptr %p, i32 %a, i32 %b) { 41; CHECK-LABEL: @test_simple_commuted( 42; CHECK-NEXT: entry: 43; CHECK-NEXT: [[X1_NOT:%.*]] = icmp eq i32 [[A:%.*]], 0 44; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0 45; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[X1_NOT]], [[X2]] 46; CHECK-NEXT: br i1 [[TMP0]], label [[TMP1:%.*]], label [[TMP2:%.*]] 47; CHECK: 1: 48; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32 49; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[P:%.*]], align 4 50; CHECK-NEXT: br label [[TMP2]] 51; CHECK: 2: 52; CHECK-NEXT: ret void 53; 54entry: 55 %x1 = icmp eq i32 %a, 0 56 br i1 %x1, label %yes1, label %fallthrough 57 58yes1: 59 store i32 0, ptr %p 60 br label %fallthrough 61 62fallthrough: 63 %x2 = icmp eq i32 %b, 0 64 br i1 %x2, label %yes2, label %end 65 66yes2: 67 store i32 1, ptr %p 68 br label %end 69 70end: 71 ret void 72} 73 74; This test should entirely fold away, leaving one large basic block. 75define void @test_recursive(ptr %p, i32 %a, i32 %b, i32 %c, i32 %d) { 76; CHECK-LABEL: @test_recursive( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B:%.*]] 79; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP0]], [[C:%.*]] 80; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[D:%.*]] 81; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP2]], 0 82; CHECK-NEXT: br i1 [[DOTNOT]], label [[TMP4:%.*]], label [[TMP3:%.*]] 83; CHECK: 3: 84; CHECK-NEXT: [[X4_NOT:%.*]] = icmp eq i32 [[D]], 0 85; CHECK-NEXT: [[X3_NOT:%.*]] = icmp eq i32 [[C]], 0 86; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0 87; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32 88; CHECK-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[X3_NOT]], i32 [[SPEC_SELECT]], i32 2 89; CHECK-NEXT: [[SPEC_SELECT2:%.*]] = select i1 [[X4_NOT]], i32 [[SPEC_SELECT1]], i32 3 90; CHECK-NEXT: store i32 [[SPEC_SELECT2]], ptr [[P:%.*]], align 4 91; CHECK-NEXT: br label [[TMP4]] 92; CHECK: 4: 93; CHECK-NEXT: ret void 94; 95entry: 96 %x1 = icmp eq i32 %a, 0 97 br i1 %x1, label %fallthrough, label %yes1 98 99yes1: 100 store i32 0, ptr %p 101 br label %fallthrough 102 103fallthrough: 104 %x2 = icmp eq i32 %b, 0 105 br i1 %x2, label %next, label %yes2 106 107yes2: 108 store i32 1, ptr %p 109 br label %next 110 111next: 112 %x3 = icmp eq i32 %c, 0 113 br i1 %x3, label %fallthrough2, label %yes3 114 115yes3: 116 store i32 2, ptr %p 117 br label %fallthrough2 118 119fallthrough2: 120 %x4 = icmp eq i32 %d, 0 121 br i1 %x4, label %end, label %yes4 122 123yes4: 124 store i32 3, ptr %p 125 br label %end 126 127 128end: 129 ret void 130} 131 132; The code in each diamond is too large - it won't be if-converted so our 133; heuristics should say no. 134define void @test_not_ifconverted(ptr %p, i32 %a, i32 %b) { 135; CHECK-LABEL: @test_not_ifconverted( 136; CHECK-NEXT: entry: 137; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0 138; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]] 139; CHECK: yes1: 140; CHECK-NEXT: [[Y1:%.*]] = or i32 [[B:%.*]], 55 141; CHECK-NEXT: [[Y2:%.*]] = add i32 [[Y1]], 24 142; CHECK-NEXT: [[Y3:%.*]] = and i32 [[Y2]], 67 143; CHECK-NEXT: store i32 [[Y3]], ptr [[P:%.*]], align 4 144; CHECK-NEXT: br label [[FALLTHROUGH]] 145; CHECK: fallthrough: 146; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B]], 0 147; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]] 148; CHECK: yes2: 149; CHECK-NEXT: [[Z1:%.*]] = or i32 [[A]], 55 150; CHECK-NEXT: [[Z2:%.*]] = add i32 [[Z1]], 24 151; CHECK-NEXT: [[Z3:%.*]] = and i32 [[Z2]], 67 152; CHECK-NEXT: store i32 [[Z3]], ptr [[P]], align 4 153; CHECK-NEXT: br label [[END]] 154; CHECK: end: 155; CHECK-NEXT: ret void 156; 157entry: 158 %x1 = icmp eq i32 %a, 0 159 br i1 %x1, label %fallthrough, label %yes1 160 161yes1: 162 %y1 = or i32 %b, 55 163 %y2 = add i32 %y1, 24 164 %y3 = and i32 %y2, 67 165 store i32 %y3, ptr %p 166 br label %fallthrough 167 168fallthrough: 169 %x2 = icmp eq i32 %b, 0 170 br i1 %x2, label %end, label %yes2 171 172yes2: 173 %z1 = or i32 %a, 55 174 %z2 = add i32 %z1, 24 175 %z3 = and i32 %z2, 67 176 store i32 %z3, ptr %p 177 br label %end 178 179end: 180 ret void 181} 182 183; The store to %p clobbers the previous store, so if-converting this would 184; be illegal. 185define void @test_aliasing1(ptr %p, i32 %a, i32 %b) { 186; CHECK-LABEL: @test_aliasing1( 187; CHECK-NEXT: entry: 188; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0 189; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]] 190; CHECK: yes1: 191; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4 192; CHECK-NEXT: br label [[FALLTHROUGH]] 193; CHECK: fallthrough: 194; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[P]], align 4 195; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[Y1]], 0 196; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]] 197; CHECK: yes2: 198; CHECK-NEXT: store i32 1, ptr [[P]], align 4 199; CHECK-NEXT: br label [[END]] 200; CHECK: end: 201; CHECK-NEXT: ret void 202; 203entry: 204 %x1 = icmp eq i32 %a, 0 205 br i1 %x1, label %fallthrough, label %yes1 206 207yes1: 208 store i32 0, ptr %p 209 br label %fallthrough 210 211fallthrough: 212 %y1 = load i32, ptr %p 213 %x2 = icmp eq i32 %y1, 0 214 br i1 %x2, label %end, label %yes2 215 216yes2: 217 store i32 1, ptr %p 218 br label %end 219 220end: 221 ret void 222} 223 224; The load from %q aliases with %p, so if-converting this would be illegal. 225define void @test_aliasing2(ptr %p, ptr %q, i32 %a, i32 %b) { 226; CHECK-LABEL: @test_aliasing2( 227; CHECK-NEXT: entry: 228; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0 229; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]] 230; CHECK: yes1: 231; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4 232; CHECK-NEXT: br label [[FALLTHROUGH]] 233; CHECK: fallthrough: 234; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[Q:%.*]], align 4 235; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[Y1]], 0 236; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]] 237; CHECK: yes2: 238; CHECK-NEXT: store i32 1, ptr [[P]], align 4 239; CHECK-NEXT: br label [[END]] 240; CHECK: end: 241; CHECK-NEXT: ret void 242; 243entry: 244 %x1 = icmp eq i32 %a, 0 245 br i1 %x1, label %fallthrough, label %yes1 246 247yes1: 248 store i32 0, ptr %p 249 br label %fallthrough 250 251fallthrough: 252 %y1 = load i32, ptr %q 253 %x2 = icmp eq i32 %y1, 0 254 br i1 %x2, label %end, label %yes2 255 256yes2: 257 store i32 1, ptr %p 258 br label %end 259 260end: 261 ret void 262} 263 264declare void @f() 265 266; This should get if-converted. 267define i32 @test_diamond_simple(ptr %p, ptr %q, i32 %a, i32 %b) { 268; CHECK-LABEL: @test_diamond_simple( 269; CHECK-NEXT: entry: 270; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B:%.*]], 0 271; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B]] 272; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP0]], 0 273; CHECK-NEXT: br i1 [[DOTNOT]], label [[TMP2:%.*]], label [[TMP1:%.*]] 274; CHECK: 1: 275; CHECK-NEXT: [[SIMPLIFYCFG_MERGE:%.*]] = zext i1 [[X2]] to i32 276; CHECK-NEXT: store i32 [[SIMPLIFYCFG_MERGE]], ptr [[P:%.*]], align 4 277; CHECK-NEXT: br label [[TMP2]] 278; CHECK: 2: 279; CHECK-NEXT: [[Z4:%.*]] = select i1 [[X2]], i32 3, i32 0 280; CHECK-NEXT: ret i32 [[Z4]] 281; 282entry: 283 %x1 = icmp eq i32 %a, 0 284 br i1 %x1, label %no1, label %yes1 285 286yes1: 287 store i32 0, ptr %p 288 br label %fallthrough 289 290no1: 291 %z1 = add i32 %a, %b 292 br label %fallthrough 293 294fallthrough: 295 %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ] 296 %x2 = icmp eq i32 %b, 0 297 br i1 %x2, label %no2, label %yes2 298 299yes2: 300 store i32 1, ptr %p 301 br label %end 302 303no2: 304 %z3 = sub i32 %z2, %b 305 br label %end 306 307end: 308 %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ] 309 ret i32 %z4 310} 311 312; Now there is a call to f() in the bottom branch. The store in the first 313; branch would now be reordered with respect to the call if we if-converted, 314; so we must not. 315define i32 @test_diamond_alias3(ptr %p, ptr %q, i32 %a, i32 %b) { 316; CHECK-LABEL: @test_diamond_alias3( 317; CHECK-NEXT: entry: 318; CHECK-NEXT: [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0 319; CHECK-NEXT: br i1 [[X1]], label [[NO1:%.*]], label [[YES1:%.*]] 320; CHECK: yes1: 321; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4 322; CHECK-NEXT: br label [[FALLTHROUGH:%.*]] 323; CHECK: no1: 324; CHECK-NEXT: call void @f() 325; CHECK-NEXT: br label [[FALLTHROUGH]] 326; CHECK: fallthrough: 327; CHECK-NEXT: [[Z2:%.*]] = phi i32 [ [[B:%.*]], [[NO1]] ], [ 0, [[YES1]] ] 328; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B]], 0 329; CHECK-NEXT: br i1 [[X2]], label [[NO2:%.*]], label [[YES2:%.*]] 330; CHECK: yes2: 331; CHECK-NEXT: store i32 1, ptr [[P]], align 4 332; CHECK-NEXT: br label [[END:%.*]] 333; CHECK: no2: 334; CHECK-NEXT: call void @f() 335; CHECK-NEXT: [[Z3:%.*]] = sub nuw nsw i32 [[Z2]], [[B]] 336; CHECK-NEXT: br label [[END]] 337; CHECK: end: 338; CHECK-NEXT: [[Z4:%.*]] = phi i32 [ [[Z3]], [[NO2]] ], [ 3, [[YES2]] ] 339; CHECK-NEXT: ret i32 [[Z4]] 340; 341entry: 342 %x1 = icmp eq i32 %a, 0 343 br i1 %x1, label %no1, label %yes1 344 345yes1: 346 store i32 0, ptr %p 347 br label %fallthrough 348 349no1: 350 call void @f() 351 %z1 = add i32 %a, %b 352 br label %fallthrough 353 354fallthrough: 355 %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ] 356 %x2 = icmp eq i32 %b, 0 357 br i1 %x2, label %no2, label %yes2 358 359yes2: 360 store i32 1, ptr %p 361 br label %end 362 363no2: 364 call void @f() 365 %z3 = sub i32 %z2, %b 366 br label %end 367 368end: 369 %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ] 370 ret i32 %z4 371} 372 373; This test has an outer if over the two triangles. This requires creating a new BB to hold the store. 374define void @test_outer_if(ptr %p, i32 %a, i32 %b, i32 %c) { 375; CHECK-LABEL: @test_outer_if( 376; CHECK-NEXT: entry: 377; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0 378; CHECK-NEXT: br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]] 379; CHECK: continue: 380; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[A:%.*]], [[B:%.*]] 381; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP0]], 0 382; CHECK-NEXT: br i1 [[DOTNOT]], label [[END]], label [[TMP1:%.*]] 383; CHECK: 1: 384; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0 385; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32 386; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[P:%.*]], align 4 387; CHECK-NEXT: br label [[END]] 388; CHECK: end: 389; CHECK-NEXT: ret void 390; 391entry: 392 %x3 = icmp eq i32 %c, 0 393 br i1 %x3, label %end, label %continue 394continue: 395 %x1 = icmp eq i32 %a, 0 396 br i1 %x1, label %fallthrough, label %yes1 397yes1: 398 store i32 0, ptr %p 399 br label %fallthrough 400 fallthrough: 401 %x2 = icmp eq i32 %b, 0 402 br i1 %x2, label %end, label %yes2 403yes2: 404 store i32 1, ptr %p 405 br label %end 406end: 407 ret void 408} 409