1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s 3; 4; The branch in the latch do.cond is conditional by a constant and the 5; conditional branch replaced by an unconditional one. 6; Ensure that the llvm.loop metadata is transferred to the new branch 7; (In for.cond.cleanup after further simplifications). 8; 9; llvm.org/PR50060 10; 11 12@n = dso_local global i32 0, align 4 13@C = dso_local global i32 0, align 4 14 15; Function Attrs: nounwind 16define dso_local void @_Z6test01v() addrspace(1) #0 { 17; CHECK-LABEL: @_Z6test01v( 18; CHECK-NEXT: entry: 19; CHECK-NEXT: [[J:%.*]] = alloca i32, align 4 20; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 21; CHECK-NEXT: br label [[DO_BODY:%.*]] 22; CHECK: do.body: 23; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @C, align 4, !tbaa [[TBAA2:![0-9]+]] 24; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1 25; CHECK-NEXT: call addrspace(1) void @llvm.lifetime.start.p0(i64 4, ptr [[J]]) #[[ATTR2:[0-9]+]] 26; CHECK-NEXT: store i32 0, ptr [[J]], align 4, !tbaa [[TBAA2]] 27; CHECK-NEXT: br label [[FOR_COND:%.*]] 28; CHECK: for.cond: 29; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[J]], align 4, !tbaa [[TBAA2]] 30; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 3 31; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] 32; CHECK: for.cond.cleanup: 33; CHECK-NEXT: call addrspace(1) void @llvm.lifetime.end.p0(i64 4, ptr [[J]]) #[[ATTR2]] 34; CHECK-NEXT: br label [[DO_BODY]], !llvm.loop [[LOOP6:![0-9]+]] 35; CHECK: for.body: 36; CHECK-NEXT: store i32 undef, ptr [[I]], align 4 37; CHECK-NEXT: call addrspace(1) void @llvm.lifetime.start.p0(i64 4, ptr [[I]]) #[[ATTR2]] 38; CHECK-NEXT: store i32 0, ptr [[I]], align 4, !tbaa [[TBAA2]] 39; CHECK-NEXT: br label [[FOR_COND1:%.*]] 40; CHECK: for.cond1: 41; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4, !tbaa [[TBAA2]] 42; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr @n, align 4, !tbaa [[TBAA2]] 43; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP2]], [[TMP3]] 44; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY4:%.*]], label [[FOR_COND_CLEANUP3:%.*]] 45; CHECK: for.cond.cleanup3: 46; CHECK-NEXT: call addrspace(1) void @llvm.lifetime.end.p0(i64 4, ptr [[I]]) #[[ATTR2]] 47; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[J]], align 4, !tbaa [[TBAA2]] 48; CHECK-NEXT: [[INC7:%.*]] = add nsw i32 [[TMP4]], 1 49; CHECK-NEXT: store i32 [[INC7]], ptr [[J]], align 4, !tbaa [[TBAA2]] 50; CHECK-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP8:![0-9]+]] 51; CHECK: for.body4: 52; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[I]], align 4, !tbaa [[TBAA2]] 53; CHECK-NEXT: store volatile i32 [[TMP5]], ptr @C, align 4, !tbaa [[TBAA2]] 54; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[I]], align 4, !tbaa [[TBAA2]] 55; CHECK-NEXT: [[INC5:%.*]] = add nsw i32 [[TMP6]], 1 56; CHECK-NEXT: store i32 [[INC5]], ptr [[I]], align 4, !tbaa [[TBAA2]] 57; CHECK-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP11:![0-9]+]] 58; 59entry: 60 %j = alloca i32, align 4 61 %i = alloca i32, align 4 62 br label %do.body 63 64do.body: ; preds = %do.cond, %entry 65 %0 = load i32, ptr @C, align 4, !tbaa !2 66 %inc = add nsw i32 %0, 1 67 call addrspace(1) void @llvm.lifetime.start.p0(i64 4, ptr %j) #2 68 store i32 0, ptr %j, align 4, !tbaa !2 69 br label %for.cond 70 71for.cond: ; preds = %for.inc6, %do.body 72 %1 = load i32, ptr %j, align 4, !tbaa !2 73 %cmp = icmp slt i32 %1, 3 74 br i1 %cmp, label %for.body, label %for.cond.cleanup 75 76for.cond.cleanup: ; preds = %for.cond 77 call addrspace(1) void @llvm.lifetime.end.p0(i64 4, ptr %j) #2 78 br label %for.end8 79 80for.body: ; preds = %for.cond 81 store i32 undef, ptr %i, align 4 82 call addrspace(1) void @llvm.lifetime.start.p0(i64 4, ptr %i) #2 83 store i32 0, ptr %i, align 4, !tbaa !2 84 br label %for.cond1 85 86for.cond1: ; preds = %for.inc, %for.body 87 %2 = load i32, ptr %i, align 4, !tbaa !2 88 %3 = load i32, ptr @n, align 4, !tbaa !2 89 %cmp2 = icmp slt i32 %2, %3 90 br i1 %cmp2, label %for.body4, label %for.cond.cleanup3 91 92for.cond.cleanup3: ; preds = %for.cond1 93 call addrspace(1) void @llvm.lifetime.end.p0(i64 4, ptr %i) #2 94 br label %for.end 95 96for.body4: ; preds = %for.cond1 97 %4 = load i32, ptr %i, align 4, !tbaa !2 98 store volatile i32 %4, ptr @C, align 4, !tbaa !2 99 br label %for.inc 100 101for.inc: ; preds = %for.body4 102 %5 = load i32, ptr %i, align 4, !tbaa !2 103 %inc5 = add nsw i32 %5, 1 104 store i32 %inc5, ptr %i, align 4, !tbaa !2 105 br label %for.cond1, !llvm.loop !6 106 107for.end: ; preds = %for.cond.cleanup3 108 br label %for.inc6 109 110for.inc6: ; preds = %for.end 111 %6 = load i32, ptr %j, align 4, !tbaa !2 112 %inc7 = add nsw i32 %6, 1 113 store i32 %inc7, ptr %j, align 4, !tbaa !2 114 br label %for.cond, !llvm.loop !8 115 116for.end8: ; preds = %for.cond.cleanup 117 br label %do.cond 118 119do.cond: ; preds = %for.end8 120 br i1 true, label %do.body, label %do.end, !llvm.loop !10 121 122do.end: ; preds = %do.cond 123 ret void 124} 125 126; Function Attrs: argmemonly nofree nosync nounwind willreturn 127declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) addrspace(1) #1 128 129; Function Attrs: argmemonly nofree nosync nounwind willreturn 130declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) addrspace(1) #1 131 132attributes #0 = { nounwind "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 133attributes #1 = { argmemonly nofree nosync nounwind willreturn } 134attributes #2 = { nounwind } 135 136!llvm.module.flags = !{!0} 137!llvm.ident = !{!1} 138 139!0 = !{i32 1, !"wchar_size", i32 4} 140!1 = !{!"clang)"} 141!2 = !{!3, !3, i64 0, i64 4} 142!3 = !{!4, i64 4, !"int"} 143!4 = !{!5, i64 1, !"omnipotent char"} 144!5 = !{!"Simple C++ TBAA"} 145!6 = distinct !{!6, !7} 146!7 = !{!"llvm.loop.mustprogress"} 147!8 = distinct !{!8, !7, !9} 148!9 = !{!"llvm.loop.unroll.disable"} 149!10 = distinct !{!10, !11} 150!11 = !{!"llvm.loop.unroll.count", i32 2} 151