1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals smart 2; RUN: opt < %s -passes=jump-threading -S | FileCheck %s 3; RUN: opt < %s -aa-pipeline=basic-aa -passes=jump-threading -S | FileCheck %s 4 5target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" 6target triple = "i386-apple-darwin7" 7 8; Test that we can thread through the block with the partially redundant load (%2). 9; rdar://6402033 10define i32 @test1(ptr %P) nounwind { 11; CHECK-LABEL: @test1( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 (...) @f1() #[[ATTR0:[0-9]+]] 14; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0 15; CHECK-NEXT: br i1 [[TMP1]], label [[BB1:%.*]], label [[BB1_THREAD:%.*]] 16; CHECK: bb1.thread: 17; CHECK-NEXT: store i32 42, ptr [[P:%.*]], align 4 18; CHECK-NEXT: br label [[BB3:%.*]] 19; CHECK: bb1: 20; CHECK-NEXT: [[DOTPR:%.*]] = load i32, ptr [[P]], align 4 21; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTPR]], 36 22; CHECK-NEXT: br i1 [[TMP2]], label [[BB3]], label [[BB2:%.*]] 23; CHECK: bb2: 24; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 (...) @f2() #[[ATTR0]] 25; CHECK-NEXT: ret i32 0 26; CHECK: bb3: 27; CHECK-NEXT: [[RES_02:%.*]] = phi i32 [ 1, [[BB1_THREAD]] ], [ 0, [[BB1]] ] 28; CHECK-NEXT: ret i32 [[RES_02]] 29; 30entry: 31 %0 = tail call i32 (...) @f1() nounwind ; <i32> [#uses=1] 32 %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1] 33 br i1 %1, label %bb1, label %bb 34 35bb: ; preds = %entry 36 store i32 42, ptr %P, align 4 37 br label %bb1 38 39bb1: ; preds = %entry, %bb 40 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ] ; <i32> [#uses=2] 41 %2 = load i32, ptr %P, align 4 ; <i32> [#uses=1] 42 %3 = icmp sgt i32 %2, 36 ; <i1> [#uses=1] 43 br i1 %3, label %bb3, label %bb2 44 45bb2: ; preds = %bb1 46 %4 = tail call i32 (...) @f2() nounwind ; <i32> [#uses=0] 47 ret i32 %res.0 48 49bb3: ; preds = %bb1 50 ret i32 %res.0 51} 52 53declare i32 @f1(...) 54 55declare i32 @f2(...) 56 57 58;; Check that we preserve TBAA information. 59; rdar://11039258 60 61define i32 @test2(ptr %P) nounwind { 62; CHECK-LABEL: @test2( 63; CHECK-NEXT: entry: 64; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 (...) @f1() #[[ATTR0]] 65; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0 66; CHECK-NEXT: br i1 [[TMP1]], label [[BB1:%.*]], label [[BB1_THREAD:%.*]] 67; CHECK: bb1.thread: 68; CHECK-NEXT: store i32 42, ptr [[P:%.*]], align 4, !tbaa [[TBAA0:![0-9]+]] 69; CHECK-NEXT: br label [[BB3:%.*]] 70; CHECK: bb1: 71; CHECK-NEXT: [[DOTPR:%.*]] = load i32, ptr [[P]], align 4, !tbaa [[TBAA0]] 72; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTPR]], 36 73; CHECK-NEXT: br i1 [[TMP2]], label [[BB3]], label [[BB2:%.*]] 74; CHECK: bb2: 75; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 (...) @f2() #[[ATTR0]] 76; CHECK-NEXT: ret i32 0 77; CHECK: bb3: 78; CHECK-NEXT: [[RES_02:%.*]] = phi i32 [ 1, [[BB1_THREAD]] ], [ 0, [[BB1]] ] 79; CHECK-NEXT: ret i32 [[RES_02]] 80; 81entry: 82 %0 = tail call i32 (...) @f1() nounwind ; <i32> [#uses=1] 83 %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1] 84 br i1 %1, label %bb1, label %bb 85 86bb: ; preds = %entry 87 store i32 42, ptr %P, align 4, !tbaa !0 88 br label %bb1 89 90bb1: ; preds = %entry, %bb 91 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ] 92 %2 = load i32, ptr %P, align 4, !tbaa !0 93 %3 = icmp sgt i32 %2, 36 94 br i1 %3, label %bb3, label %bb2 95 96bb2: ; preds = %bb1 97 %4 = tail call i32 (...) @f2() nounwind 98 ret i32 %res.0 99 100bb3: ; preds = %bb1 101 ret i32 %res.0 102} 103 104define i32 @test3(ptr %x, i1 %f) { 105; Correctly thread loads of different (but compatible) types, placing bitcasts 106; as necessary in the predecessors. This is especially tricky because the same 107; predecessor ends up with two entries in the PHI node and they must share 108; a single cast. 109; CHECK-LABEL: @test3( 110; CHECK-NEXT: entry: 111; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[X:%.*]], align 8 112; CHECK-NEXT: br i1 [[F:%.*]], label [[IF_END57:%.*]], label [[IF_END57]] 113; CHECK: if.end57: 114; CHECK-NEXT: [[TMP3:%.*]] = phi ptr [ [[TMP1]], [[ENTRY:%.*]] ], [ [[TMP1]], [[ENTRY]] ] 115; CHECK-NEXT: [[TOBOOL59:%.*]] = icmp eq ptr [[TMP3]], null 116; CHECK-NEXT: br i1 [[TOBOOL59]], label [[RETURN:%.*]], label [[IF_THEN60:%.*]] 117; CHECK: if.then60: 118; CHECK-NEXT: ret i32 42 119; CHECK: return: 120; CHECK-NEXT: ret i32 13 121; 122entry: 123 %0 = load ptr, ptr %x, align 8 124 br i1 %f, label %if.end57, label %if.then56 125 126if.then56: 127 br label %if.end57 128 129if.end57: 130 %1 = load ptr, ptr %x, align 8 131 %tobool59 = icmp eq ptr %1, null 132 br i1 %tobool59, label %return, label %if.then60 133 134if.then60: 135 ret i32 42 136 137return: 138 ret i32 13 139} 140 141define i32 @test4(ptr %P) { 142; CHECK-LABEL: @test4( 143; CHECK-NEXT: entry: 144; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1() 145; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0 146; CHECK-NEXT: br i1 [[V1]], label [[BB1:%.*]], label [[BB1_THREAD:%.*]] 147; CHECK: bb1.thread: 148; CHECK-NEXT: store atomic i32 42, ptr [[P:%.*]] unordered, align 4 149; CHECK-NEXT: br label [[BB3:%.*]] 150; CHECK: bb1: 151; CHECK-NEXT: [[V2_PR:%.*]] = load atomic i32, ptr [[P]] unordered, align 4 152; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2_PR]], 36 153; CHECK-NEXT: br i1 [[V3]], label [[BB3]], label [[BB2:%.*]] 154; CHECK: bb2: 155; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2() 156; CHECK-NEXT: ret i32 0 157; CHECK: bb3: 158; CHECK-NEXT: [[RES_04:%.*]] = phi i32 [ 1, [[BB1_THREAD]] ], [ 0, [[BB1]] ] 159; CHECK-NEXT: ret i32 [[RES_04]] 160; 161entry: 162 %v0 = tail call i32 (...) @f1() 163 %v1 = icmp eq i32 %v0, 0 164 br i1 %v1, label %bb1, label %bb 165 166bb: 167 store atomic i32 42, ptr %P unordered, align 4 168 br label %bb1 169 170bb1: 171 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ] 172 %v2 = load atomic i32, ptr %P unordered, align 4 173 %v3 = icmp sgt i32 %v2, 36 174 br i1 %v3, label %bb3, label %bb2 175 176bb2: 177 %v4 = tail call i32 (...) @f2() 178 ret i32 %res.0 179 180bb3: 181 ret i32 %res.0 182} 183 184define i32 @test5(ptr %P) { 185; Negative test 186; CHECK-LABEL: @test5( 187; CHECK-NEXT: entry: 188; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1() 189; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0 190; CHECK-NEXT: br i1 [[V1]], label [[BB1:%.*]], label [[BB:%.*]] 191; CHECK: bb: 192; CHECK-NEXT: store atomic i32 42, ptr [[P:%.*]] release, align 4 193; CHECK-NEXT: br label [[BB1]] 194; CHECK: bb1: 195; CHECK-NEXT: [[RES_0:%.*]] = phi i32 [ 1, [[BB]] ], [ 0, [[ENTRY:%.*]] ] 196; CHECK-NEXT: [[V2:%.*]] = load atomic i32, ptr [[P]] acquire, align 4 197; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2]], 36 198; CHECK-NEXT: br i1 [[V3]], label [[BB3:%.*]], label [[BB2:%.*]] 199; CHECK: bb2: 200; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2() 201; CHECK-NEXT: ret i32 [[RES_0]] 202; CHECK: bb3: 203; CHECK-NEXT: ret i32 [[RES_0]] 204; 205entry: 206 %v0 = tail call i32 (...) @f1() 207 %v1 = icmp eq i32 %v0, 0 208 br i1 %v1, label %bb1, label %bb 209 210bb: 211 store atomic i32 42, ptr %P release, align 4 212 br label %bb1 213 214bb1: 215 216 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ] 217 %v2 = load atomic i32, ptr %P acquire, align 4 218 %v3 = icmp sgt i32 %v2, 36 219 br i1 %v3, label %bb3, label %bb2 220 221bb2: 222 %v4 = tail call i32 (...) @f2() 223 ret i32 %res.0 224 225bb3: 226 ret i32 %res.0 227} 228 229define i32 @test6(ptr %P) { 230; Negative test 231; CHECK-LABEL: @test6( 232; CHECK-NEXT: entry: 233; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1() 234; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0 235; CHECK-NEXT: br i1 [[V1]], label [[BB1:%.*]], label [[BB:%.*]] 236; CHECK: bb: 237; CHECK-NEXT: store i32 42, ptr [[P:%.*]], align 4 238; CHECK-NEXT: br label [[BB1]] 239; CHECK: bb1: 240; CHECK-NEXT: [[RES_0:%.*]] = phi i32 [ 1, [[BB]] ], [ 0, [[ENTRY:%.*]] ] 241; CHECK-NEXT: [[V2:%.*]] = load atomic i32, ptr [[P]] acquire, align 4 242; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2]], 36 243; CHECK-NEXT: br i1 [[V3]], label [[BB3:%.*]], label [[BB2:%.*]] 244; CHECK: bb2: 245; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2() 246; CHECK-NEXT: ret i32 [[RES_0]] 247; CHECK: bb3: 248; CHECK-NEXT: ret i32 [[RES_0]] 249; 250entry: 251 %v0 = tail call i32 (...) @f1() 252 %v1 = icmp eq i32 %v0, 0 253 br i1 %v1, label %bb1, label %bb 254 255bb: 256 store i32 42, ptr %P 257 br label %bb1 258 259bb1: 260 261 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ] 262 %v2 = load atomic i32, ptr %P acquire, align 4 263 %v3 = icmp sgt i32 %v2, 36 264 br i1 %v3, label %bb3, label %bb2 265 266bb2: 267 %v4 = tail call i32 (...) @f2() 268 ret i32 %res.0 269 270bb3: 271 ret i32 %res.0 272} 273 274define i32 @test7(ptr %P) { 275; Negative test 276; CHECK-LABEL: @test7( 277; CHECK-NEXT: entry: 278; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1() 279; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0 280; CHECK-NEXT: br i1 [[V1]], label [[BB1:%.*]], label [[BB:%.*]] 281; CHECK: bb: 282; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4 283; CHECK-NEXT: br label [[BB1]] 284; CHECK: bb1: 285; CHECK-NEXT: [[RES_0:%.*]] = phi i32 [ 1, [[BB]] ], [ 0, [[ENTRY:%.*]] ] 286; CHECK-NEXT: [[V2:%.*]] = load atomic i32, ptr [[P]] acquire, align 4 287; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2]], 36 288; CHECK-NEXT: br i1 [[V3]], label [[BB3:%.*]], label [[BB2:%.*]] 289; CHECK: bb2: 290; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2() 291; CHECK-NEXT: ret i32 [[RES_0]] 292; CHECK: bb3: 293; CHECK-NEXT: ret i32 [[RES_0]] 294; 295entry: 296 %v0 = tail call i32 (...) @f1() 297 %v1 = icmp eq i32 %v0, 0 298 br i1 %v1, label %bb1, label %bb 299 300bb: 301 %val = load i32, ptr %P 302 br label %bb1 303 304bb1: 305 306 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ] 307 %v2 = load atomic i32, ptr %P acquire, align 4 308 %v3 = icmp sgt i32 %v2, 36 309 br i1 %v3, label %bb3, label %bb2 310 311bb2: 312 %v4 = tail call i32 (...) @f2() 313 ret i32 %res.0 314 315bb3: 316 ret i32 %res.0 317} 318 319; We keep the tbaa and range metadata for the first load, as it dominates the 320; second load. Hence we can eliminate the branch. 321define void @test8(ptr, ptr, ptr) { 322; CHECK-LABEL: @test8( 323; CHECK-NEXT: ret2: 324; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP0:%.*]], align 4, !tbaa [[TBAA0]], !range [[RNG4:![0-9]+]], !alias.scope [[META5:![0-9]+]], !noalias [[META8:![0-9]+]], !noundef [[META10:![0-9]+]] 325; CHECK-NEXT: store i32 [[A]], ptr [[TMP1:%.*]], align 4 326; CHECK-NEXT: [[XXX:%.*]] = tail call i32 (...) @f1() #[[ATTR0]] 327; CHECK-NEXT: ret void 328; 329 %a = load i32, ptr %0, !tbaa !0, !range !4, !alias.scope !9, !noalias !10, !noundef !11 330 %b = load i32, ptr %0, !range !5 331 store i32 %a, ptr %1 332 %c = icmp eq i32 %b, 8 333 br i1 %c, label %ret1, label %ret2 334 335ret1: 336 ret void 337 338ret2: 339 %xxx = tail call i32 (...) @f1() nounwind 340 ret void 341} 342 343; Make sure we merge/PRE aliasing metadata correctly. That means that 344; we need to remove metadata from the existing load, and add appropriate 345; metadata to the newly inserted load. 346define void @test9(ptr, ptr, ptr, i1 %c) { 347; CHECK-LABEL: @test9( 348; CHECK-NEXT: br i1 [[C:%.*]], label [[D1:%.*]], label [[D2:%.*]] 349; CHECK: d1: 350; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP0:%.*]], align 4 351; CHECK-NEXT: br label [[D3:%.*]] 352; CHECK: d2: 353; CHECK-NEXT: [[XXXX:%.*]] = tail call i32 (...) @f1() #[[ATTR0]] 354; CHECK-NEXT: [[B_PR:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[TBAA0]] 355; CHECK-NEXT: br label [[D3]] 356; CHECK: d3: 357; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[B_PR]], [[D2]] ], [ [[A]], [[D1]] ] 358; CHECK-NEXT: [[P:%.*]] = phi i32 [ 1, [[D2]] ], [ [[A]], [[D1]] ] 359; CHECK-NEXT: store i32 [[P]], ptr [[TMP1:%.*]], align 4 360; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[B]], 8 361; CHECK-NEXT: br i1 [[C2]], label [[RET1:%.*]], label [[RET2:%.*]] 362; CHECK: ret1: 363; CHECK-NEXT: ret void 364; CHECK: ret2: 365; CHECK-NEXT: [[XXX:%.*]] = tail call i32 (...) @f1() #[[ATTR0]] 366; CHECK-NEXT: ret void 367; 368 br i1 %c, label %d1, label %d2 369 370d1: 371 %a = load i32, ptr %0, !range !4, !alias.scope !9, !noalias !10 372 br label %d3 373 374d2: 375 %xxxx = tail call i32 (...) @f1() nounwind 376 br label %d3 377 378d3: 379 %p = phi i32 [ 1, %d2 ], [ %a, %d1 ] 380 %b = load i32, ptr %0, !tbaa !0 381 store i32 %p, ptr %1 382 %c2 = icmp eq i32 %b, 8 383 br i1 %c2, label %ret1, label %ret2 384 385ret1: 386 ret void 387 388ret2: 389 %xxx = tail call i32 (...) @f1() nounwind 390 ret void 391} 392 393define i32 @fn_noalias(i1 %c2,ptr noalias %P, ptr noalias %P2) { 394; CHECK-LABEL: @fn_noalias( 395; CHECK-NEXT: entry: 396; CHECK-NEXT: br i1 [[C2:%.*]], label [[COND2:%.*]], label [[COND1:%.*]] 397; CHECK: cond1: 398; CHECK-NEXT: [[L1:%.*]] = load i64, ptr [[P:%.*]], align 4 399; CHECK-NEXT: store i64 42, ptr [[P2:%.*]], align 4 400; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[L1]], 0 401; CHECK-NEXT: br i1 [[C]], label [[COND2_THREAD:%.*]], label [[END:%.*]] 402; CHECK: cond2.thread: 403; CHECK-NEXT: call void @fn2(i64 [[L1]]) 404; CHECK-NEXT: br label [[COND3:%.*]] 405; CHECK: cond2: 406; CHECK-NEXT: [[L2_PR:%.*]] = load i64, ptr [[P]], align 4 407; CHECK-NEXT: call void @fn2(i64 [[L2_PR]]) 408; CHECK-NEXT: [[C3:%.*]] = icmp eq i64 [[L2_PR]], 0 409; CHECK-NEXT: br i1 [[C3]], label [[COND3]], label [[END]] 410; CHECK: cond3: 411; CHECK-NEXT: [[L23:%.*]] = phi i64 [ [[L1]], [[COND2_THREAD]] ], [ [[L2_PR]], [[COND2]] ] 412; CHECK-NEXT: call void @fn3(i64 [[L23]]) 413; CHECK-NEXT: br label [[END]] 414; CHECK: end: 415; CHECK-NEXT: ret i32 0 416; 417entry: 418 br i1 %c2, label %cond2, label %cond1 419 420cond1: 421 %l1 = load i64, ptr %P 422 store i64 42, ptr %P2 423 %c = icmp eq i64 %l1, 0 424 br i1 %c, label %cond2, label %end 425 426cond2: 427 %l2 = load i64, ptr %P 428 call void @fn2(i64 %l2) 429 %c3 = icmp eq i64 %l2, 0 430 br i1 %c3, label %cond3, label %end 431 432cond3: 433 call void @fn3(i64 %l2) 434 br label %end 435 436end: 437 ret i32 0 438} 439 440; This tests if we can thread from %sw.bb.i to %do.body.preheader.i67 through 441; %sw.bb21.i. To make this happen, %l2 should be detected as a partically 442; redundant load with %l3 across the store to %phase in %sw.bb21.i. 443 444%struct.NEXT_MOVE = type { i32, i32, ptr } 445@hash_move = unnamed_addr global [65 x i32] zeroinitializer, align 4 446@current_move = internal global [65 x i32] zeroinitializer, align 4 447@last = internal unnamed_addr global [65 x ptr] zeroinitializer, align 8 448@next_status = internal unnamed_addr global [65 x %struct.NEXT_MOVE] zeroinitializer, align 8 449define fastcc i32 @Search(i64 %idxprom.i, i64 %idxprom.i89, i32 %c) { 450; CHECK-LABEL: @Search( 451; CHECK-NEXT: cond.true282: 452; CHECK-NEXT: [[ARRAYIDX185:%.*]] = getelementptr inbounds [65 x i32], ptr @hash_move, i64 0, i64 [[IDXPROM_I:%.*]] 453; CHECK-NEXT: [[ARRAYIDX307:%.*]] = getelementptr inbounds [65 x i32], ptr @current_move, i64 0, i64 [[IDXPROM_I]] 454; CHECK-NEXT: [[ARRAYIDX89:%.*]] = getelementptr inbounds [65 x ptr], ptr @last, i64 0, i64 [[IDXPROM_I]] 455; CHECK-NEXT: [[PHASE:%.*]] = getelementptr inbounds [65 x %struct.NEXT_MOVE], ptr @next_status, i64 0, i64 [[IDXPROM_I]], i32 0 456; CHECK-NEXT: switch i32 [[C:%.*]], label [[CLEANUP:%.*]] [ 457; CHECK-NEXT: i32 1, label [[SW_BB_I:%.*]] 458; CHECK-NEXT: i32 0, label [[SW_BB21_I:%.*]] 459; CHECK-NEXT: ] 460; CHECK: sw.bb.i: 461; CHECK-NEXT: [[CALL_I62:%.*]] = call fastcc ptr @GenerateCheckEvasions() 462; CHECK-NEXT: store ptr [[CALL_I62]], ptr [[ARRAYIDX89]], align 8 463; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[ARRAYIDX185]], align 4 464; CHECK-NEXT: [[TOBOOL_I63:%.*]] = icmp eq i32 [[L2]], 0 465; CHECK-NEXT: br i1 [[TOBOOL_I63]], label [[SW_BB21_I_THREAD:%.*]], label [[IF_THEN_I64:%.*]] 466; CHECK: sw.bb21.i.thread: 467; CHECK-NEXT: store i32 10, ptr [[PHASE]], align 8 468; CHECK-NEXT: br label [[DO_BODY_PREHEADER_I67:%.*]] 469; CHECK: if.then.i64: 470; CHECK-NEXT: store i32 7, ptr [[PHASE]], align 8 471; CHECK-NEXT: store i32 [[L2]], ptr [[ARRAYIDX307]], align 4 472; CHECK-NEXT: [[CALL16_I:%.*]] = call fastcc i32 @ValidMove(i32 [[L2]]) 473; CHECK-NEXT: [[TOBOOL17_I:%.*]] = icmp eq i32 [[CALL16_I]], 0 474; CHECK-NEXT: br i1 [[TOBOOL17_I]], label [[IF_ELSE_I65:%.*]], label [[CLEANUP]] 475; CHECK: if.else.i65: 476; CHECK-NEXT: call void @f65() 477; CHECK-NEXT: br label [[SW_BB21_I]] 478; CHECK: sw.bb21.i: 479; CHECK-NEXT: [[L3_PR:%.*]] = load i32, ptr [[ARRAYIDX185]], align 4 480; CHECK-NEXT: store i32 10, ptr [[PHASE]], align 8 481; CHECK-NEXT: [[TOBOOL27_I:%.*]] = icmp eq i32 [[L3_PR]], 0 482; CHECK-NEXT: br i1 [[TOBOOL27_I]], label [[DO_BODY_PREHEADER_I67]], label [[CLEANUP]] 483; CHECK: do.body.preheader.i67: 484; CHECK-NEXT: call void @f67() 485; CHECK-NEXT: ret i32 67 486; CHECK: cleanup: 487; CHECK-NEXT: call void @Cleanup() 488; CHECK-NEXT: ret i32 0 489; 490entry: 491 %arrayidx185 = getelementptr inbounds [65 x i32], ptr @hash_move, i64 0, i64 %idxprom.i 492 %arrayidx307 = getelementptr inbounds [65 x i32], ptr @current_move, i64 0, i64 %idxprom.i 493 %arrayidx89 = getelementptr inbounds [65 x ptr], ptr @last, i64 0, i64 %idxprom.i 494 %phase = getelementptr inbounds [65 x %struct.NEXT_MOVE], ptr @next_status, i64 0, i64 %idxprom.i, i32 0 495 br label %cond.true282 496 497cond.true282: 498 switch i32 %c, label %sw.default.i [ 499 i32 1, label %sw.bb.i 500 i32 0, label %sw.bb21.i 501 ] 502 503sw.default.i: 504 br label %cleanup 505 506sw.bb.i: 507 %call.i62 = call fastcc ptr @GenerateCheckEvasions() 508 store ptr %call.i62, ptr %arrayidx89, align 8 509 %l2 = load i32, ptr %arrayidx185, align 4 510 %tobool.i63 = icmp eq i32 %l2, 0 511 br i1 %tobool.i63, label %sw.bb21.i, label %if.then.i64 512 513if.then.i64: ; preds = %sw.bb.i 514 store i32 7, ptr %phase, align 8 515 store i32 %l2, ptr %arrayidx307, align 4 516 %call16.i = call fastcc i32 @ValidMove(i32 %l2) 517 %tobool17.i = icmp eq i32 %call16.i, 0 518 br i1 %tobool17.i, label %if.else.i65, label %cleanup 519 520if.else.i65: 521 call void @f65() 522 br label %sw.bb21.i 523 524sw.bb21.i: 525 store i32 10, ptr %phase, align 8 526 %l3= load i32, ptr %arrayidx185, align 4 527 %tobool27.i = icmp eq i32 %l3, 0 528 br i1 %tobool27.i, label %do.body.preheader.i67, label %cleanup 529 530do.body.preheader.i67: 531 call void @f67() 532 ret i32 67 533 534cleanup: 535 call void @Cleanup() 536 ret i32 0 537} 538 539declare fastcc ptr @GenerateCheckEvasions() 540declare fastcc i32 @ValidMove(i32 %move) 541declare void @f67() 542declare void @Cleanup() 543declare void @f65() 544 545define i32 @fn_SinglePred(i1 %c2,ptr %P) { 546; CHECK-LABEL: @fn_SinglePred( 547; CHECK-NEXT: entry: 548; CHECK-NEXT: [[L1:%.*]] = load i64, ptr [[P:%.*]], align 4 549; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[L1]], 0 550; CHECK-NEXT: br i1 [[C]], label [[COND3:%.*]], label [[COND1:%.*]] 551; CHECK: cond1: 552; CHECK-NEXT: br i1 [[C2:%.*]], label [[COND2:%.*]], label [[END:%.*]] 553; CHECK: cond2: 554; CHECK-NEXT: [[L2:%.*]] = phi i64 [ [[L1]], [[COND1]] ] 555; CHECK-NEXT: call void @fn2(i64 [[L2]]) 556; CHECK-NEXT: br label [[END]] 557; CHECK: cond3: 558; CHECK-NEXT: call void @fn2(i64 [[L1]]) 559; CHECK-NEXT: call void @fn3(i64 [[L1]]) 560; CHECK-NEXT: br label [[END]] 561; CHECK: end: 562; CHECK-NEXT: ret i32 0 563; 564 565entry: 566 %l1 = load i64, ptr %P 567 %c = icmp eq i64 %l1, 0 568 br i1 %c, label %cond2, label %cond1 569 570cond1: 571 br i1 %c2, label %cond2, label %end 572 573cond2: 574 %l2 = load i64, ptr %P 575 call void @fn2(i64 %l2) 576 %c3 = icmp eq i64 %l2, 0 577 br i1 %c3, label %cond3, label %end 578 579cond3: 580 call void @fn3(i64 %l2) 581 br label %end 582 583end: 584 ret i32 0 585} 586 587define i32 @fn_SinglePredMultihop(i1 %c1, i1 %c2,ptr %P) { 588; CHECK-LABEL: @fn_SinglePredMultihop( 589; CHECK-NEXT: entry: 590; CHECK-NEXT: [[L1:%.*]] = load i64, ptr [[P:%.*]], align 4 591; CHECK-NEXT: [[C0:%.*]] = icmp eq i64 [[L1]], 0 592; CHECK-NEXT: br i1 [[C0]], label [[COND3:%.*]], label [[COND0:%.*]] 593; CHECK: cond0: 594; CHECK-NEXT: br i1 [[C1:%.*]], label [[COND1:%.*]], label [[END:%.*]] 595; CHECK: cond1: 596; CHECK-NEXT: br i1 [[C2:%.*]], label [[COND2:%.*]], label [[END]] 597; CHECK: cond2: 598; CHECK-NEXT: [[L2:%.*]] = phi i64 [ [[L1]], [[COND1]] ] 599; CHECK-NEXT: call void @fn2(i64 [[L2]]) 600; CHECK-NEXT: br label [[END]] 601; CHECK: cond3: 602; CHECK-NEXT: call void @fn2(i64 [[L1]]) 603; CHECK-NEXT: call void @fn3(i64 [[L1]]) 604; CHECK-NEXT: br label [[END]] 605; CHECK: end: 606; CHECK-NEXT: ret i32 0 607; 608 609entry: 610 %l1 = load i64, ptr %P 611 %c0 = icmp eq i64 %l1, 0 612 br i1 %c0, label %cond2, label %cond0 613 614cond0: 615 br i1 %c1, label %cond1, label %end 616 617cond1: 618 br i1 %c2, label %cond2, label %end 619 620cond2: 621 %l2 = load i64, ptr %P 622 call void @fn2(i64 %l2) 623 %c3 = icmp eq i64 %l2, 0 624 br i1 %c3, label %cond3, label %end 625 626cond3: 627 call void @fn3(i64 %l2) 628 br label %end 629 630end: 631 ret i32 0 632} 633 634declare void @fn2(i64) 635declare void @fn3(i64) 636 637 638; Make sure we phi-translate and make the partially redundant load in 639; merge fully redudant and then we can jump-thread the block with the 640; store. 641; 642define i32 @phi_translate_partial_redundant_loads(i32, ptr, ptr) { 643; CHECK-LABEL: @phi_translate_partial_redundant_loads( 644; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 645; CHECK-NEXT: br i1 [[CMP0]], label [[MERGE_THREAD:%.*]], label [[MERGE:%.*]] 646; CHECK: merge.thread: 647; CHECK-NEXT: store i32 1, ptr [[TMP1:%.*]], align 4 648; CHECK-NEXT: br label [[LEFT_X:%.*]] 649; CHECK: merge: 650; CHECK-NEXT: [[NEWLOAD_PR:%.*]] = load i32, ptr [[TMP2:%.*]], align 4 651; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[NEWLOAD_PR]], 5 652; CHECK-NEXT: br i1 [[CMP1]], label [[LEFT_X]], label [[RIGHT_X:%.*]] 653; CHECK: left_x: 654; CHECK-NEXT: ret i32 20 655; CHECK: right_x: 656; CHECK-NEXT: ret i32 10 657; 658 %cmp0 = icmp ne i32 %0, 0 659 br i1 %cmp0, label %left, label %right 660 661left: 662 store i32 1, ptr %1, align 4 663 br label %merge 664 665right: 666 br label %merge 667 668merge: 669 %phiptr = phi ptr [ %1, %left ], [ %2, %right ] 670 %newload = load i32, ptr %phiptr, align 4 671 %cmp1 = icmp slt i32 %newload, 5 672 br i1 %cmp1, label %left_x, label %right_x 673 674left_x: 675 ret i32 20 676 677right_x: 678 ret i32 10 679} 680 681 682 683!0 = !{!3, !3, i64 0} 684!1 = !{!"omnipotent char", !2} 685!2 = !{!"Simple C/C++ TBAA"} 686!3 = !{!"int", !1} 687!4 = !{ i32 0, i32 1 } 688!5 = !{ i32 8, i32 10 } 689!6 = !{!6} 690!7 = !{!7, !6} 691!8 = !{!8, !6} 692!9 = !{!7} 693!10 = !{!8} 694!11 = !{} 695;. 696; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0} 697; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]]} 698; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]]} 699; CHECK: [[META3]] = !{!"Simple C/C++ TBAA"} 700; CHECK: [[RNG4]] = !{i32 0, i32 1} 701; CHECK: [[META5]] = !{[[META6:![0-9]+]]} 702; CHECK: [[META6]] = distinct !{[[META6]], [[META7:![0-9]+]]} 703; CHECK: [[META7]] = distinct !{[[META7]]} 704; CHECK: [[META8]] = !{[[META9:![0-9]+]]} 705; CHECK: [[META9]] = distinct !{[[META9]], [[META7]]} 706; CHECK: [[META10]] = !{} 707;. 708