xref: /aosp_15_r20/external/llvm/test/Transforms/InstSimplify/call.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1; RUN: opt < %s -instsimplify -S | FileCheck %s
2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3
4declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
5declare {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b)
6declare {i8, i1} @llvm.ssub.with.overflow.i8(i8 %a, i8 %b)
7declare {i8, i1} @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
8
9define i1 @test_uadd1() {
10; CHECK-LABEL: @test_uadd1(
11  %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 3)
12  %overflow = extractvalue {i8, i1} %x, 1
13  ret i1 %overflow
14; CHECK-NEXT: ret i1 true
15}
16
17define i8 @test_uadd2() {
18; CHECK-LABEL: @test_uadd2(
19  %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 44)
20  %result = extractvalue {i8, i1} %x, 0
21  ret i8 %result
22; CHECK-NEXT: ret i8 42
23}
24
25define {i8, i1} @test_usub1(i8 %V) {
26; CHECK-LABEL: @test_usub1(
27  %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 %V)
28  ret {i8, i1} %x
29; CHECK-NEXT: ret { i8, i1 } zeroinitializer
30}
31
32define {i8, i1} @test_ssub1(i8 %V) {
33; CHECK-LABEL: @test_ssub1(
34  %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 %V)
35  ret {i8, i1} %x
36; CHECK-NEXT: ret { i8, i1 } zeroinitializer
37}
38
39define {i8, i1} @test_umul1(i8 %V) {
40; CHECK-LABEL: @test_umul1(
41  %x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %V, i8 0)
42  ret {i8, i1} %x
43; CHECK-NEXT: ret { i8, i1 } zeroinitializer
44}
45
46declare i256 @llvm.cttz.i256(i256 %src, i1 %is_zero_undef)
47
48define i256 @test_cttz() {
49; CHECK-LABEL: @test_cttz(
50  %x = call i256 @llvm.cttz.i256(i256 10, i1 false)
51  ret i256 %x
52; CHECK-NEXT: ret i256 1
53}
54
55declare i256 @llvm.ctpop.i256(i256 %src)
56
57define i256 @test_ctpop() {
58; CHECK-LABEL: @test_ctpop(
59  %x = call i256 @llvm.ctpop.i256(i256 10)
60  ret i256 %x
61; CHECK-NEXT: ret i256 2
62}
63
64; Test a non-intrinsic that we know about as a library call.
65declare float @fabs(float %x)
66
67define float @test_fabs_libcall() {
68; CHECK-LABEL: @test_fabs_libcall(
69
70  %x = call float @fabs(float -42.0)
71; This is still a real function call, so instsimplify won't nuke it -- other
72; passes have to do that.
73; CHECK-NEXT: call float @fabs
74
75  ret float %x
76; CHECK-NEXT: ret float 4.2{{0+}}e+01
77}
78
79
80declare float @llvm.fabs.f32(float) nounwind readnone
81declare float @llvm.floor.f32(float) nounwind readnone
82declare float @llvm.ceil.f32(float) nounwind readnone
83declare float @llvm.trunc.f32(float) nounwind readnone
84declare float @llvm.rint.f32(float) nounwind readnone
85declare float @llvm.nearbyint.f32(float) nounwind readnone
86
87; Test idempotent intrinsics
88define float @test_idempotence(float %a) {
89; CHECK-LABEL: @test_idempotence(
90
91; CHECK: fabs
92; CHECK-NOT: fabs
93  %a0 = call float @llvm.fabs.f32(float %a)
94  %a1 = call float @llvm.fabs.f32(float %a0)
95
96; CHECK: floor
97; CHECK-NOT: floor
98  %b0 = call float @llvm.floor.f32(float %a)
99  %b1 = call float @llvm.floor.f32(float %b0)
100
101; CHECK: ceil
102; CHECK-NOT: ceil
103  %c0 = call float @llvm.ceil.f32(float %a)
104  %c1 = call float @llvm.ceil.f32(float %c0)
105
106; CHECK: trunc
107; CHECK-NOT: trunc
108  %d0 = call float @llvm.trunc.f32(float %a)
109  %d1 = call float @llvm.trunc.f32(float %d0)
110
111; CHECK: rint
112; CHECK-NOT: rint
113  %e0 = call float @llvm.rint.f32(float %a)
114  %e1 = call float @llvm.rint.f32(float %e0)
115
116; CHECK: nearbyint
117; CHECK-NOT: nearbyint
118  %f0 = call float @llvm.nearbyint.f32(float %a)
119  %f1 = call float @llvm.nearbyint.f32(float %f0)
120
121  %r0 = fadd float %a1, %b1
122  %r1 = fadd float %r0, %c1
123  %r2 = fadd float %r1, %d1
124  %r3 = fadd float %r2, %e1
125  %r4 = fadd float %r3, %f1
126
127  ret float %r4
128}
129
130define i8* @operator_new() {
131entry:
132  %call = tail call noalias i8* @_Znwm(i64 8)
133  %cmp = icmp eq i8* %call, null
134  br i1 %cmp, label %cast.end, label %cast.notnull
135
136cast.notnull:                                     ; preds = %entry
137  %add.ptr = getelementptr inbounds i8, i8* %call, i64 4
138  br label %cast.end
139
140cast.end:                                         ; preds = %cast.notnull, %entry
141  %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ]
142  ret i8* %cast.result
143
144; CHECK-LABEL: @operator_new
145; CHECK: br i1 false, label %cast.end, label %cast.notnull
146}
147
148declare nonnull noalias i8* @_Znwm(i64)
149
150%"struct.std::nothrow_t" = type { i8 }
151@_ZSt7nothrow = external global %"struct.std::nothrow_t"
152
153define i8* @operator_new_nothrow_t() {
154entry:
155  %call = tail call noalias i8* @_ZnamRKSt9nothrow_t(i64 8, %"struct.std::nothrow_t"* @_ZSt7nothrow)
156  %cmp = icmp eq i8* %call, null
157  br i1 %cmp, label %cast.end, label %cast.notnull
158
159cast.notnull:                                     ; preds = %entry
160  %add.ptr = getelementptr inbounds i8, i8* %call, i64 4
161  br label %cast.end
162
163cast.end:                                         ; preds = %cast.notnull, %entry
164  %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ]
165  ret i8* %cast.result
166
167; CHECK-LABEL: @operator_new_nothrow_t
168; CHECK: br i1 %cmp, label %cast.end, label %cast.notnull
169}
170
171declare i8* @_ZnamRKSt9nothrow_t(i64, %"struct.std::nothrow_t"*) nounwind
172
173define i8* @malloc_can_return_null() {
174entry:
175  %call = tail call noalias i8* @malloc(i64 8)
176  %cmp = icmp eq i8* %call, null
177  br i1 %cmp, label %cast.end, label %cast.notnull
178
179cast.notnull:                                     ; preds = %entry
180  %add.ptr = getelementptr inbounds i8, i8* %call, i64 4
181  br label %cast.end
182
183cast.end:                                         ; preds = %cast.notnull, %entry
184  %cast.result = phi i8* [ %add.ptr, %cast.notnull ], [ null, %entry ]
185  ret i8* %cast.result
186
187; CHECK-LABEL: @malloc_can_return_null
188; CHECK: br i1 %cmp, label %cast.end, label %cast.notnull
189}
190
191define i32 @call_null() {
192entry:
193  %call = call i32 null()
194  ret i32 %call
195}
196; CHECK-LABEL: define i32 @call_null(
197; CHECK: ret i32 undef
198
199define i32 @call_undef() {
200entry:
201  %call = call i32 undef()
202  ret i32 %call
203}
204; CHECK-LABEL: define i32 @call_undef(
205; CHECK: ret i32 undef
206
207@GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49]
208
209define <8 x i32> @partial_masked_load() {
210; CHECK-LABEL: @partial_masked_load(
211; CHECK:         ret <8 x i32> <i32 undef, i32 undef, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47>
212  %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -2) to <8 x i32>*), i32 4, <8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef)
213  ret <8 x i32> %masked.load
214}
215
216define <8 x i32> @masked_load_undef_mask(<8 x i32>* %V) {
217; CHECK-LABEL: @masked_load_undef_mask(
218; CHECK:         ret <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0>
219  %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %V, i32 4, <8 x i1> undef, <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0>)
220  ret <8 x i32> %masked.load
221}
222
223declare noalias i8* @malloc(i64)
224
225declare <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>*, i32, <8 x i1>, <8 x i32>)
226