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