[Instrumentation] Fix a warning
[llvm-project.git] / flang / test / Fir / rebox.fir
blob91c1e9da5d454b691807ae11986f32c3c249c076
1 // RUN: tco %s | FileCheck %s
2 // RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s
4 // Test applying slice on fir.box
5 //   subroutine foo(x)
6 //     real :: x(3:, 4:)
7 //     call bar(x(5, 6:80:3))
8 //   end subroutine
10 func.func private @bar1(!fir.box<!fir.array<?xf32>>)
11 // CHECK-LABEL: define void @test_rebox_1(
12 // CHECK-SAME: ptr %[[INBOX:.*]])
13 func.func @test_rebox_1(%arg0: !fir.box<!fir.array<?x?xf32>>) {
14   // CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
15   %c2 = arith.constant 2 : index
16   %c3 = arith.constant 3 : index
17   %c4 = arith.constant 4 : index
18   %c5 = arith.constant 5 : index
19   %c6 = arith.constant 6 : index
20   %c80 = arith.constant 80 : index
21   %undef = fir.undefined index
22   %0 = fir.slice %c5, %undef, %undef, %c6, %c80, %c3 : (index, index, index, index, index, index) -> !fir.slice<2>
23   %1 = fir.shift %c3, %c4 : (index, index) -> !fir.shift<2>
25   // CHECK: %[[EXTRA_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 6
26   // CHECK: %[[EXTRA:.*]] = load i8, ptr %[[EXTRA_GEP]]
27   // CHECK: %[[EXTRA_WITH_ADDENDUM_CORRECTION:.*]] = and i8 %[[EXTRA]]
28   // CHECK: %[[OUTBOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20240719, i8 1, i8 27, i8 0, i8 undef, [1 x [3 x i64]] undef }, i8 %[[EXTRA_WITH_ADDENDUM_CORRECTION]], 6
29   // CHECK: %[[INSTRIDE_0_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 7, i32 0, i32 2
30   // CHECK: %[[INSTRIDE_0:.*]] = load i64, ptr %[[INSTRIDE_0_GEP]]
31   // CHECK: %[[INSTRIDE_1_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 7, i32 1, i32 2
32   // CHECK: %[[INSTRIDE_1:.*]] = load i64, ptr %[[INSTRIDE_1_GEP]]
33   // CHECK: %[[INBASE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 0
34   // CHECK: %[[INBASE:.*]] = load ptr, ptr %[[INBASE_GEP]]
35   // CHECK: %[[OFFSET_0:.*]] = mul i64 2, %[[INSTRIDE_0]]
36   // CHECK: %[[VOIDBASE0:.*]] = getelementptr i8, ptr %[[INBASE]], i64 %[[OFFSET_0]]
37   // CHECK: %[[OFFSET_1:.*]] = mul i64 2, %[[INSTRIDE_1]]
38   // CHECK: %[[VOIDBASE1:.*]] = getelementptr i8, ptr %[[VOIDBASE0]], i64 %[[OFFSET_1]]
39   // CHECK: %[[OUTSTRIDE0:.*]] = mul i64 3, %[[INSTRIDE_1]]
40   // CHECK: %[[OUTBOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %{{.*}}, i64 %[[OUTSTRIDE0]], 7, 0, 2
41   // CHECK: %[[OUTBOX2:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[OUTBOX1]], ptr %[[VOIDBASE1]], 0
42   // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[OUTBOX2]], ptr %[[OUTBOX_ALLOC]], align 8
43   %2 = fir.rebox %arg0(%1) [%0] : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>, !fir.slice<2>) -> !fir.box<!fir.array<?xf32>>
44   // CHECK: call void @bar1(ptr %[[OUTBOX_ALLOC]])
45   fir.call @bar1(%2) : (!fir.box<!fir.array<?xf32>>) -> ()
46   return
49 // Test that character length is propagated in rebox
50 //   subroutine foo(x)
51 //     character(*) :: x(:, :)
52 //     call bar(x(4:30:1, 4:30:1))
53 //   end subroutine
55 func.func private @bar_rebox_test2(!fir.box<!fir.array<?x?x!fir.char<1,?>>>)
56 // CHECK-LABEL: define void @test_rebox_2(
57 // CHECK-SAME: ptr %[[INBOX:.*]])
58 func.func @test_rebox_2(%arg0: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
59   %c1 = arith.constant 1 : index
60   %c4 = arith.constant 4 : index
61   %c30 = arith.constant 30 : index
62   %0 = fir.slice %c4, %c30, %c1, %c4, %c30, %c1 : (index, index, index, index, index, index) -> !fir.slice<2>
63   // CHECK: %[[OUTBOX:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }
64   // CHECK: %[[LEN_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 1
65   // CHECK: %[[LEN:.*]] = load i64, ptr %[[LEN_GEP]]
66   // CHECK: %[[SIZE:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[LEN]]
67   // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } undef, i64 %[[SIZE]], 1
69   %1 = fir.rebox %arg0 [%0]  : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.slice<2>) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>>
70   fir.call @bar_rebox_test2(%1) : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> ()
71   return
75 // Test setting a new shape on a fir.box
76 //   subroutine foo(x)
77 //     real :: x(:)
78 //     real, pointer(:, :, :), p
79 //     p(2:5, 3:7, 4:9) => x
80 //     call bar(p)
81 //   end subroutine
83 func.func private @bar_rebox_test3(!fir.box<!fir.array<?x?x?xf32>>)
84 // CHECK-LABEL: define void @test_rebox_3(
85 // CHECK-SAME: ptr %[[INBOX:.*]])
86 func.func @test_rebox_3(%arg0: !fir.box<!fir.array<?xf32>>) {
87   // CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] }
88   %c2 = arith.constant 2 : index
89   %c3 = arith.constant 3 : index
90   %c4 = arith.constant 4 : index
91   %c5 = arith.constant 5 : index
92   %1 = fir.shape_shift %c2, %c3, %c3, %c4, %c4, %c5 : (index, index, index, index, index, index) -> !fir.shapeshift<3>
93   // CHECK: %[[INSTRIDE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 7, i32 0, i32 2
94   // CHECK: %[[INSTRIDE:.*]] = load i64, ptr %[[INSTRIDE_GEP]]
95   // CHECK: %[[INBASE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 0
96   // CHECK: %[[INBASE:.*]] = load ptr, ptr %[[INBASE_GEP]]
97   // CHECK: %[[OUTSTRIDE1:.*]] = mul i64 3, %[[INSTRIDE]]
98   // CHECK: %[[OUTSTRIDE2:.*]] = mul i64 4, %[[OUTSTRIDE1]]
99   // CHECK: %[[OUTBOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %{{.*}}, i64 %[[INSTRIDE]], 7, 0, 2
100   // CHECK: %[[OUTBOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX0]], i64 3, 7, 1, 0
101   // CHECK: %[[OUTBOX2:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX1]], i64 4, 7, 1, 1
102   // CHECK: %[[OUTBOX3:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX2]], i64 %[[OUTSTRIDE1]], 7, 1, 2
103   // CHECK: %[[OUTBOX4:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX3]], i64 4, 7, 2, 0
104   // CHECK: %[[OUTBOX5:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX4]], i64 5, 7, 2, 1
105   // CHECK: %[[OUTBOX6:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX5]], i64 %[[OUTSTRIDE2]], 7, 2, 2
106   // CHECK: %[[OUTBOX7:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX6]], ptr %[[INBASE]], 0
107   // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX7]], ptr %[[OUTBOX_ALLOC]]
108   %2 = fir.rebox %arg0(%1) : (!fir.box<!fir.array<?xf32>>, !fir.shapeshift<3>) -> !fir.box<!fir.array<?x?x?xf32>>
109   // CHECK: call void @bar_rebox_test3(ptr %[[OUTBOX_ALLOC]])
110   fir.call @bar_rebox_test3(%2) : (!fir.box<!fir.array<?x?x?xf32>>) -> ()
111   return
115 // Test reboxing of character entities where the input has dynamic length and the output has compile
116 // time constant length.
118 // CHECK-LABEL: define void @test_rebox_4(
119 // CHECK-SAME: ptr %[[INPUT:.*]])
120 func.func @test_rebox_4(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>>) {
121   // CHECK: %[[NEWBOX_STORAGE:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
122   // CHECK: %[[EXTENT_GEP:.*]] = getelementptr {{{.*}}}, ptr %[[INPUT]], i32 0, i32 7, i32 0, i32 1
123   // CHECK: %[[EXTENT:.*]] = load i64, ptr %[[EXTENT_GEP]]
124   // CHECK: %[[STRIDE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INPUT]], i32 0, i32 7, i32 0, i32 2
125   // CHECK: %[[STRIDE:.*]] = load i64, ptr %[[STRIDE_GEP]]
126   // CHECK: %[[BASE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INPUT]], i32 0, i32 0
127   // CHECK: %[[BASE:.*]] = load ptr, ptr %[[BASE_GEP]]
128   // CHECK: %[[NEWBOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %{{.*}}, i64 %[[EXTENT]], 7, 0, 1
129   // CHECK: %[[NEWBOX2:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[NEWBOX1]], i64 %[[STRIDE]], 7, 0, 2
130   // CHECK: %[[NEWBOX3:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[NEWBOX2]], ptr %[[BASE]], 0
131   // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[NEWBOX3]], ptr %[[NEWBOX_STORAGE]]
132   // CHECK: call void @bar_test_rebox_4(ptr %[[NEWBOX_STORAGE]])
134   %1 = fir.rebox %arg0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>
135   fir.call @bar_test_rebox_4(%1) : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>) -> ()
136   return
138 func.func private @bar_test_rebox_4(!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,10>>>>)
140 // Testing complex part slice reboxing
141 //   subroutine test_cmplx_2(a)
142 //     complex :: a(:)
143 //     call bar1(a%re)
144 //   end subroutine
146 // CHECK-LABEL: define void @test_cmplx_1(
147 // CHECK-SAME: ptr %[[INBOX:.*]])
148 func.func @test_cmplx_1(%arg0: !fir.box<!fir.array<?xcomplex<f32>>>) {
149   // CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
150   %c1 = arith.constant 1 : index
151   %c1_i32 = arith.constant 0 : i32
152   %c0 = arith.constant 0 : index
153   %0:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.array<?xcomplex<f32>>>, index) -> (index, index, index)
154   %1 = fir.slice %c1, %0#1, %c1 path %c1_i32 : (index, index, index, i32) -> !fir.slice<1>
155   %2 = fir.rebox %arg0 [%1] : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.slice<1>) -> !fir.box<!fir.array<?xf32>>
156   // CHECK: %[[INSTRIDE_0_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 7, i64 0, i32 1
157   // CHECK: %[[INSTRIDE_0:.*]] = load i64, ptr %[[INSTRIDE_0_GEP]]
158   // CHECK: %[[INSTRIDE_1_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 7, i32 0, i32 2
159   // CHECK: %[[INSTRIDE_1:.*]] = load i64, ptr %[[INSTRIDE_1_GEP]]
160   // CHECK: %[[FRONT_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 0
161   // CHECK: %[[FRONT_PTR:.*]] = load ptr, ptr %[[FRONT_GEP]]
162   // CHECK: %[[FIELD_OFFSET_GEP:.*]] = getelementptr { float, float }, ptr %[[FRONT_PTR]], i64 0, i32 0
163   // CHECK: %[[FRONT_OFFSET:.*]] = mul i64 0, %[[INSTRIDE_1]]
164   // CHECK: %[[OFFSET_GEP:.*]] = getelementptr i8, ptr %[[FIELD_OFFSET_GEP]], i64 %[[FRONT_OFFSET]]
165   // CHECK: %[[SUB_1:.*]] = sub i64 %[[INSTRIDE_0]], 1
166   // CHECK: %[[ADD_1:.*]] = add i64 %[[SUB_1]], 1
167   // CHECK: %[[DIV_1:.*]] = sdiv i64 %[[ADD_1]], 1
168   // CHECK: %[[CHECK_NONZERO:.*]] = icmp sgt i64 %[[DIV_1]], 0
169   // CHECK: %[[CHECKED_BOUND:.*]] = select i1 %[[CHECK_NONZERO]], i64 %[[DIV_1]], i64 0
170   // CHECK: %[[STRIDE:.*]] = mul i64 1, %[[INSTRIDE_1]]
171   // CHECK: %[[VAL_BUILD_1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %{{.*}}, i64 %[[CHECKED_BOUND]], 7, 0, 1
172   // CHECK: %[[VAL_BUILD_2:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[VAL_BUILD_1]], i64 %[[STRIDE]], 7, 0, 2
173   // CHECK: %[[VAL_BUILD_3:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[VAL_BUILD_2]], ptr %[[OFFSET_GEP]], 0
174   // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[VAL_BUILD_3]], ptr %[[OUTBOX_ALLOC]]
175   fir.call @bar1(%2) : (!fir.box<!fir.array<?xf32>>) -> ()
176   // CHECK: call void @bar1(ptr %[[OUTBOX_ALLOC]])
177   return
180 // Testing triple on complex part slice
181 //   subroutine test_cmplx_2(a)
182 //     complex :: a(:)
183 //     call bar1(a(7:60:5)%im)
184 //   end subroutine
186 // CHECK-LABEL: define void @test_cmplx_2(
187 // CHECK-SAME: ptr %[[INBOX:.*]])
188 func.func @test_cmplx_2(%arg0: !fir.box<!fir.array<?xcomplex<f32>>>) {
189   // CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
190   %c7 = arith.constant 7 : index
191   %c5 = arith.constant 5 : index
192   %c60 = arith.constant 60 : index
193   %c1_i32 = arith.constant 1 : i32
194   %0 = fir.slice %c7, %c60, %c5 path %c1_i32 : (index, index, index, i32) -> !fir.slice<1>
195   %1 = fir.rebox %arg0 [%0] : (!fir.box<!fir.array<?xcomplex<f32>>>, !fir.slice<1>) -> !fir.box<!fir.array<11xf32>>
196   %2 = fir.convert %1 : (!fir.box<!fir.array<11xf32>>) -> !fir.box<!fir.array<?xf32>>
197   // CHECK: %[[INSTRIDE_0_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 7, i32 0, i32 2
198   // CHECK: %[[INSTRIDE_0:.*]] = load i64, ptr %[[INSTRIDE_0_GEP]]
199   // CHECK: %[[FRONT_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 0
200   // CHECK: %[[FRONT_PTR:.*]] = load ptr, ptr %[[FRONT_GEP]]
201   // CHECK: %[[FIELD_OFFSET_GEP:.*]] = getelementptr { float, float }, ptr %[[FRONT_PTR]], i64 0, i32 1
202   // CHECK: %[[FRONT_OFFSET:.*]] = mul i64 6, %[[INSTRIDE_0]]
203   // CHECK: %[[OFFSET_GEP:.*]] = getelementptr i8, ptr %[[FIELD_OFFSET_GEP]], i64 %[[FRONT_OFFSET]]
204   // CHECK: %[[STRIDE:.*]] = mul i64 5, %[[INSTRIDE_0]]
205   // CHECK: %[[VAL_BUILD_1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %{{.*}}, i64 %[[STRIDE]], 7, 0, 2
206   // CHECK: %[[VAL_BUILD_2:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[VAL_BUILD_1]], ptr %[[OFFSET_GEP]], 0
207   // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[VAL_BUILD_2]], ptr %[[OUTBOX_ALLOC]]
208   fir.call @bar1(%2) fastmath<contract> : (!fir.box<!fir.array<?xf32>>) -> ()
209   // CHECK: call void @bar1(ptr %[[OUTBOX_ALLOC]])
210   return
213 // Test reboxing of unlimited polymorphic.
215 func.func @rebox_unlimited_polymorphic_box(%arg0 : !fir.class<!fir.array<?xnone>>, %arg1 : !fir.box<!fir.array<?xnone>>, %arg0r : !fir.ref<!fir.class<!fir.array<?xnone>>>, %arg1r : !fir.ref<!fir.box<!fir.array<?xnone>>>) {
216   %c1 = arith.constant 1 : index
217   %c10 = arith.constant 10 : index
218   %1 = fir.slice %c1, %c10, %c1 : (index, index, index) -> !fir.slice<1>
219   %2 = fir.rebox %arg0 [%1] : (!fir.class<!fir.array<?xnone>>, !fir.slice<1>) -> !fir.class<!fir.array<?xnone>>
220   %3 = fir.rebox %arg1 [%1] : (!fir.box<!fir.array<?xnone>>, !fir.slice<1>) -> !fir.box<!fir.array<?xnone>>
221   fir.store %2 to %arg0r : !fir.ref<!fir.class<!fir.array<?xnone>>>
222   fir.store %3 to %arg1r : !fir.ref<!fir.box<!fir.array<?xnone>>>
223   return
225 // CHECK-LABEL: define void @rebox_unlimited_polymorphic_box
226 // CHECK:  %[[VAL_16:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }
227 // CHECK:  %[[VAL_17:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }
228 // ...
229 // CHECK:  store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %{{.*}}, ptr %[[VAL_17]]
230 // ...
231 // CHECK:  store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %{{.*}}, ptr %[[VAL_16]]