1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s 3 4; SimplifyCFG should eliminate redundant indirectbr edges. 5 6declare void @foo() 7declare void @A() 8declare void @B(i32) 9declare void @C() 10 11define void @indbrtest0(ptr %P, ptr %Q) { 12; CHECK-LABEL: @indbrtest0( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: store ptr blockaddress(@indbrtest0, [[BB0:%.*]]), ptr [[P:%.*]], align 8 15; CHECK-NEXT: store ptr blockaddress(@indbrtest0, [[BB1:%.*]]), ptr [[P]], align 8 16; CHECK-NEXT: store ptr blockaddress(@indbrtest0, [[BB2:%.*]]), ptr [[P]], align 8 17; CHECK-NEXT: call void @foo() 18; CHECK-NEXT: [[T:%.*]] = load ptr, ptr [[Q:%.*]], align 8 19; CHECK-NEXT: indirectbr ptr [[T]], [label [[BB0]], label [[BB1]], label %BB2] 20; CHECK: BB0: 21; CHECK-NEXT: call void @A() 22; CHECK-NEXT: br label [[BB1]] 23; CHECK: common.ret: 24; CHECK-NEXT: ret void 25; CHECK: BB1: 26; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[BB0]] ], [ 1, [[ENTRY:%.*]] ] 27; CHECK-NEXT: call void @B(i32 [[X]]) 28; CHECK-NEXT: br label [[COMMON_RET:%.*]] 29; CHECK: BB2: 30; CHECK-NEXT: call void @C() 31; CHECK-NEXT: br label [[COMMON_RET]] 32; 33entry: 34 store ptr blockaddress(@indbrtest0, %BB0), ptr %P 35 store ptr blockaddress(@indbrtest0, %BB1), ptr %P 36 store ptr blockaddress(@indbrtest0, %BB2), ptr %P 37 call void @foo() 38 %t = load ptr, ptr %Q 39 indirectbr ptr %t, [label %BB0, label %BB1, label %BB2, label %BB0, label %BB1, label %BB2] 40BB0: 41 call void @A() 42 br label %BB1 43BB1: 44 %x = phi i32 [ 0, %BB0 ], [ 1, %entry ], [ 1, %entry ] 45 call void @B(i32 %x) 46 ret void 47BB2: 48 call void @C() 49 ret void 50} 51 52; SimplifyCFG should convert the indirectbr into a directbr. It would be even 53; better if it removed the branch altogether, but simplifycfdg currently misses 54; that because the predecessor is the entry block. 55 56 57define void @indbrtest1(ptr %P, ptr %Q) { 58; CHECK-LABEL: @indbrtest1( 59; CHECK-NEXT: entry: 60; CHECK-NEXT: store ptr blockaddress(@indbrtest1, [[BB0:%.*]]), ptr [[P:%.*]], align 8 61; CHECK-NEXT: call void @foo() 62; CHECK-NEXT: br label [[BB0]] 63; CHECK: BB0: 64; CHECK-NEXT: call void @A() 65; CHECK-NEXT: ret void 66; 67entry: 68 store ptr blockaddress(@indbrtest1, %BB0), ptr %P 69 call void @foo() 70 %t = load ptr, ptr %Q 71 indirectbr ptr %t, [label %BB0, label %BB0] 72BB0: 73 call void @A() 74 ret void 75} 76 77; SimplifyCFG should notice that BB0 does not have its address taken and 78; remove it from entry's successor list. 79 80 81define void @indbrtest2(ptr %t) { 82; CHECK-LABEL: @indbrtest2( 83; CHECK-NEXT: entry: 84; CHECK-NEXT: unreachable 85; 86entry: 87 indirectbr ptr %t, [label %BB0, label %BB0] 88BB0: 89 ret void 90} 91 92 93; Make sure the blocks in the next few tests aren't trivially removable as 94; successors by taking their addresses. 95 96@anchor = constant [13 x ptr] [ 97 ptr blockaddress(@indbrtest3, %L1), ptr blockaddress(@indbrtest3, %L2), ptr blockaddress(@indbrtest3, %L3), 98 ptr blockaddress(@indbrtest4, %L1), ptr blockaddress(@indbrtest4, %L2), ptr blockaddress(@indbrtest4, %L3), 99 ptr blockaddress(@indbrtest5, %L1), ptr blockaddress(@indbrtest5, %L2), ptr blockaddress(@indbrtest5, %L3), ptr blockaddress(@indbrtest5, %L4), 100 ptr blockaddress(@indbrtest6, %L1), ptr blockaddress(@indbrtest6, %L2), ptr blockaddress(@indbrtest6, %L3) 101] 102 103; SimplifyCFG should turn the indirectbr into a conditional branch on the 104; condition of the select. 105 106define void @indbrtest3(i1 %cond, ptr %address) nounwind { 107; CHECK-LABEL: @indbrtest3( 108; CHECK-NEXT: entry: 109; CHECK-NEXT: br i1 [[COND:%.*]], label [[L1:%.*]], label [[L2:%.*]] 110; CHECK: common.ret: 111; CHECK-NEXT: ret void 112; CHECK: L1: 113; CHECK-NEXT: call void @A() 114; CHECK-NEXT: br label [[COMMON_RET:%.*]] 115; CHECK: L2: 116; CHECK-NEXT: call void @C() 117; CHECK-NEXT: br label [[COMMON_RET]] 118; 119entry: 120 %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest3, %L1), ptr blockaddress(@indbrtest3, %L2) 121 indirectbr ptr %indirect.goto.dest, [label %L1, label %L2, label %L3] 122 123L1: 124 call void @A() 125 ret void 126L2: 127 call void @C() 128 ret void 129L3: 130 call void @foo() 131 ret void 132} 133 134; SimplifyCFG should turn the indirectbr into an unconditional branch to the 135; only possible destination. 136; As in @indbrtest1, it should really remove the branch entirely, but it doesn't 137; because it's in the entry block. 138 139define void @indbrtest4(i1 %cond) nounwind { 140; CHECK-LABEL: @indbrtest4( 141; CHECK-NEXT: entry: 142; CHECK-NEXT: br label [[L1:%.*]] 143; CHECK: L1: 144; CHECK-NEXT: call void @A() 145; CHECK-NEXT: ret void 146; 147entry: 148 %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest4, %L1), ptr blockaddress(@indbrtest4, %L1) 149 indirectbr ptr %indirect.goto.dest, [label %L1, label %L2, label %L3] 150 151L1: 152 call void @A() 153 ret void 154L2: 155 call void @C() 156 ret void 157L3: 158 call void @foo() 159 ret void 160} 161 162; SimplifyCFG should turn the indirectbr into an unreachable because neither 163; destination is listed as a successor. 164 165define void @indbrtest5(i1 %cond, ptr %anchor) nounwind { 166; CHECK-LABEL: @indbrtest5( 167; CHECK-NEXT: entry: 168; CHECK-NEXT: unreachable 169; 170entry: 171 %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest5, %L1), ptr blockaddress(@indbrtest5, %L2) 172; This needs to have more than one successor for this test, otherwise it gets 173; replaced with an unconditional branch to the single successor. 174 indirectbr ptr %indirect.goto.dest, [label %L3, label %L4] 175 176L1: 177 call void @A() 178 ret void 179L2: 180 call void @C() 181 ret void 182L3: 183 call void @foo() 184 ret void 185L4: 186 call void @foo() 187 188; This keeps blockaddresses not otherwise listed as successors from being zapped 189; before SimplifyCFG even looks at the indirectbr. 190 indirectbr ptr %anchor, [label %L1, label %L2] 191} 192 193; The same as above, except the selected addresses are equal. 194 195define void @indbrtest6(i1 %cond, ptr %anchor) nounwind { 196; CHECK-LABEL: @indbrtest6( 197; CHECK-NEXT: entry: 198; CHECK-NEXT: unreachable 199; 200entry: 201 %indirect.goto.dest = select i1 %cond, ptr blockaddress(@indbrtest6, %L1), ptr blockaddress(@indbrtest6, %L1) 202; This needs to have more than one successor for this test, otherwise it gets 203; replaced with an unconditional branch to the single successor. 204 indirectbr ptr %indirect.goto.dest, [label %L2, label %L3] 205 206L1: 207 call void @A() 208 ret void 209L2: 210 call void @C() 211 ret void 212L3: 213 call void @foo() 214 215; This keeps blockaddresses not otherwise listed as successors from being zapped 216; before SimplifyCFG even looks at the indirectbr. 217 indirectbr ptr %anchor, [label %L1, label %L2] 218} 219 220; PR10072 221 222@xblkx.bbs = internal unnamed_addr constant [9 x ptr] [ptr blockaddress(@indbrtest7, %xblkx.begin), ptr blockaddress(@indbrtest7, %xblkx.begin3), ptr blockaddress(@indbrtest7, %xblkx.begin4), ptr blockaddress(@indbrtest7, %xblkx.begin5), ptr blockaddress(@indbrtest7, %xblkx.begin6), ptr blockaddress(@indbrtest7, %xblkx.begin7), ptr blockaddress(@indbrtest7, %xblkx.begin8), ptr blockaddress(@indbrtest7, %xblkx.begin9), ptr blockaddress(@indbrtest7, %xblkx.end)] 223 224define void @indbrtest7() { 225; CHECK-LABEL: @indbrtest7( 226; CHECK-NEXT: escape-string.top: 227; CHECK-NEXT: [[XVAL202X:%.*]] = call i32 @xfunc5x() 228; CHECK-NEXT: br label [[XLAB5X:%.*]] 229; CHECK: xlab8x: 230; CHECK-NEXT: [[XVALUEX:%.*]] = call i32 @xselectorx() 231; CHECK-NEXT: [[XBLKX_X:%.*]] = getelementptr [9 x ptr], ptr @xblkx.bbs, i32 0, i32 [[XVALUEX]] 232; CHECK-NEXT: [[XBLKX_LOAD:%.*]] = load ptr, ptr [[XBLKX_X]], align 8 233; CHECK-NEXT: indirectbr ptr [[XBLKX_LOAD]], [label [[XLAB4X:%.*]], label %v2j] 234; CHECK: v2j: 235; CHECK-NEXT: [[XUNUSEDX:%.*]] = call i32 @xactionx() 236; CHECK-NEXT: br label [[XLAB4X]] 237; CHECK: xlab4x: 238; CHECK-NEXT: [[INCR19:%.*]] = add i32 [[XVAL704X_0:%.*]], 1 239; CHECK-NEXT: br label [[XLAB5X]] 240; CHECK: xlab5x: 241; CHECK-NEXT: [[XVAL704X_0]] = phi i32 [ 0, [[ESCAPE_STRING_TOP:%.*]] ], [ [[INCR19]], [[XLAB4X]] ] 242; CHECK-NEXT: [[XVAL10X:%.*]] = icmp ult i32 [[XVAL704X_0]], [[XVAL202X]] 243; CHECK-NEXT: br i1 [[XVAL10X]], label [[XLAB8X:%.*]], label [[XLAB9X:%.*]] 244; CHECK: xlab9x: 245; CHECK-NEXT: ret void 246; 247escape-string.top: 248 %xval202x = call i32 @xfunc5x() 249 br label %xlab5x 250 251xlab8x: ; preds = %xlab5x 252 %xvaluex = call i32 @xselectorx() 253 %xblkx.x = getelementptr [9 x ptr], ptr @xblkx.bbs, i32 0, i32 %xvaluex 254 %xblkx.load = load ptr, ptr %xblkx.x 255 indirectbr ptr %xblkx.load, [label %xblkx.begin, label %xblkx.begin3, label %xblkx.begin4, label %xblkx.begin5, label %xblkx.begin6, label %xblkx.begin7, label %xblkx.begin8, label %xblkx.begin9, label %xblkx.end] 256 257xblkx.begin: 258 br label %xblkx.end 259 260xblkx.begin3: 261 br label %xblkx.end 262 263xblkx.begin4: 264 br label %xblkx.end 265 266xblkx.begin5: 267 br label %xblkx.end 268 269xblkx.begin6: 270 br label %xblkx.end 271 272xblkx.begin7: 273 br label %xblkx.end 274 275xblkx.begin8: 276 br label %xblkx.end 277 278xblkx.begin9: 279 br label %xblkx.end 280 281xblkx.end: 282 %yes.0 = phi i1 [ false, %xblkx.begin ], [ true, %xlab8x ], [ false, %xblkx.begin9 ], [ false, %xblkx.begin8 ], [ false, %xblkx.begin7 ], [ false, %xblkx.begin6 ], [ false, %xblkx.begin5 ], [ true, %xblkx.begin4 ], [ false, %xblkx.begin3 ] 283 br i1 %yes.0, label %v2j, label %xlab17x 284 285v2j: 286 %xunusedx = call i32 @xactionx() 287 br label %xlab4x 288 289xlab17x: 290 br label %xlab4x 291 292xlab4x: 293 %incr19 = add i32 %xval704x.0, 1 294 br label %xlab5x 295 296xlab5x: 297 %xval704x.0 = phi i32 [ 0, %escape-string.top ], [ %incr19, %xlab4x ] 298 %xval10x = icmp ult i32 %xval704x.0, %xval202x 299 br i1 %xval10x, label %xlab8x, label %xlab9x 300 301xlab9x: 302 ret void 303} 304 305define void @indbrtest8() { 306; CHECK-LABEL: @indbrtest8( 307; CHECK-NEXT: entry: 308; CHECK-NEXT: call void @B(i32 undef) 309; CHECK-NEXT: ret void 310; 311entry: 312 indirectbr ptr blockaddress(@indbrtest8, %BB1), [label %BB0, label %BB1] 313BB0: 314 call void @A() 315 ret void 316BB1: 317 call void @B(i32 undef) 318 ret void 319} 320 321define void @indbrtest9() { 322; CHECK-LABEL: @indbrtest9( 323; CHECK-NEXT: entry: 324; CHECK-NEXT: unreachable 325; 326entry: 327 indirectbr ptr blockaddress(@indbrtest9, %BB1), [label %BB0] 328BB0: 329 call void @A() 330 ret void 331BB1: 332 call void @B(i32 undef) 333 ret void 334} 335 336define void @indbrtest10() { 337; CHECK-LABEL: @indbrtest10( 338; CHECK-NEXT: entry: 339; CHECK-NEXT: call void @B(i32 undef) 340; CHECK-NEXT: ret void 341; 342entry: 343 indirectbr ptr blockaddress(@indbrtest10, %BB1), [label %BB1] 344BB0: 345 call void @A() 346 ret void 347BB1: 348 call void @B(i32 undef) 349 ret void 350} 351 352define void @indbrtest11() { 353; CHECK-LABEL: @indbrtest11( 354; CHECK-NEXT: entry: 355; CHECK-NEXT: call void @A() 356; CHECK-NEXT: ret void 357; 358entry: 359 indirectbr ptr blockaddress(@indbrtest11, %BB0), [label %BB0, label %BB1, label %BB1] 360BB0: 361 call void @A() 362 ret void 363BB1: 364 call void @B(i32 undef) 365 ret void 366} 367 368define void @indbrtest12() { 369; CHECK-LABEL: @indbrtest12( 370; CHECK-NEXT: entry: 371; CHECK-NEXT: call void @B(i32 undef) 372; CHECK-NEXT: ret void 373; 374entry: 375 indirectbr ptr blockaddress(@indbrtest12, %BB1), [label %BB0, label %BB1, label %BB1] 376BB0: 377 call void @A() 378 ret void 379BB1: 380 call void @B(i32 undef) 381 ret void 382} 383 384declare i32 @xfunc5x() 385declare i8 @xfunc7x() 386declare i32 @xselectorx() 387declare i32 @xactionx() 388