1 // RUN: %clang_cc1 -no-enable-noundef-analysis -fenable-matrix -fclang-abi-compat=latest -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - -std=c++17 | FileCheck %s
3 typedef double dx5x5_t
__attribute__((matrix_type(5, 5)));
4 typedef float fx3x4_t
__attribute__((matrix_type(3, 4)));
6 // CHECK: %struct.Matrix = type { i8, [12 x float], float }
8 void load_store(dx5x5_t
*a
, dx5x5_t
*b
) {
9 // CHECK-LABEL: define{{.*}} void @_Z10load_storePu11matrix_typeILm5ELm5EdES0_(
11 // CHECK-NEXT: %a.addr = alloca ptr, align 8
12 // CHECK-NEXT: %b.addr = alloca ptr, align 8
13 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8
14 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8
15 // CHECK-NEXT: %0 = load ptr, ptr %b.addr, align 8
16 // CHECK-NEXT: %1 = load <25 x double>, ptr %0, align 8
17 // CHECK-NEXT: %2 = load ptr, ptr %a.addr, align 8
18 // CHECK-NEXT: store <25 x double> %1, ptr %2, align 8
19 // CHECK-NEXT: ret void
24 typedef float fx3x3_t
__attribute__((matrix_type(3, 3)));
26 void parameter_passing(fx3x3_t a
, fx3x3_t
*b
) {
27 // CHECK-LABEL: define{{.*}} void @_Z17parameter_passingu11matrix_typeILm3ELm3EfEPS_(
29 // CHECK-NEXT: %a.addr = alloca [9 x float], align 4
30 // CHECK-NEXT: %b.addr = alloca ptr, align 8
31 // CHECK-NEXT: store <9 x float> %a, ptr %a.addr, align 4
32 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8
33 // CHECK-NEXT: %0 = load <9 x float>, ptr %a.addr, align 4
34 // CHECK-NEXT: %1 = load ptr, ptr %b.addr, align 8
35 // CHECK-NEXT: store <9 x float> %0, ptr %1, align 4
36 // CHECK-NEXT: ret void
40 fx3x3_t
return_matrix(fx3x3_t
*a
) {
41 // CHECK-LABEL: define{{.*}} <9 x float> @_Z13return_matrixPu11matrix_typeILm3ELm3EfE(
43 // CHECK-NEXT: %a.addr = alloca ptr, align 8
44 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8
45 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8
46 // CHECK-NEXT: %1 = load <9 x float>, ptr %0, align 4
47 // CHECK-NEXT: ret <9 x float> %1
57 void matrix_struct_pointers(Matrix
*a
, Matrix
*b
) {
58 // CHECK-LABEL: define{{.*}} void @_Z22matrix_struct_pointersP6MatrixS0_(
60 // CHECK-NEXT: %a.addr = alloca ptr, align 8
61 // CHECK-NEXT: %b.addr = alloca ptr, align 8
62 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8
63 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8
64 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8
65 // CHECK-NEXT: %Data = getelementptr inbounds %struct.Matrix, ptr %0, i32 0, i32 1
66 // CHECK-NEXT: %1 = load <12 x float>, ptr %Data, align 4
67 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 8
68 // CHECK-NEXT: %Data1 = getelementptr inbounds %struct.Matrix, ptr %2, i32 0, i32 1
69 // CHECK-NEXT: store <12 x float> %1, ptr %Data1, align 4
70 // CHECK-NEXT: ret void
74 void matrix_struct_reference(Matrix
&a
, Matrix
&b
) {
75 // CHECK-LABEL: define{{.*}} void @_Z23matrix_struct_referenceR6MatrixS0_(
77 // CHECK-NEXT: %a.addr = alloca ptr, align 8
78 // CHECK-NEXT: %b.addr = alloca ptr, align 8
79 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8
80 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8
81 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8
82 // CHECK-NEXT: %Data = getelementptr inbounds %struct.Matrix, ptr %0, i32 0, i32 1
83 // CHECK-NEXT: %1 = load <12 x float>, ptr %Data, align 4
84 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 8
85 // CHECK-NEXT: %Data1 = getelementptr inbounds %struct.Matrix, ptr %2, i32 0, i32 1
86 // CHECK-NEXT: store <12 x float> %1, ptr %Data1, align 4
87 // CHECK-NEXT: ret void
98 void matrix_class_reference(MatrixClass
&a
, MatrixClass
&b
) {
99 // CHECK-LABEL: define{{.*}} void @_Z22matrix_class_referenceR11MatrixClassS0_(
100 // CHECK-NEXT: entry:
101 // CHECK-NEXT: %a.addr = alloca ptr, align 8
102 // CHECK-NEXT: %b.addr = alloca ptr, align 8
103 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8
104 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8
105 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8
106 // CHECK-NEXT: %Data = getelementptr inbounds %class.MatrixClass, ptr %0, i32 0, i32 1
107 // CHECK-NEXT: %1 = load <12 x float>, ptr %Data, align 4
108 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 8
109 // CHECK-NEXT: %Data1 = getelementptr inbounds %class.MatrixClass, ptr %2, i32 0, i32 1
110 // CHECK-NEXT: store <12 x float> %1, ptr %Data1, align 4
111 // CHECK-NEXT: ret void
115 template <typename Ty
, unsigned Rows
, unsigned Cols
>
116 class MatrixClassTemplate
{
118 using MatrixTy
= Ty
__attribute__((matrix_type(Rows
, Cols
)));
124 template <typename Ty
, unsigned Rows
, unsigned Cols
>
125 void matrix_template_reference(MatrixClassTemplate
<Ty
, Rows
, Cols
> &a
, MatrixClassTemplate
<Ty
, Rows
, Cols
> &b
) {
129 MatrixClassTemplate
<float, 10, 15> matrix_template_reference_caller(float *Data
) {
130 // CHECK-LABEL: define{{.*}} void @_Z32matrix_template_reference_callerPf(ptr noalias sret(%class.MatrixClassTemplate) align 8 %agg.result, ptr %Data
131 // CHECK-NEXT: entry:
132 // CHECK-NEXT: %Data.addr = alloca ptr, align 8
133 // CHECK-NEXT: %Arg = alloca %class.MatrixClassTemplate, align 8
134 // CHECK-NEXT: store ptr %Data, ptr %Data.addr, align 8
135 // CHECK-NEXT: %0 = load ptr, ptr %Data.addr, align 8
136 // CHECK-NEXT: %1 = load <150 x float>, ptr %0, align 4
137 // CHECK-NEXT: %Data1 = getelementptr inbounds %class.MatrixClassTemplate, ptr %Arg, i32 0, i32 1
138 // CHECK-NEXT: store <150 x float> %1, ptr %Data1, align 4
139 // CHECK-NEXT: call void @_Z25matrix_template_referenceIfLj10ELj15EEvR19MatrixClassTemplateIT_XT0_EXT1_EES3_(ptr nonnull align 8 dereferenceable(616) %Arg, ptr nonnull align 8 dereferenceable(616) %agg.result)
140 // CHECK-NEXT: ret void
142 // CHECK-LABEL: define linkonce_odr void @_Z25matrix_template_referenceIfLj10ELj15EEvR19MatrixClassTemplateIT_XT0_EXT1_EES3_(ptr nonnull align 8 dereferenceable(616) %a, ptr nonnull align 8 dereferenceable(616) %b)
143 // CHECK-NEXT: entry:
144 // CHECK-NEXT: %a.addr = alloca ptr, align 8
145 // CHECK-NEXT: %b.addr = alloca ptr, align 8
146 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8
147 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8
148 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8
149 // CHECK-NEXT: %Data = getelementptr inbounds %class.MatrixClassTemplate, ptr %0, i32 0, i32 1
150 // CHECK-NEXT: %1 = load <150 x float>, ptr %Data, align 4
151 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 8
152 // CHECK-NEXT: %Data1 = getelementptr inbounds %class.MatrixClassTemplate, ptr %2, i32 0, i32 1
153 // CHECK-NEXT: store <150 x float> %1, ptr %Data1, align 4
154 // CHECK-NEXT: ret void
156 MatrixClassTemplate
<float, 10, 15> Result
, Arg
;
157 Arg
.Data
= *((MatrixClassTemplate
<float, 10, 15>::MatrixTy
*)Data
);
158 matrix_template_reference(Arg
, Result
);
162 template <class T
, unsigned long R
, unsigned long C
>
163 using matrix
= T
__attribute__((matrix_type(R
, C
)));
168 template <class T
, unsigned long R
, unsigned long C
>
169 selector
<0> use_matrix(matrix
<T
, R
, C
> &m
) {}
171 template <class T
, unsigned long R
>
172 selector
<1> use_matrix(matrix
<T
, R
, 10> &m
) {}
175 selector
<2> use_matrix(matrix
<T
, 10, 10> &m
) {}
177 template <class T
, unsigned long C
>
178 selector
<3> use_matrix(matrix
<T
, 10, C
> &m
) {}
180 template <unsigned long R
, unsigned long C
>
181 selector
<4> use_matrix(matrix
<float, R
, C
> &m
) {}
183 void test_template_deduction() {
185 // CHECK-LABEL: define{{.*}} void @_Z23test_template_deductionv()
186 // CHECK-NEXT: entry:
187 // CHECK-NEXT: %m0 = alloca [120 x i32], align 4
188 // CHECK-NEXT: %w = alloca %struct.selector, align 1
189 // CHECK-NEXT: %undef.agg.tmp = alloca %struct.selector, align 1
190 // CHECK-NEXT: %m1 = alloca [100 x i32], align 4
191 // CHECK-NEXT: %x = alloca %struct.selector.0, align 1
192 // CHECK-NEXT: %undef.agg.tmp1 = alloca %struct.selector.0, align 1
193 // CHECK-NEXT: %m2 = alloca [120 x i32], align 4
194 // CHECK-NEXT: %y = alloca %struct.selector.1, align 1
195 // CHECK-NEXT: %undef.agg.tmp2 = alloca %struct.selector.1, align 1
196 // CHECK-NEXT: %m3 = alloca [144 x i32], align 4
197 // CHECK-NEXT: %z = alloca %struct.selector.2, align 1
198 // CHECK-NEXT: %undef.agg.tmp3 = alloca %struct.selector.2, align 1
199 // CHECK-NEXT: %m4 = alloca [144 x float], align 4
200 // CHECK-NEXT: %v = alloca %struct.selector.3, align 1
201 // CHECK-NEXT: %undef.agg.tmp4 = alloca %struct.selector.3, align 1
202 // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E(ptr nonnull align 4 dereferenceable(480) %m0)
203 // CHECK-NEXT: call void @_Z10use_matrixIiE8selectorILi2EERu11matrix_typeILm10ELm10ET_E(ptr nonnull align 4 dereferenceable(400) %m1)
204 // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E(ptr nonnull align 4 dereferenceable(480) %m2)
205 // CHECK-NEXT: call void @_Z10use_matrixIiLm12ELm12EE8selectorILi0EERu11matrix_typeIXT0_EXT1_ET_E(ptr nonnull align 4 dereferenceable(576) %m3)
206 // CHECK-NEXT: call void @_Z10use_matrixILm12ELm12EE8selectorILi4EERu11matrix_typeIXT_EXT0_EfE(ptr nonnull align 4 dereferenceable(576) %m4)
207 // CHECK-NEXT: ret void
209 // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E(ptr nonnull align 4 dereferenceable(480) %m)
210 // CHECK-NEXT: entry:
211 // CHECK-NEXT: %m.addr = alloca ptr, align 8
212 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
213 // CHECK-NEXT: call void @llvm.trap()
214 // CHECK-NEXT: unreachable
216 // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiE8selectorILi2EERu11matrix_typeILm10ELm10ET_E(ptr nonnull align 4 dereferenceable(400) %m)
217 // CHECK-NEXT: entry:
218 // CHECK-NEXT: %m.addr = alloca ptr, align 8
219 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
220 // CHECK-NEXT: call void @llvm.trap()
221 // CHECK-NEXT: unreachable
223 // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E(ptr nonnull align 4 dereferenceable(480) %m)
224 // CHECK-NEXT: entry:
225 // CHECK-NEXT: %m.addr = alloca ptr, align 8
226 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
227 // CHECK-NEXT: call void @llvm.trap()
228 // CHECK-NEXT: unreachable
230 // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12ELm12EE8selectorILi0EERu11matrix_typeIXT0_EXT1_ET_E(ptr nonnull align 4 dereferenceable(576) %m)
231 // CHECK-NEXT: entry:
232 // CHECK-NEXT: %m.addr = alloca ptr, align 8
233 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
234 // CHECK-NEXT: call void @llvm.trap()
235 // CHECK-NEXT: unreachable
237 // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixILm12ELm12EE8selectorILi4EERu11matrix_typeIXT_EXT0_EfE(ptr nonnull align 4 dereferenceable(576)
238 // CHECK-NEXT: entry:
239 // CHECK-NEXT: %m.addr = alloca ptr, align 8
240 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
241 // CHECK-NEXT: call void @llvm.trap()
242 // CHECK-NEXT: unreachable
244 matrix
<int, 10, 12> m0
;
245 selector
<3> w
= use_matrix(m0
);
246 matrix
<int, 10, 10> m1
;
247 selector
<2> x
= use_matrix(m1
);
248 matrix
<int, 12, 10> m2
;
249 selector
<1> y
= use_matrix(m2
);
250 matrix
<int, 12, 12> m3
;
251 selector
<0> z
= use_matrix(m3
);
252 matrix
<float, 12, 12> m4
;
253 selector
<4> v
= use_matrix(m4
);
257 void foo(matrix
<int, R
, 10> &m
) {
261 // CHECK-LABEL: define{{.*}} void @_Z11test_auto_tv()
262 // CHECK-NEXT: entry:
263 // CHECK-NEXT: %m = alloca [130 x i32], align 4
264 // CHECK-NEXT: call void @_Z3fooITnDaLm13EEvRu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(520) %m)
265 // CHECK-NEXT: ret void
267 // CHECK-LABEL: define linkonce_odr void @_Z3fooITnDaLm13EEvRu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(520) %m)
268 // CHECK-NEXT: entry:
269 // CHECK-NEXT: %m.addr = alloca ptr, align 8
270 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
271 // CHECK-NEXT: ret void
273 matrix
<int, 13, 10> m
;
277 template <unsigned long R
, unsigned long C
>
278 matrix
<float, R
+ 1, C
+ 2> use_matrix_2(matrix
<int, R
, C
> &m
) {}
280 template <unsigned long R
, unsigned long C
>
281 selector
<0> use_matrix_2(matrix
<int, R
+ 2, C
/ 2> &m1
, matrix
<float, R
, C
> &m2
) {}
283 template <unsigned long R
, unsigned long C
>
284 selector
<1> use_matrix_2(matrix
<int, R
+ C
, C
> &m1
, matrix
<float, R
, C
- R
> &m2
) {}
286 template <unsigned long R
>
287 matrix
<float, R
+ R
, R
- 3> use_matrix_2(matrix
<int, R
, 10> &m1
) {}
289 template <unsigned long R
>
290 selector
<2> use_matrix_3(matrix
<int, R
- 2, R
> &m
) {}
292 void test_use_matrix_2() {
293 // CHECK-LABEL: define{{.*}} void @_Z17test_use_matrix_2v()
294 // CHECK-NEXT: entry:
295 // CHECK-NEXT: %m1 = alloca [24 x i32], align 4
296 // CHECK-NEXT: %r1 = alloca [40 x float], align 4
297 // CHECK-NEXT: %m2 = alloca [24 x float], align 4
298 // CHECK-NEXT: %r2 = alloca %struct.selector.2, align 1
299 // CHECK-NEXT: %undef.agg.tmp = alloca %struct.selector.2, align 1
300 // CHECK-NEXT: %m3 = alloca [104 x i32], align 4
301 // CHECK-NEXT: %m4 = alloca [15 x float], align 4
302 // CHECK-NEXT: %r3 = alloca %struct.selector.1, align 1
303 // CHECK-NEXT: %undef.agg.tmp1 = alloca %struct.selector.1, align 1
304 // CHECK-NEXT: %m5 = alloca [50 x i32], align 4
305 // CHECK-NEXT: %r4 = alloca [20 x float], align 4
306 // CHECK-NEXT: %r5 = alloca %struct.selector.0, align 1
307 // CHECK-NEXT: %undef.agg.tmp3 = alloca %struct.selector.0, align 1
308 // CHECK-NEXT: %call = call <40 x float> @_Z12use_matrix_2ILm4ELm6EEu11matrix_typeIXplT_Li1EEXplT0_Li2EEfERu11matrix_typeIXT_EXT0_EiE(ptr nonnull align 4 dereferenceable(96) %m1)
309 // CHECK-NEXT: store <40 x float> %call, ptr %r1, align 4
310 // CHECK-NEXT: call void @_Z12use_matrix_2ILm2ELm12EE8selectorILi0EERu11matrix_typeIXplT_Li2EEXdvT0_Li2EEiERu11matrix_typeIXT_EXT0_EfE(ptr nonnull align 4 dereferenceable(96) %m1, ptr nonnull align 4 dereferenceable(96) %m2)
311 // CHECK-NEXT: call void @_Z12use_matrix_2ILm5ELm8EE8selectorILi1EERu11matrix_typeIXplT_T0_EXT0_EiERu11matrix_typeIXT_EXmiT0_T_EfE(ptr nonnull align 4 dereferenceable(416) %m3, ptr nonnull align 4 dereferenceable(60) %m4)
312 // CHECK-NEXT: %call2 = call <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(200) %m5)
313 // CHECK-NEXT: store <20 x float> %call2, ptr %r4, align 4
314 // CHECK-NEXT: call void @_Z12use_matrix_3ILm6EE8selectorILi2EERu11matrix_typeIXmiT_Li2EEXT_EiE(ptr nonnull align 4 dereferenceable(96) %m1)
315 // CHECK-NEXT: ret void
317 // CHECK-LABEL: define linkonce_odr <40 x float> @_Z12use_matrix_2ILm4ELm6EEu11matrix_typeIXplT_Li1EEXplT0_Li2EEfERu11matrix_typeIXT_EXT0_EiE(ptr nonnull align 4 dereferenceable(96) %m)
318 // CHECK-NEXT: entry:
319 // CHECK-NEXT: %m.addr = alloca ptr, align 8
320 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
321 // CHECK-NEXT: call void @llvm.trap()
322 // CHECK-NEXT: unreachable
324 // CHECK-LABEL: define linkonce_odr void @_Z12use_matrix_2ILm2ELm12EE8selectorILi0EERu11matrix_typeIXplT_Li2EEXdvT0_Li2EEiERu11matrix_typeIXT_EXT0_EfE(ptr nonnull align 4 dereferenceable(96) %m1, ptr nonnull align 4 dereferenceable(96) %m2)
325 // CHECK-NEXT: entry:
326 // CHECK-NEXT: %m1.addr = alloca ptr, align 8
327 // CHECK-NEXT: %m2.addr = alloca ptr, align 8
328 // CHECK-NEXT: store ptr %m1, ptr %m1.addr, align 8
329 // CHECK-NEXT: store ptr %m2, ptr %m2.addr, align 8
330 // CHECK-NEXT: call void @llvm.trap()
331 // CHECK-NEXT: unreachable
333 // CHECK-LABEL: define linkonce_odr void @_Z12use_matrix_2ILm5ELm8EE8selectorILi1EERu11matrix_typeIXplT_T0_EXT0_EiERu11matrix_typeIXT_EXmiT0_T_EfE(ptr nonnull align 4 dereferenceable(416) %m1, ptr nonnull align 4 dereferenceable(60) %m2)
334 // CHECK-NEXT: entry:
335 // CHECK-NEXT: %m1.addr = alloca ptr, align 8
336 // CHECK-NEXT: %m2.addr = alloca ptr, align 8
337 // CHECK-NEXT: store ptr %m1, ptr %m1.addr, align 8
338 // CHECK-NEXT: store ptr %m2, ptr %m2.addr, align 8
339 // CHECK-NEXT: call void @llvm.trap()
340 // CHECK-NEXT: unreachable
342 // CHECK-LABEL: define linkonce_odr <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(200) %m1)
343 // CHECK-NEXT: entry:
344 // CHECK-NEXT: %m1.addr = alloca ptr, align 8
345 // CHECK-NEXT: store ptr %m1, ptr %m1.addr, align 8
346 // CHECK-NEXT: call void @llvm.trap()
347 // CHECK-NEXT: unreachable
349 // CHECK-LABEL: define linkonce_odr void @_Z12use_matrix_3ILm6EE8selectorILi2EERu11matrix_typeIXmiT_Li2EEXT_EiE(ptr nonnull align 4 dereferenceable(96) %m)
350 // CHECK-NEXT: entry:
351 // CHECK-NEXT: %m.addr = alloca ptr, align 8
352 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
353 // CHECK-NEXT: call void @llvm.trap()
354 // CHECK-NEXT: unreachable
356 matrix
<int, 4, 6> m1
;
357 matrix
<float, 5, 8> r1
= use_matrix_2(m1
);
359 matrix
<float, 2, 12> m2
;
360 selector
<0> r2
= use_matrix_2(m1
, m2
);
362 matrix
<int, 13, 8> m3
;
363 matrix
<float, 5, 3> m4
;
364 selector
<1> r3
= use_matrix_2(m3
, m4
);
366 matrix
<int, 5, 10> m5
;
367 matrix
<float, 10, 2> r4
= use_matrix_2(m5
);
369 selector
<2> r5
= use_matrix_3(m1
);