xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/pr50060-constantfold-loopid.ll (revision 07b9d231ff9baa6473b0dd588a3ce5330d3e4871)
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