xref: /llvm-project/llvm/test/Transforms/DeadStoreElimination/multiblock-multipath-throwing.ll (revision f497a00da968b0ff90d8c98caa184d14b9a92495)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=dse -S | FileCheck %s
3
4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
5
6declare void @readnone_may_throw() readnone
7
8declare void @use(ptr)
9
10; Tests where the pointer/object is accessible after the function returns.
11
12; Cannot remove the store from the entry block, because the call in bb2 may throw.
13define void @accessible_after_return_1(ptr noalias %P, i1 %c1) {
14; CHECK-LABEL: @accessible_after_return_1(
15; CHECK-NEXT:    store i32 1, ptr [[P:%.*]], align 4
16; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
17; CHECK:       bb1:
18; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
19; CHECK-NEXT:    br label [[BB5:%.*]]
20; CHECK:       bb2:
21; CHECK-NEXT:    call void @readnone_may_throw()
22; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
23; CHECK-NEXT:    br label [[BB5]]
24; CHECK:       bb5:
25; CHECK-NEXT:    call void @use(ptr [[P]])
26; CHECK-NEXT:    ret void
27;
28  store i32 1, ptr %P
29  br i1 %c1, label %bb1, label %bb2
30
31bb1:
32  store i32 0, ptr %P
33  br label %bb5
34
35bb2:
36  call void @readnone_may_throw()
37  store i32 3, ptr %P
38  br label %bb5
39
40bb5:
41  call void @use(ptr %P)
42  ret void
43}
44
45; Cannot remove the store from the entry block, because the call in bb3 may throw.
46define void @accessible_after_return6(ptr %P, i1 %c.1, i1 %c.2) {
47; CHECK-LABEL: @accessible_after_return6(
48; CHECK-NEXT:  entry:
49; CHECK-NEXT:    store i32 0, ptr [[P:%.*]], align 4
50; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
51; CHECK:       bb1:
52; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
53; CHECK:       bb2:
54; CHECK-NEXT:    store i32 1, ptr [[P]], align 4
55; CHECK-NEXT:    ret void
56; CHECK:       bb3:
57; CHECK-NEXT:    call void @readnone_may_throw()
58; CHECK-NEXT:    store i32 2, ptr [[P]], align 4
59; CHECK-NEXT:    ret void
60; CHECK:       bb4:
61; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
62; CHECK-NEXT:    ret void
63;
64entry:
65  store i32 0, ptr %P
66  br i1 %c.1, label %bb1, label %bb2
67
68bb1:
69  br i1 %c.2, label %bb3, label %bb4
70
71bb2:
72  store i32 1, ptr %P
73  ret void
74
75bb3:
76  call void @readnone_may_throw()
77  store i32 2, ptr %P
78  ret void
79
80bb4:
81  store i32 3, ptr %P
82  ret void
83}
84
85; Tests where the pointer/object is *NOT* accessible after the function returns.
86
87; The store in the entry block can be eliminated, because it is overwritten
88; on all paths to the exit. As the location is not visible to the caller, the
89; call in bb2 (which may throw) can be ignored.
90define void @alloca_1(i1 %c1) {
91; CHECK-LABEL: @alloca_1(
92; CHECK-NEXT:  entry:
93; CHECK-NEXT:    [[P:%.*]] = alloca i32
94; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
95; CHECK:       bb1:
96; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
97; CHECK-NEXT:    br label [[BB5:%.*]]
98; CHECK:       bb2:
99; CHECK-NEXT:    call void @readnone_may_throw()
100; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
101; CHECK-NEXT:    br label [[BB5]]
102; CHECK:       bb5:
103; CHECK-NEXT:    call void @use(ptr [[P]])
104; CHECK-NEXT:    ret void
105;
106entry:
107  %P = alloca i32
108  store i32 1, ptr %P
109  br i1 %c1, label %bb1, label %bb2
110
111bb1:
112  store i32 0, ptr %P
113  br label %bb5
114
115bb2:
116  call void @readnone_may_throw()
117  store i32 3, ptr %P
118  br label %bb5
119
120bb5:
121  call void @use(ptr %P)
122  ret void
123}
124
125; The store in the entry block can be eliminated, because it is overwritten
126; on all paths to the exit. As the location is not visible to the caller, the
127; call in bb3 (which may throw) can be ignored.
128define void @alloca_2(i1 %c.1, i1 %c.2) {
129; CHECK-LABEL: @alloca_2(
130; CHECK-NEXT:    [[P:%.*]] = alloca i32
131; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
132; CHECK:       bb1:
133; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
134; CHECK-NEXT:    br label [[BB5:%.*]]
135; CHECK:       bb2:
136; CHECK-NEXT:    br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
137; CHECK:       bb3:
138; CHECK-NEXT:    call void @readnone_may_throw()
139; CHECK-NEXT:    store i32 3, ptr [[P]], align 4
140; CHECK-NEXT:    br label [[BB5]]
141; CHECK:       bb4:
142; CHECK-NEXT:    store i32 5, ptr [[P]], align 4
143; CHECK-NEXT:    br label [[BB5]]
144; CHECK:       bb5:
145; CHECK-NEXT:    call void @use(ptr [[P]])
146; CHECK-NEXT:    ret void
147;
148  %P = alloca i32
149  store i32 1, ptr %P
150  br i1 %c.1, label %bb1, label %bb2
151
152bb1:
153  store i32 0, ptr %P
154  br label %bb5
155
156bb2:
157  br i1 %c.2, label %bb3, label %bb4
158
159bb3:
160  call void @readnone_may_throw()
161  store i32 3, ptr %P
162  br label %bb5
163
164bb4:
165  store i32 5, ptr %P
166  br label %bb5
167
168bb5:
169  call void @use(ptr %P)
170  ret void
171}
172