[Frontend] Remove unused includes (NFC) (#116927)
[llvm-project.git] / llvm / test / tools / llvm-reduce / remove-ifunc.ll
bloba7853d937d9a655aad2c6cef4035988f2cdad0ca
1 ; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=ifuncs --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
2 ; RUN: FileCheck --check-prefixes=CHECK-FINAL --input-file=%t %s
5 ; CHECK-FINAL: @initialized_with_ifunc = global ptr @ifunc_constant_initializer_user
6 @initialized_with_ifunc = global ptr @ifunc_constant_initializer_user
9 ; CHECK-FINAL: [[TABLE:@[0-9]+]] = internal global [[[TABLE_SIZE:[0-9]+]] x ptr] poison
10 ; CHECK-FINAL: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 10, ptr @1, ptr null }]
13 ; CHECK-INTERESTINGNESS: @ifunc_kept1 = ifunc
15 ; CHECK-FINAL: @ifunc_kept1 = ifunc void (), ptr @resolver1
16 @ifunc_kept1 = ifunc void (), ptr @resolver1
17 @ifunc_removed2 = ifunc void (), ptr @resolver1
19 ; CHECK-INTERESTINGNESS: @ifunc_kept3 =
20 ; CHECK-FINAL: @ifunc_kept3 = ifunc i32 (double), ptr @resolver2
21 @ifunc_kept3 = ifunc i32 (double), ptr @resolver2
24 ; Remove one with no users
25 @ifunc4_removed = ifunc float (i64), ptr @resolver2
27 ; Keep one with no users
28 ; CHECK-INTERESTINGNESS: @ifunc5_kept = ifunc
29 @ifunc5_kept = ifunc float (i64), ptr @resolver2
32 ; Make sure the hidden is preserved
33 ; CHECK-INTERESTINGNESS: @ifunc_kept_hidden =
34 ; CHECK-FINAL: @ifunc_kept_hidden = hidden ifunc i32 (double), ptr @resolver3
35 @ifunc_kept_hidden = hidden ifunc i32 (double), ptr @resolver3
36 @ifunc7 = ifunc float (i64), ptr @resolver3
38 @ifunc_ptr_arg = ifunc void (ptr), ptr @resolver4
41 ; CHECK-INTERESTINGNESS: @ifunc_nonvoid_kept0 = ifunc
42 @ifunc_nonvoid_kept0 = ifunc i32 (double), ptr @resolver5
43 @ifunc_nonvoid_removed0 = ifunc i32 (double), ptr @resolver5
45 ; CHECK-INTERESTINGNESS: @ifunc_nonvoid_kept1 = ifunc
46 @ifunc_nonvoid_kept1 = ifunc i32 (double), ptr @resolver5
47 @ifunc_nonvoid_removed1 = ifunc i32 (double), ptr @resolver5
49 ; CHECK-FINAL: @ifunc_constant_initializer_user = ifunc i32 (double), ptr @resolver5
50 @ifunc_constant_initializer_user = ifunc i32 (double), ptr @resolver5
54 define ptr @resolver1() {
55   ret ptr inttoptr (i64 123 to ptr)
58 define ptr @resolver2() {
59   ret ptr inttoptr (i64 456 to ptr)
62 define ptr @resolver3() {
63   ret ptr inttoptr (i64 789 to ptr)
66 define ptr @resolver4() {
67   ret ptr inttoptr (i64 999 to ptr)
70 define ptr @resolver5() {
71   ret ptr inttoptr (i64 420 to ptr)
74 define void @call_ifunc_kept1() {
75   ; CHECK-FINAL-LABEL: define void @call_ifunc_kept1() {
76   ; CHECK-FINAL-NEXT: call void @ifunc_kept1()
77   ; CHECK-FINAL-NEXT: ret void
78   call void @ifunc_kept1()
79   ret void
82 ; Test call to removed ifunc
83 define void @call_ifunc_removed(ptr %ptr) {
84   ; CHECK-FINAL-LABEL: define void @call_ifunc_removed(ptr %ptr)
85   ; CHECK-FINAL-NEXT: %1 = load ptr, ptr @0, align 8
86   ; CHECK-FINAL-NEXT:  call void %1()
87   ; CHECK-FINAL-NEXT:  ret void
88   call void @ifunc_removed2()
89   ret void
92 ; Test value use of removed ifunc
93 define void @store_ifunc_removed2(ptr %ptr) {
94   ; CHECK-FINAL-LABEL: define void @store_ifunc_removed2(ptr %ptr) {
95   ; CHECK-FINAL-NEXT: %1 = load ptr, ptr [[TABLE]], align 8
96   ; CHECK-FINAL-NEXT: store ptr %1, ptr %ptr, align 8
97   ; CHECK-FINAL-NEXT: %2 = load ptr, ptr @0, align 8
98   ; CHECK-FINAL-NEXT: store ptr %ptr, ptr %2, align 8
99   ; CHECK-FINAL-NEXT: ret void
100   store ptr @ifunc_removed2, ptr %ptr
101   store ptr %ptr, ptr @ifunc_removed2
102   ret void
105 declare void @other_func(ptr)
107 ; Check a call user, but not as the call operand
108 define void @call_ifunc_removed_is_argument(ptr %ptr) {
109   ; CHECK-FINAL-LABEL: define void @call_ifunc_removed_is_argument(ptr %ptr) {
110   ; CHECK-FINAL-NEXT: %1 = load ptr, ptr [[TABLE]], align 8
111   ; CHECK-FINAL-NEXT: call void @other_func(ptr %1)
112   ; CHECK-FINAL-NEXT: ret void
113   call void @other_func(ptr @ifunc_removed2)
114   ret void
117 ; Check a call user calling the ifunc, and using the ifunc as an argument
118 define void @call_ifunc_removed_both_call_argument(ptr %ptr) {
119   ; CHECK-FINAL-LABEL: define void @call_ifunc_removed_both_call_argument(
120   ; CHECK-FINAL-NEXT: %1 = load ptr, ptr getelementptr inbounds ([[[TABLE_SIZE]] x ptr], ptr [[TABLE]], i32 0, i32 3), align 8
121   ; CHECK-FINAL-NEXT: %2 = load ptr, ptr getelementptr inbounds ([[[TABLE_SIZE]] x ptr], ptr [[TABLE]], i32 0, i32 3), align 8
122   ; CHECK-FINAL-NEXT: call void %1(ptr %1)
123   ; CHECK-FINAL-NEXT: ret void
124   call void @ifunc_ptr_arg(ptr @ifunc_ptr_arg)
125   ret void
128 define i32 @call_ifunc_nonvoid(double %arg) {
129   ; CHECK-FINAL-LABEL: define i32 @call_ifunc_nonvoid(double %arg) {
130   ; CHECK-FINAL-NEXT: %ret0 = call i32 @ifunc_nonvoid_kept0(double %arg)
131   ; CHECK-FINAL-NEXT: %1 = load ptr, ptr getelementptr inbounds ([[[TABLE_SIZE]] x ptr], ptr [[TABLE]], i32 0, i32 4), align 8
132   ; CHECK-FINAL-NEXT: %ret1 = call i32 %1(double %arg)
133   ; CHECK-FINAL-NEXT: %add = add i32 %ret0, %ret1
134   ; CHECK-FINAL-NEXT: ret i32 %add
135   %ret0 = call i32 @ifunc_nonvoid_kept0(double %arg)
136   %ret1 = call i32 @ifunc_nonvoid_removed0(double %arg)
137   %add = add i32 %ret0, %ret1
138   ret i32 %add
141 ; Use site is different than ifunc function type
142 define float @call_different_type_ifunc_nonvoid(double %arg) {
143   ; CHECK-FINAL-LABEL: define float @call_different_type_ifunc_nonvoid(double %arg) {
144   ; CHECK-FINAL-NEXT: %cast.arg = bitcast double %arg to i64
145   ; CHECK-FINAL-NEXT: %ret0 = call float @ifunc_nonvoid_kept0(i64 %cast.arg)
146   ; CHECK-FINAL-NEXT: %1 = load ptr, ptr getelementptr inbounds ([[[TABLE_SIZE]] x ptr], ptr [[TABLE]], i32 0, i32 4), align 8
147   ; CHECK-FINAL-NEXT: %ret1 = call float %1(i64 %cast.arg)
148   ; CHECK-FINAL-NEXT: %fadd = fadd float %ret0, %ret1
149   ; CHECK-FINAL-NEXT: ret float %fadd
150   %cast.arg = bitcast double %arg to i64
151   %ret0 = call float(i64) @ifunc_nonvoid_kept0(i64 %cast.arg)
152   %ret1 = call float(i64) @ifunc_nonvoid_removed0(i64 %cast.arg)
153   %fadd = fadd float %ret0, %ret1
154   ret float %fadd
157 ; FIXME: Should be able to expand this, but we miss the call
158 ; instruction in the constexpr cast.
159 define i32 @call_addrspacecast_callee_type_ifunc_nonvoid(double %arg) {
160   ; CHECK-FINAL-LABEL: define i32 @call_addrspacecast_callee_type_ifunc_nonvoid(double %arg) {
161   ; CHECK-FINAL-NEXT: %ret0 = call addrspace(1) i32 addrspacecast (ptr @ifunc_nonvoid_kept1 to ptr addrspace(1))(double %arg)
162   ; CHECK-FINAL-NEXT: %ret1 = call addrspace(1) i32 addrspacecast (ptr @ifunc_nonvoid_removed1 to ptr addrspace(1))(double %arg)
163   ; CHECK-FINAL-NEXT: %add = add i32 %ret0, %ret1
164   ; CHECK-FINAL-NEXT: ret i32 %add
165   %ret0 = call addrspace(1) i32 addrspacecast (ptr @ifunc_nonvoid_kept1 to ptr addrspace(1)) (double %arg)
166   %ret1 = call addrspace(1) i32 addrspacecast (ptr @ifunc_nonvoid_removed1 to ptr addrspace(1)) (double %arg)
167   %add = add i32 %ret0, %ret1
168   ret i32 %add
171 define i32 @call_used_in_initializer(double %arg) {
172   ; CHECK-FINAL-LABEL: define i32 @call_used_in_initializer(double %arg) {
173   ; CHECK-FINAL-NEXT: %1 = load ptr, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 7), align 8
174   ; CHECK-FINAL-NEXT: %ret = call i32 %1(double %arg)
175   ; CHECK-FINAL-NEXT: ret i32 %ret
176   %ret = call i32 @ifunc_constant_initializer_user(double %arg)
177   ret i32 %ret
180 ; CHECK-FINAL-LABEL: define internal void @1() {
181 ; CHECK-FINAL-NEXT: %1 = call ptr @resolver1()
182 ; CHECK-FINAL-NEXT: store ptr %1, ptr @0, align 8
183 ; CHECK-FINAL-NEXT: %2 = call ptr @resolver2()
184 ; CHECK-FINAL-NEXT: store ptr %2, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 1), align 8
185 ; CHECK-FINAL-NEXT: %3 = call ptr @resolver3()
186 ; CHECK-FINAL-NEXT: store ptr %3, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 2), align 8
187 ; CHECK-FINAL-NEXT: %4 = call ptr @resolver4()
188 ; CHECK-FINAL-NEXT: store ptr %4, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 3), align 8
189 ; CHECK-FINAL-NEXT: %5 = call ptr @resolver5()
190 ; CHECK-FINAL-NEXT: store ptr %5, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 4), align 8
191 ; CHECK-FINAL-NEXT: %6 = call ptr @resolver5()
192 ; CHECK-FINAL-NEXT: store ptr %6, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 5), align 8
193 ; CHECK-FINAL-NEXT: %7 = call ptr @resolver5()
194 ; CHECK-FINAL-NEXT: store ptr %7, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 6), align 8
195 ; CHECK-FINAL-NEXT: %8 = call ptr @resolver5()
196 ; CHECK-FINAL-NEXT: store ptr %8, ptr getelementptr inbounds ([8 x ptr], ptr @0, i32 0, i32 7), align 8
197 ; CHECK-FINAL-NEXT: ret void
198 ; CHECK-FINAL-NEXT: }