722 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 62; RUN: opt < %s -passes=jump-threading -S | FileCheck %s3; RUN: opt < %s -aa-pipeline=basic-aa -passes=jump-threading -S | FileCheck %s4 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://640203310define i32 @test1(ptr %P) nounwind {11; CHECK-LABEL: define i32 @test1(12; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] {13; CHECK-NEXT: [[ENTRY:.*:]]14; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 (...) @f1() #[[ATTR0]]15; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 016; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB1_THREAD:.*]]17; CHECK: [[BB1_THREAD]]:18; CHECK-NEXT: store i32 42, ptr [[P]], align 419; CHECK-NEXT: br label %[[BB3:.*]]20; CHECK: [[BB1]]:21; CHECK-NEXT: [[DOTPR:%.*]] = load i32, ptr [[P]], align 422; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTPR]], 3623; CHECK-NEXT: br i1 [[TMP2]], label %[[BB3]], label %[[BB2:.*]]24; CHECK: [[BB2]]:25; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 (...) @f2() #[[ATTR0]]26; CHECK-NEXT: ret i32 027; CHECK: [[BB3]]:28; CHECK-NEXT: [[RES_02:%.*]] = phi i32 [ 1, %[[BB1_THREAD]] ], [ 0, %[[BB1]] ]29; CHECK-NEXT: ret i32 [[RES_02]]30;31entry:32 %0 = tail call i32 (...) @f1() nounwind ; <i32> [#uses=1]33 %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]34 br i1 %1, label %bb1, label %bb35 36bb: ; preds = %entry37 store i32 42, ptr %P, align 438 br label %bb139 40bb1: ; preds = %entry, %bb41 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ] ; <i32> [#uses=2]42 %2 = load i32, ptr %P, align 4 ; <i32> [#uses=1]43 %3 = icmp sgt i32 %2, 36 ; <i1> [#uses=1]44 br i1 %3, label %bb3, label %bb245 46bb2: ; preds = %bb147 %4 = tail call i32 (...) @f2() nounwind ; <i32> [#uses=0]48 ret i32 %res.049 50bb3: ; preds = %bb151 ret i32 %res.052}53 54declare i32 @f1(...)55 56declare i32 @f2(...)57 58 59;; Check that we preserve TBAA information.60; rdar://1103925861 62define i32 @test2(ptr %P) nounwind {63; CHECK-LABEL: define i32 @test2(64; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0]] {65; CHECK-NEXT: [[ENTRY:.*:]]66; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 (...) @f1() #[[ATTR0]]67; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 068; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB1_THREAD:.*]]69; CHECK: [[BB1_THREAD]]:70; CHECK-NEXT: store i32 42, ptr [[P]], align 4, !tbaa [[INT_TBAA0:![0-9]+]]71; CHECK-NEXT: br label %[[BB3:.*]]72; CHECK: [[BB1]]:73; CHECK-NEXT: [[DOTPR:%.*]] = load i32, ptr [[P]], align 4, !tbaa [[INT_TBAA0]]74; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTPR]], 3675; CHECK-NEXT: br i1 [[TMP2]], label %[[BB3]], label %[[BB2:.*]]76; CHECK: [[BB2]]:77; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 (...) @f2() #[[ATTR0]]78; CHECK-NEXT: ret i32 079; CHECK: [[BB3]]:80; CHECK-NEXT: [[RES_02:%.*]] = phi i32 [ 1, %[[BB1_THREAD]] ], [ 0, %[[BB1]] ]81; CHECK-NEXT: ret i32 [[RES_02]]82;83entry:84 %0 = tail call i32 (...) @f1() nounwind ; <i32> [#uses=1]85 %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]86 br i1 %1, label %bb1, label %bb87 88bb: ; preds = %entry89 store i32 42, ptr %P, align 4, !tbaa !090 br label %bb191 92bb1: ; preds = %entry, %bb93 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]94 %2 = load i32, ptr %P, align 4, !tbaa !095 %3 = icmp sgt i32 %2, 3696 br i1 %3, label %bb3, label %bb297 98bb2: ; preds = %bb199 %4 = tail call i32 (...) @f2() nounwind100 ret i32 %res.0101 102bb3: ; preds = %bb1103 ret i32 %res.0104}105 106define i32 @test3(ptr %x, i1 %f) {107; Correctly thread loads of different (but compatible) types, placing bitcasts108; as necessary in the predecessors. This is especially tricky because the same109; predecessor ends up with two entries in the PHI node and they must share110; a single cast.111; CHECK-LABEL: define i32 @test3(112; CHECK-SAME: ptr [[X:%.*]], i1 [[F:%.*]]) {113; CHECK-NEXT: [[ENTRY:.*]]:114; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[X]], align 8115; CHECK-NEXT: br i1 [[F]], label %[[IF_END57:.*]], label %[[IF_END57]]116; CHECK: [[IF_END57]]:117; CHECK-NEXT: [[TMP3:%.*]] = phi ptr [ [[TMP1]], %[[ENTRY]] ], [ [[TMP1]], %[[ENTRY]] ]118; CHECK-NEXT: [[TOBOOL59:%.*]] = icmp eq ptr [[TMP3]], null119; CHECK-NEXT: br i1 [[TOBOOL59]], label %[[RETURN:.*]], label %[[IF_THEN60:.*]]120; CHECK: [[IF_THEN60]]:121; CHECK-NEXT: ret i32 42122; CHECK: [[RETURN]]:123; CHECK-NEXT: ret i32 13124;125entry:126 %0 = load ptr, ptr %x, align 8127 br i1 %f, label %if.end57, label %if.then56128 129if.then56:130 br label %if.end57131 132if.end57:133 %1 = load ptr, ptr %x, align 8134 %tobool59 = icmp eq ptr %1, null135 br i1 %tobool59, label %return, label %if.then60136 137if.then60:138 ret i32 42139 140return:141 ret i32 13142}143 144define i32 @test4(ptr %P) {145; CHECK-LABEL: define i32 @test4(146; CHECK-SAME: ptr [[P:%.*]]) {147; CHECK-NEXT: [[ENTRY:.*:]]148; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1()149; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0150; CHECK-NEXT: br i1 [[V1]], label %[[BB1:.*]], label %[[BB1_THREAD:.*]]151; CHECK: [[BB1_THREAD]]:152; CHECK-NEXT: store atomic i32 42, ptr [[P]] unordered, align 4153; CHECK-NEXT: br label %[[BB3:.*]]154; CHECK: [[BB1]]:155; CHECK-NEXT: [[V2_PR:%.*]] = load atomic i32, ptr [[P]] unordered, align 4156; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2_PR]], 36157; CHECK-NEXT: br i1 [[V3]], label %[[BB3]], label %[[BB2:.*]]158; CHECK: [[BB2]]:159; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2()160; CHECK-NEXT: ret i32 0161; CHECK: [[BB3]]:162; CHECK-NEXT: [[RES_04:%.*]] = phi i32 [ 1, %[[BB1_THREAD]] ], [ 0, %[[BB1]] ]163; CHECK-NEXT: ret i32 [[RES_04]]164;165entry:166 %v0 = tail call i32 (...) @f1()167 %v1 = icmp eq i32 %v0, 0168 br i1 %v1, label %bb1, label %bb169 170bb:171 store atomic i32 42, ptr %P unordered, align 4172 br label %bb1173 174bb1:175 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]176 %v2 = load atomic i32, ptr %P unordered, align 4177 %v3 = icmp sgt i32 %v2, 36178 br i1 %v3, label %bb3, label %bb2179 180bb2:181 %v4 = tail call i32 (...) @f2()182 ret i32 %res.0183 184bb3:185 ret i32 %res.0186}187 188define i32 @test5(ptr %P) {189; Negative test190; CHECK-LABEL: define i32 @test5(191; CHECK-SAME: ptr [[P:%.*]]) {192; CHECK-NEXT: [[ENTRY:.*]]:193; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1()194; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0195; CHECK-NEXT: br i1 [[V1]], label %[[BB1:.*]], label %[[BB:.*]]196; CHECK: [[BB]]:197; CHECK-NEXT: store atomic i32 42, ptr [[P]] release, align 4198; CHECK-NEXT: br label %[[BB1]]199; CHECK: [[BB1]]:200; CHECK-NEXT: [[RES_0:%.*]] = phi i32 [ 1, %[[BB]] ], [ 0, %[[ENTRY]] ]201; CHECK-NEXT: [[V2:%.*]] = load atomic i32, ptr [[P]] acquire, align 4202; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2]], 36203; CHECK-NEXT: br i1 [[V3]], label %[[BB3:.*]], label %[[BB2:.*]]204; CHECK: [[BB2]]:205; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2()206; CHECK-NEXT: ret i32 [[RES_0]]207; CHECK: [[BB3]]:208; CHECK-NEXT: ret i32 [[RES_0]]209;210entry:211 %v0 = tail call i32 (...) @f1()212 %v1 = icmp eq i32 %v0, 0213 br i1 %v1, label %bb1, label %bb214 215bb:216 store atomic i32 42, ptr %P release, align 4217 br label %bb1218 219bb1:220 221 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]222 %v2 = load atomic i32, ptr %P acquire, align 4223 %v3 = icmp sgt i32 %v2, 36224 br i1 %v3, label %bb3, label %bb2225 226bb2:227 %v4 = tail call i32 (...) @f2()228 ret i32 %res.0229 230bb3:231 ret i32 %res.0232}233 234define i32 @test6(ptr %P) {235; Negative test236; CHECK-LABEL: define i32 @test6(237; CHECK-SAME: ptr [[P:%.*]]) {238; CHECK-NEXT: [[ENTRY:.*]]:239; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1()240; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0241; CHECK-NEXT: br i1 [[V1]], label %[[BB1:.*]], label %[[BB:.*]]242; CHECK: [[BB]]:243; CHECK-NEXT: store i32 42, ptr [[P]], align 4244; CHECK-NEXT: br label %[[BB1]]245; CHECK: [[BB1]]:246; CHECK-NEXT: [[RES_0:%.*]] = phi i32 [ 1, %[[BB]] ], [ 0, %[[ENTRY]] ]247; CHECK-NEXT: [[V2:%.*]] = load atomic i32, ptr [[P]] acquire, align 4248; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2]], 36249; CHECK-NEXT: br i1 [[V3]], label %[[BB3:.*]], label %[[BB2:.*]]250; CHECK: [[BB2]]:251; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2()252; CHECK-NEXT: ret i32 [[RES_0]]253; CHECK: [[BB3]]:254; CHECK-NEXT: ret i32 [[RES_0]]255;256entry:257 %v0 = tail call i32 (...) @f1()258 %v1 = icmp eq i32 %v0, 0259 br i1 %v1, label %bb1, label %bb260 261bb:262 store i32 42, ptr %P263 br label %bb1264 265bb1:266 267 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]268 %v2 = load atomic i32, ptr %P acquire, align 4269 %v3 = icmp sgt i32 %v2, 36270 br i1 %v3, label %bb3, label %bb2271 272bb2:273 %v4 = tail call i32 (...) @f2()274 ret i32 %res.0275 276bb3:277 ret i32 %res.0278}279 280define i32 @test7(ptr %P) {281; Negative test282; CHECK-LABEL: define i32 @test7(283; CHECK-SAME: ptr [[P:%.*]]) {284; CHECK-NEXT: [[ENTRY:.*]]:285; CHECK-NEXT: [[V0:%.*]] = tail call i32 (...) @f1()286; CHECK-NEXT: [[V1:%.*]] = icmp eq i32 [[V0]], 0287; CHECK-NEXT: br i1 [[V1]], label %[[BB1:.*]], label %[[BB:.*]]288; CHECK: [[BB]]:289; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P]], align 4290; CHECK-NEXT: br label %[[BB1]]291; CHECK: [[BB1]]:292; CHECK-NEXT: [[RES_0:%.*]] = phi i32 [ 1, %[[BB]] ], [ 0, %[[ENTRY]] ]293; CHECK-NEXT: [[V2:%.*]] = load atomic i32, ptr [[P]] acquire, align 4294; CHECK-NEXT: [[V3:%.*]] = icmp sgt i32 [[V2]], 36295; CHECK-NEXT: br i1 [[V3]], label %[[BB3:.*]], label %[[BB2:.*]]296; CHECK: [[BB2]]:297; CHECK-NEXT: [[V4:%.*]] = tail call i32 (...) @f2()298; CHECK-NEXT: ret i32 [[RES_0]]299; CHECK: [[BB3]]:300; CHECK-NEXT: ret i32 [[RES_0]]301;302entry:303 %v0 = tail call i32 (...) @f1()304 %v1 = icmp eq i32 %v0, 0305 br i1 %v1, label %bb1, label %bb306 307bb:308 %val = load i32, ptr %P309 br label %bb1310 311bb1:312 313 %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]314 %v2 = load atomic i32, ptr %P acquire, align 4315 %v3 = icmp sgt i32 %v2, 36316 br i1 %v3, label %bb3, label %bb2317 318bb2:319 %v4 = tail call i32 (...) @f2()320 ret i32 %res.0321 322bb3:323 ret i32 %res.0324}325 326; We keep the tbaa and range metadata for the first load, as it dominates the327; second load. Hence we can eliminate the branch.328define void @test8(ptr, ptr, ptr) {329; CHECK-LABEL: define void @test8(330; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) {331; CHECK-NEXT: [[RET2:.*:]]332; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[INT_TBAA0]], !range [[RNG4:![0-9]+]], !alias.scope [[META5:![0-9]+]], !noalias [[META8:![0-9]+]], !noundef [[META10:![0-9]+]]333; CHECK-NEXT: store i32 [[A]], ptr [[TMP1]], align 4334; CHECK-NEXT: [[XXX:%.*]] = tail call i32 (...) @f1() #[[ATTR0]]335; CHECK-NEXT: ret void336;337 %a = load i32, ptr %0, !tbaa !0, !range !4, !alias.scope !9, !noalias !10, !noundef !11338 %b = load i32, ptr %0, !range !5339 store i32 %a, ptr %1340 %c = icmp eq i32 %b, 8341 br i1 %c, label %ret1, label %ret2342 343ret1:344 ret void345 346ret2:347 %xxx = tail call i32 (...) @f1() nounwind348 ret void349}350 351; Make sure we merge/PRE aliasing metadata correctly. That means that352; we need to remove metadata from the existing load, and add appropriate353; metadata to the newly inserted load.354define void @test9(ptr, ptr, ptr, i1 %c) {355; CHECK-LABEL: define void @test9(356; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]], i1 [[C:%.*]]) {357; CHECK-NEXT: br i1 [[C]], label %[[D1:.*]], label %[[D2:.*]]358; CHECK: [[D1]]:359; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP0]], align 4360; CHECK-NEXT: br label %[[D3:.*]]361; CHECK: [[D2]]:362; CHECK-NEXT: [[XXXX:%.*]] = tail call i32 (...) @f1() #[[ATTR0]]363; CHECK-NEXT: [[B_PR:%.*]] = load i32, ptr [[TMP0]], align 4, !tbaa [[INT_TBAA0]]364; CHECK-NEXT: br label %[[D3]]365; CHECK: [[D3]]:366; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[B_PR]], %[[D2]] ], [ [[A]], %[[D1]] ]367; CHECK-NEXT: [[P:%.*]] = phi i32 [ 1, %[[D2]] ], [ [[A]], %[[D1]] ]368; CHECK-NEXT: store i32 [[P]], ptr [[TMP1]], align 4369; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[B]], 8370; CHECK-NEXT: br i1 [[C2]], label %[[RET1:.*]], label %[[RET2:.*]]371; CHECK: [[RET1]]:372; CHECK-NEXT: ret void373; CHECK: [[RET2]]:374; CHECK-NEXT: [[XXX:%.*]] = tail call i32 (...) @f1() #[[ATTR0]]375; CHECK-NEXT: ret void376;377 br i1 %c, label %d1, label %d2378 379d1:380 %a = load i32, ptr %0, !range !4, !alias.scope !9, !noalias !10381 br label %d3382 383d2:384 %xxxx = tail call i32 (...) @f1() nounwind385 br label %d3386 387d3:388 %p = phi i32 [ 1, %d2 ], [ %a, %d1 ]389 %b = load i32, ptr %0, !tbaa !0390 store i32 %p, ptr %1391 %c2 = icmp eq i32 %b, 8392 br i1 %c2, label %ret1, label %ret2393 394ret1:395 ret void396 397ret2:398 %xxx = tail call i32 (...) @f1() nounwind399 ret void400}401 402define i32 @fn_noalias(i1 %c2,ptr noalias %P, ptr noalias %P2) {403; CHECK-LABEL: define i32 @fn_noalias(404; CHECK-SAME: i1 [[C2:%.*]], ptr noalias [[P:%.*]], ptr noalias [[P2:%.*]]) {405; CHECK-NEXT: [[ENTRY:.*:]]406; CHECK-NEXT: br i1 [[C2]], label %[[COND2:.*]], label %[[COND1:.*]]407; CHECK: [[COND1]]:408; CHECK-NEXT: [[L1:%.*]] = load i64, ptr [[P]], align 4409; CHECK-NEXT: store i64 42, ptr [[P2]], align 4410; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[L1]], 0411; CHECK-NEXT: br i1 [[C]], label %[[COND2_THREAD:.*]], label %[[END:.*]]412; CHECK: [[COND2_THREAD]]:413; CHECK-NEXT: call void @fn2(i64 [[L1]])414; CHECK-NEXT: br label %[[COND3:.*]]415; CHECK: [[COND2]]:416; CHECK-NEXT: [[L2_PR:%.*]] = load i64, ptr [[P]], align 4417; CHECK-NEXT: call void @fn2(i64 [[L2_PR]])418; CHECK-NEXT: [[C3:%.*]] = icmp eq i64 [[L2_PR]], 0419; CHECK-NEXT: br i1 [[C3]], label %[[COND3]], label %[[END]]420; CHECK: [[COND3]]:421; CHECK-NEXT: [[L23:%.*]] = phi i64 [ [[L1]], %[[COND2_THREAD]] ], [ [[L2_PR]], %[[COND2]] ]422; CHECK-NEXT: call void @fn3(i64 [[L23]])423; CHECK-NEXT: br label %[[END]]424; CHECK: [[END]]:425; CHECK-NEXT: ret i32 0426;427entry:428 br i1 %c2, label %cond2, label %cond1429 430cond1:431 %l1 = load i64, ptr %P432 store i64 42, ptr %P2433 %c = icmp eq i64 %l1, 0434 br i1 %c, label %cond2, label %end435 436cond2:437 %l2 = load i64, ptr %P438 call void @fn2(i64 %l2)439 %c3 = icmp eq i64 %l2, 0440 br i1 %c3, label %cond3, label %end441 442cond3:443 call void @fn3(i64 %l2)444 br label %end445 446end:447 ret i32 0448}449 450; This tests if we can thread from %sw.bb.i to %do.body.preheader.i67 through451; %sw.bb21.i. To make this happen, %l2 should be detected as a partically452; redundant load with %l3 across the store to %phase in %sw.bb21.i.453 454%struct.NEXT_MOVE = type { i32, i32, ptr }455@hash_move = unnamed_addr global [65 x i32] zeroinitializer, align 4456@current_move = internal global [65 x i32] zeroinitializer, align 4457@last = internal unnamed_addr global [65 x ptr] zeroinitializer, align 8458@next_status = internal unnamed_addr global [65 x %struct.NEXT_MOVE] zeroinitializer, align 8459define fastcc i32 @Search(i64 %idxprom.i, i64 %idxprom.i89, i32 %c) {460; CHECK-LABEL: define fastcc i32 @Search(461; CHECK-SAME: i64 [[IDXPROM_I:%.*]], i64 [[IDXPROM_I89:%.*]], i32 [[C:%.*]]) {462; CHECK-NEXT: [[COND_TRUE282:.*:]]463; CHECK-NEXT: [[ARRAYIDX185:%.*]] = getelementptr inbounds [65 x i32], ptr @hash_move, i64 0, i64 [[IDXPROM_I]]464; CHECK-NEXT: [[ARRAYIDX307:%.*]] = getelementptr inbounds [65 x i32], ptr @current_move, i64 0, i64 [[IDXPROM_I]]465; CHECK-NEXT: [[ARRAYIDX89:%.*]] = getelementptr inbounds [65 x ptr], ptr @last, i64 0, i64 [[IDXPROM_I]]466; CHECK-NEXT: [[PHASE:%.*]] = getelementptr inbounds [65 x %struct.NEXT_MOVE], ptr @next_status, i64 0, i64 [[IDXPROM_I]], i32 0467; CHECK-NEXT: switch i32 [[C]], label %[[CLEANUP:.*]] [468; CHECK-NEXT: i32 1, label %[[SW_BB_I:.*]]469; CHECK-NEXT: i32 0, label %[[SW_BB21_I:.*]]470; CHECK-NEXT: ]471; CHECK: [[SW_BB_I]]:472; CHECK-NEXT: [[CALL_I62:%.*]] = call fastcc ptr @GenerateCheckEvasions()473; CHECK-NEXT: store ptr [[CALL_I62]], ptr [[ARRAYIDX89]], align 8474; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[ARRAYIDX185]], align 4475; CHECK-NEXT: [[TOBOOL_I63:%.*]] = icmp eq i32 [[L2]], 0476; CHECK-NEXT: br i1 [[TOBOOL_I63]], label %[[SW_BB21_I_THREAD:.*]], label %[[IF_THEN_I64:.*]]477; CHECK: [[SW_BB21_I_THREAD]]:478; CHECK-NEXT: store i32 10, ptr [[PHASE]], align 8479; CHECK-NEXT: br label %[[DO_BODY_PREHEADER_I67:.*]]480; CHECK: [[IF_THEN_I64]]:481; CHECK-NEXT: store i32 7, ptr [[PHASE]], align 8482; CHECK-NEXT: store i32 [[L2]], ptr [[ARRAYIDX307]], align 4483; CHECK-NEXT: [[CALL16_I:%.*]] = call fastcc i32 @ValidMove(i32 [[L2]])484; CHECK-NEXT: [[TOBOOL17_I:%.*]] = icmp eq i32 [[CALL16_I]], 0485; CHECK-NEXT: br i1 [[TOBOOL17_I]], label %[[IF_ELSE_I65:.*]], label %[[CLEANUP]]486; CHECK: [[IF_ELSE_I65]]:487; CHECK-NEXT: call void @f65()488; CHECK-NEXT: br label %[[SW_BB21_I]]489; CHECK: [[SW_BB21_I]]:490; CHECK-NEXT: [[L3_PR:%.*]] = load i32, ptr [[ARRAYIDX185]], align 4491; CHECK-NEXT: store i32 10, ptr [[PHASE]], align 8492; CHECK-NEXT: [[TOBOOL27_I:%.*]] = icmp eq i32 [[L3_PR]], 0493; CHECK-NEXT: br i1 [[TOBOOL27_I]], label %[[DO_BODY_PREHEADER_I67]], label %[[CLEANUP]]494; CHECK: [[DO_BODY_PREHEADER_I67]]:495; CHECK-NEXT: call void @f67()496; CHECK-NEXT: ret i32 67497; CHECK: [[CLEANUP]]:498; CHECK-NEXT: call void @Cleanup()499; CHECK-NEXT: ret i32 0500;501entry:502 %arrayidx185 = getelementptr inbounds [65 x i32], ptr @hash_move, i64 0, i64 %idxprom.i503 %arrayidx307 = getelementptr inbounds [65 x i32], ptr @current_move, i64 0, i64 %idxprom.i504 %arrayidx89 = getelementptr inbounds [65 x ptr], ptr @last, i64 0, i64 %idxprom.i505 %phase = getelementptr inbounds [65 x %struct.NEXT_MOVE], ptr @next_status, i64 0, i64 %idxprom.i, i32 0506 br label %cond.true282507 508cond.true282:509 switch i32 %c, label %sw.default.i [510 i32 1, label %sw.bb.i511 i32 0, label %sw.bb21.i512 ]513 514sw.default.i:515 br label %cleanup516 517sw.bb.i:518 %call.i62 = call fastcc ptr @GenerateCheckEvasions()519 store ptr %call.i62, ptr %arrayidx89, align 8520 %l2 = load i32, ptr %arrayidx185, align 4521 %tobool.i63 = icmp eq i32 %l2, 0522 br i1 %tobool.i63, label %sw.bb21.i, label %if.then.i64523 524if.then.i64: ; preds = %sw.bb.i525 store i32 7, ptr %phase, align 8526 store i32 %l2, ptr %arrayidx307, align 4527 %call16.i = call fastcc i32 @ValidMove(i32 %l2)528 %tobool17.i = icmp eq i32 %call16.i, 0529 br i1 %tobool17.i, label %if.else.i65, label %cleanup530 531if.else.i65:532 call void @f65()533 br label %sw.bb21.i534 535sw.bb21.i:536 store i32 10, ptr %phase, align 8537 %l3= load i32, ptr %arrayidx185, align 4538 %tobool27.i = icmp eq i32 %l3, 0539 br i1 %tobool27.i, label %do.body.preheader.i67, label %cleanup540 541do.body.preheader.i67:542 call void @f67()543 ret i32 67544 545cleanup:546 call void @Cleanup()547 ret i32 0548}549 550declare fastcc ptr @GenerateCheckEvasions()551declare fastcc i32 @ValidMove(i32 %move)552declare void @f67()553declare void @Cleanup()554declare void @f65()555 556define i32 @fn_SinglePred(i1 %c2,ptr %P) {557; CHECK-LABEL: define i32 @fn_SinglePred(558; CHECK-SAME: i1 [[C2:%.*]], ptr [[P:%.*]]) {559; CHECK-NEXT: [[ENTRY:.*:]]560; CHECK-NEXT: [[L1:%.*]] = load i64, ptr [[P]], align 4561; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[L1]], 0562; CHECK-NEXT: br i1 [[C]], label %[[COND3:.*]], label %[[COND1:.*]]563; CHECK: [[COND1]]:564; CHECK-NEXT: br i1 [[C2]], label %[[COND2:.*]], label %[[END:.*]]565; CHECK: [[COND2]]:566; CHECK-NEXT: [[L2:%.*]] = phi i64 [ [[L1]], %[[COND1]] ]567; CHECK-NEXT: call void @fn2(i64 [[L2]])568; CHECK-NEXT: br label %[[END]]569; CHECK: [[COND3]]:570; CHECK-NEXT: call void @fn2(i64 [[L1]])571; CHECK-NEXT: call void @fn3(i64 [[L1]])572; CHECK-NEXT: br label %[[END]]573; CHECK: [[END]]:574; CHECK-NEXT: ret i32 0575;576 577entry:578 %l1 = load i64, ptr %P579 %c = icmp eq i64 %l1, 0580 br i1 %c, label %cond2, label %cond1581 582cond1:583 br i1 %c2, label %cond2, label %end584 585cond2:586 %l2 = load i64, ptr %P587 call void @fn2(i64 %l2)588 %c3 = icmp eq i64 %l2, 0589 br i1 %c3, label %cond3, label %end590 591cond3:592 call void @fn3(i64 %l2)593 br label %end594 595end:596 ret i32 0597}598 599define i32 @fn_SinglePredMultihop(i1 %c1, i1 %c2,ptr %P) {600; CHECK-LABEL: define i32 @fn_SinglePredMultihop(601; CHECK-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]], ptr [[P:%.*]]) {602; CHECK-NEXT: [[ENTRY:.*:]]603; CHECK-NEXT: [[L1:%.*]] = load i64, ptr [[P]], align 4604; CHECK-NEXT: [[C0:%.*]] = icmp eq i64 [[L1]], 0605; CHECK-NEXT: br i1 [[C0]], label %[[COND3:.*]], label %[[COND0:.*]]606; CHECK: [[COND0]]:607; CHECK-NEXT: br i1 [[C1]], label %[[COND1:.*]], label %[[END:.*]]608; CHECK: [[COND1]]:609; CHECK-NEXT: br i1 [[C2]], label %[[COND2:.*]], label %[[END]]610; CHECK: [[COND2]]:611; CHECK-NEXT: [[L2:%.*]] = phi i64 [ [[L1]], %[[COND1]] ]612; CHECK-NEXT: call void @fn2(i64 [[L2]])613; CHECK-NEXT: br label %[[END]]614; CHECK: [[COND3]]:615; CHECK-NEXT: call void @fn2(i64 [[L1]])616; CHECK-NEXT: call void @fn3(i64 [[L1]])617; CHECK-NEXT: br label %[[END]]618; CHECK: [[END]]:619; CHECK-NEXT: ret i32 0620;621 622entry:623 %l1 = load i64, ptr %P624 %c0 = icmp eq i64 %l1, 0625 br i1 %c0, label %cond2, label %cond0626 627cond0:628 br i1 %c1, label %cond1, label %end629 630cond1:631 br i1 %c2, label %cond2, label %end632 633cond2:634 %l2 = load i64, ptr %P635 call void @fn2(i64 %l2)636 %c3 = icmp eq i64 %l2, 0637 br i1 %c3, label %cond3, label %end638 639cond3:640 call void @fn3(i64 %l2)641 br label %end642 643end:644 ret i32 0645}646 647declare void @fn2(i64)648declare void @fn3(i64)649 650 651; Make sure we phi-translate and make the partially redundant load in652; merge fully redundant and then we can jump-thread the block with the653; store.654;655define i32 @phi_translate_partial_redundant_loads(i32, ptr, ptr) {656; CHECK-LABEL: define i32 @phi_translate_partial_redundant_loads(657; CHECK-SAME: i32 [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) {658; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i32 [[TMP0]], 0659; CHECK-NEXT: br i1 [[CMP0]], label %[[MERGE_THREAD:.*]], label %[[MERGE:.*]]660; CHECK: [[MERGE_THREAD]]:661; CHECK-NEXT: store i32 1, ptr [[TMP1]], align 4662; CHECK-NEXT: br label %[[LEFT_X:.*]]663; CHECK: [[MERGE]]:664; CHECK-NEXT: [[NEWLOAD_PR:%.*]] = load i32, ptr [[TMP2]], align 4665; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[NEWLOAD_PR]], 5666; CHECK-NEXT: br i1 [[CMP1]], label %[[LEFT_X]], label %[[RIGHT_X:.*]]667; CHECK: [[LEFT_X]]:668; CHECK-NEXT: ret i32 20669; CHECK: [[RIGHT_X]]:670; CHECK-NEXT: ret i32 10671;672 %cmp0 = icmp ne i32 %0, 0673 br i1 %cmp0, label %left, label %right674 675left:676 store i32 1, ptr %1, align 4677 br label %merge678 679right:680 br label %merge681 682merge:683 %phiptr = phi ptr [ %1, %left ], [ %2, %right ]684 %newload = load i32, ptr %phiptr, align 4685 %cmp1 = icmp slt i32 %newload, 5686 br i1 %cmp1, label %left_x, label %right_x687 688left_x:689 ret i32 20690 691right_x:692 ret i32 10693}694 695 696 697!0 = !{!3, !3, i64 0}698!1 = !{!"omnipotent char", !2}699!2 = !{!"Simple C/C++ TBAA"}700!3 = !{!"int", !1}701!4 = !{ i32 0, i32 1 }702!5 = !{ i32 8, i32 10 }703!6 = !{!6}704!7 = !{!7, !6}705!8 = !{!8, !6}706!9 = !{!7}707!10 = !{!8}708!11 = !{}709;.710; CHECK: [[INT_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}711; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]]}712; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]]}713; CHECK: [[META3]] = !{!"Simple C/C++ TBAA"}714; CHECK: [[RNG4]] = !{i32 0, i32 1}715; CHECK: [[META5]] = !{[[META6:![0-9]+]]}716; CHECK: [[META6]] = distinct !{[[META6]], [[META7:![0-9]+]]}717; CHECK: [[META7]] = distinct !{[[META7]]}718; CHECK: [[META8]] = !{[[META9:![0-9]+]]}719; CHECK: [[META9]] = distinct !{[[META9]], [[META7]]}720; CHECK: [[META10]] = !{}721;.722