1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s
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).
12 @n = dso_local global i32 0, align 4
13 @C = dso_local global i32 0, align 4
15 ; Function Attrs: nounwind
16 define dso_local void @_Z6test01v() addrspace(1) #0 {
17 ; CHECK-LABEL: @_Z6test01v(
19 ; CHECK-NEXT: [[J:%.*]] = alloca i32, align 4
20 ; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4
21 ; CHECK-NEXT: br label [[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:%.*]]
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]+]]
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:%.*]]
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]+]]
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]+]]
60 %j = alloca i32, align 4
61 %i = alloca i32, align 4
64 do.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
71 for.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
76 for.cond.cleanup: ; preds = %for.cond
77 call addrspace(1) void @llvm.lifetime.end.p0(i64 4, ptr %j) #2
80 for.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
86 for.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
92 for.cond.cleanup3: ; preds = %for.cond1
93 call addrspace(1) void @llvm.lifetime.end.p0(i64 4, ptr %i) #2
96 for.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
101 for.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
107 for.end: ; preds = %for.cond.cleanup3
110 for.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
116 for.end8: ; preds = %for.cond.cleanup
119 do.cond: ; preds = %for.end8
120 br i1 true, label %do.body, label %do.end, !llvm.loop !10
122 do.end: ; preds = %do.cond
126 ; Function Attrs: argmemonly nofree nosync nounwind willreturn
127 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) addrspace(1) #1
129 ; Function Attrs: argmemonly nofree nosync nounwind willreturn
130 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) addrspace(1) #1
132 attributes #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" }
133 attributes #1 = { argmemonly nofree nosync nounwind willreturn }
134 attributes #2 = { nounwind }
136 !llvm.module.flags = !{!0}
139 !0 = !{i32 1, !"wchar_size", i32 4}
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}