[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / multiblock-multipath-throwing.ll
blob4fe04e5467d3d104a65dc55fd17944f2140faa48
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -basic-aa -dse -S | FileCheck %s
4 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
6 declare void @readnone_may_throw() readnone
8 declare void @use(i32 *)
10 ; Tests where the pointer/object is accessible after the function returns.
12 ; Cannot remove the store from the entry block, because the call in bb2 may throw.
13 define void @accessible_after_return_1(i32* noalias %P, i1 %c1) {
14 ; CHECK-LABEL: @accessible_after_return_1(
15 ; CHECK-NEXT:    store i32 1, i32* [[P:%.*]], align 4
16 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
17 ; CHECK:       bb1:
18 ; CHECK-NEXT:    store i32 0, i32* [[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, i32* [[P]], align 4
23 ; CHECK-NEXT:    br label [[BB5]]
24 ; CHECK:       bb5:
25 ; CHECK-NEXT:    call void @use(i32* [[P]])
26 ; CHECK-NEXT:    ret void
28   store i32 1, i32* %P
29   br i1 %c1, label %bb1, label %bb2
31 bb1:
32   store i32 0, i32* %P
33   br label %bb5
35 bb2:
36   call void @readnone_may_throw()
37   store i32 3, i32* %P
38   br label %bb5
40 bb5:
41   call void @use(i32* %P)
42   ret void
45 ; Cannot remove the store from the entry block, because the call in bb3 may throw.
46 define void @accessible_after_return6(i32* %P, i1 %c.1, i1 %c.2) {
47 ; CHECK-LABEL: @accessible_after_return6(
48 ; CHECK-NEXT:  entry:
49 ; CHECK-NEXT:    store i32 0, i32* [[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, i32* [[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, i32* [[P]], align 4
59 ; CHECK-NEXT:    ret void
60 ; CHECK:       bb4:
61 ; CHECK-NEXT:    store i32 3, i32* [[P]], align 4
62 ; CHECK-NEXT:    ret void
64 entry:
65   store i32 0, i32* %P
66   br i1 %c.1, label %bb1, label %bb2
68 bb1:
69   br i1 %c.2, label %bb3, label %bb4
71 bb2:
72   store i32 1, i32* %P
73   ret void
75 bb3:
76   call void @readnone_may_throw()
77   store i32 2, i32* %P
78   ret void
80 bb4:
81   store i32 3, i32* %P
82   ret void
85 ; Tests where the pointer/object is *NOT* accessible after the function returns.
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.
90 define 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, i32* [[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, i32* [[P]], align 4
101 ; CHECK-NEXT:    br label [[BB5]]
102 ; CHECK:       bb5:
103 ; CHECK-NEXT:    call void @use(i32* [[P]])
104 ; CHECK-NEXT:    ret void
106 entry:
107   %P = alloca i32
108   store i32 1, i32* %P
109   br i1 %c1, label %bb1, label %bb2
111 bb1:
112   store i32 0, i32* %P
113   br label %bb5
115 bb2:
116   call void @readnone_may_throw()
117   store i32 3, i32* %P
118   br label %bb5
120 bb5:
121   call void @use(i32* %P)
122   ret void
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.
128 define 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, i32* [[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, i32* [[P]], align 4
140 ; CHECK-NEXT:    br label [[BB5]]
141 ; CHECK:       bb4:
142 ; CHECK-NEXT:    store i32 5, i32* [[P]], align 4
143 ; CHECK-NEXT:    br label [[BB5]]
144 ; CHECK:       bb5:
145 ; CHECK-NEXT:    call void @use(i32* [[P]])
146 ; CHECK-NEXT:    ret void
148   %P = alloca i32
149   store i32 1, i32* %P
150   br i1 %c.1, label %bb1, label %bb2
152 bb1:
153   store i32 0, i32* %P
154   br label %bb5
156 bb2:
157   br i1 %c.2, label %bb3, label %bb4
159 bb3:
160   call void @readnone_may_throw()
161   store i32 3, i32* %P
162   br label %bb5
164 bb4:
165   store i32 5, i32* %P
166   br label %bb5
168 bb5:
169   call void @use(i32* %P)
170   ret void