1 // RUN: %clang_cc1 -disable-noundef-analysis -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck --check-prefixes=COMMON,CHECK64 %s
2 // RUN: %clang_cc1 -disable-noundef-analysis -fenable-matrix -triple i386-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck --check-prefixes=COMMON,CHECK32 %s
3 
4 // Also check we do not crash when running some middle-end passes. Most
5 // importantly this includes the IR verifier, to ensure we emit valid IR.
6 // RUN: %clang_cc1 -fenable-matrix -emit-llvm -triple x86_64-apple-darwin %s -o %t
7 
8 // Tests for the matrix type builtins.
9 
10 typedef double dx5x5_t __attribute__((matrix_type(5, 5)));
11 typedef float fx2x3_t __attribute__((matrix_type(2, 3)));
12 typedef float fx3x2_t __attribute__((matrix_type(3, 2)));
13 typedef int ix20x4_t __attribute__((matrix_type(20, 4)));
14 typedef int ix4x20_t __attribute__((matrix_type(4, 20)));
15 typedef unsigned ux1x6_t __attribute__((matrix_type(1, 6)));
16 typedef unsigned ux6x1_t __attribute__((matrix_type(6, 1)));
17 
18 void transpose_double_5x5(dx5x5_t *a) {
19   // COMMON-LABEL: define{{.*}} void @transpose_double_5x5(
20   // CHECK32:       [[A:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4
21   // CHECK64:       [[A:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
22   // COMMON-NEXT:   [[TRANS:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[A]], i32 5, i32 5)
23   // COMMON-NEXT:   [[AT_ADDR:%.*]] = bitcast [25 x double]* %a_t to <25 x double>*
24   // CHECK32-NEXT:  store <25 x double> [[TRANS]], <25 x double>* [[AT_ADDR]], align 4
25   // CHECK64-NEXT:  store <25 x double> [[TRANS]], <25 x double>* [[AT_ADDR]], align 8
26 
27   dx5x5_t a_t = __builtin_matrix_transpose(*a);
28 }
29 
30 void transpose_float_3x2(fx3x2_t *a) {
31   // COMMON-LABEL: define{{.*}} void @transpose_float_3x2(
32   // COMMON:        [[A:%.*]] = load <6 x float>, <6 x float>* {{.*}}, align 4
33   // COMMON-NEXT:   [[TRANS:%.*]] = call <6 x float> @llvm.matrix.transpose.v6f32(<6 x float> [[A]], i32 3, i32 2)
34   // COMMON-NEXT:   [[AT_ADDR:%.*]] = bitcast [6 x float]* %a_t to <6 x float>*
35   // COMMON-NEXT:   store <6 x float> [[TRANS]], <6 x float>* [[AT_ADDR]], align 4
36 
37   fx2x3_t a_t = __builtin_matrix_transpose(*a);
38 }
39 
40 void transpose_int_20x4(ix20x4_t *a) {
41   // COMMON-LABEL: define{{.*}} void @transpose_int_20x4(
42   // COMMON:         [[A:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4
43   // COMMON-NEXT:    [[TRANS:%.*]] = call <80 x i32> @llvm.matrix.transpose.v80i32(<80 x i32> [[A]], i32 20, i32 4)
44   // COMMON-NEXT:    [[AT_ADDR:%.*]] = bitcast [80 x i32]* %a_t to <80 x i32>*
45   // COMMON-NEXT:    store <80 x i32> [[TRANS]], <80 x i32>* [[AT_ADDR]], align 4
46 
47   ix4x20_t a_t = __builtin_matrix_transpose(*a);
48 }
49 
50 struct Foo {
51   ux1x6_t in;
52   ux6x1_t out;
53 };
54 
55 void transpose_struct_member(struct Foo *F) {
56   // COMMON-LABEL: define{{.*}} void @transpose_struct_member(
57   // COMMON:         [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4
58   // COMMON-NEXT:    [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6)
59   // CHECK32-NEXT:   [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 4
60   // CHECK64-NEXT:   [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8
61   // COMMON-NEXT:    [[OUT_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 1
62   // COMMON-NEXT:    [[OUT_PTR_C:%.*]] = bitcast [6 x i32]* [[OUT_PTR]] to <6 x i32>*
63   // COMMON-NEXT:    store <6 x i32> [[M_T]], <6 x i32>* [[OUT_PTR_C]], align 4
64 
65   F->out = __builtin_matrix_transpose(F->in);
66 }
67 
68 void transpose_transpose_struct_member(struct Foo *F) {
69   // COMMON-LABEL: define{{.*}} void @transpose_transpose_struct_member(
70   // COMMON:         [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4
71   // COMMON-NEXT:    [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6)
72   // COMMON-NEXT:    [[M_T2:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M_T]], i32 6, i32 1)
73   // CHECK32-NEXT:   [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 4
74   // CHECK64-NEXT:   [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8
75   // COMMON-NEXT:    [[IN_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 0
76   // COMMON-NEXT:    [[IN_PTR_C:%.*]] = bitcast [6 x i32]* [[IN_PTR]] to <6 x i32>*
77   // COMMON-NEXT:    store <6 x i32> [[M_T2]], <6 x i32>* [[IN_PTR_C]], align 4
78 
79   F->in = __builtin_matrix_transpose(__builtin_matrix_transpose(F->in));
80 }
81 
82 dx5x5_t get_matrix();
83 
84 void transpose_rvalue() {
85   // COMMON-LABEL: define{{.*}} void @transpose_rvalue()
86   // COMMON-NEXT:  entry:
87   // CHECK32-NEXT:   [[M_T_ADDR:%.*]] = alloca [25 x double], align 4
88   // CHECK64-NEXT:   [[M_T_ADDR:%.*]] = alloca [25 x double], align 8
89   // CHECK32-NEXT:   [[CALL:%.*]] = call <25 x double> bitcast (<25 x double> (...)* @get_matrix to <25 x double> ()*)()
90   // CHECK64-NEXT:   [[CALL:%.*]] = call <25 x double> (...) @get_matrix()
91   // COMMON-NEXT:    [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[CALL]], i32 5, i32 5)
92   // COMMON-NEXT:    [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>*
93   // CHECK32-NEXT:   store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 4
94   // CHECK64-NEXT:   store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8
95 
96   dx5x5_t m_t = __builtin_matrix_transpose(get_matrix());
97 }
98 
99 const dx5x5_t global_matrix;
100 
101 void transpose_global() {
102   // COMMON-LABEL: define{{.*}} void @transpose_global()
103   // COMMON-NEXT:  entry:
104   // CHECK32-NEXT:    [[M_T_ADDR:%.*]] = alloca [25 x double], align 4
105   // CHECK32-NEXT:    [[GLOBAL_MATRIX:%.*]] = load <25 x double>, <25 x double>* bitcast ([25 x double]* @global_matrix to <25 x double>*), align 4
106   // CHECK64-NEXT:    [[M_T_ADDR:%.*]] = alloca [25 x double], align 8
107   // CHECK64-NEXT:    [[GLOBAL_MATRIX:%.*]] = load <25 x double>, <25 x double>* bitcast ([25 x double]* @global_matrix to <25 x double>*), align 8
108   // COMMON-NEXT:    [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[GLOBAL_MATRIX]], i32 5, i32 5)
109   // COMMON-NEXT:    [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>*
110   // CHECK32-NEXT:    store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 4
111   // CHECK64-NEXT:    store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8
112 
113   dx5x5_t m_t = __builtin_matrix_transpose(global_matrix);
114 }
115 
116 void column_major_load_with_const_stride_double(double *Ptr) {
117   // COMMON-LABEL: define{{.*}} void @column_major_load_with_const_stride_double(double* %Ptr)
118   // CHECK32:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
119   // CHECK32-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5)
120   // CHECK64:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
121   // CHECK64-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5)
122 
123   dx5x5_t m_a1 = __builtin_matrix_column_major_load(Ptr, 5, 5, 5);
124 }
125 
126 void column_major_load_with_const_stride2_double(double *Ptr) {
127   // COMMON-LABEL: define{{.*}} void @column_major_load_with_const_stride2_double(double* %Ptr)
128   // CHECK32:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
129   // CHECK32-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 15, i1 false, i32 5, i32 5)
130   // CHECK64:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
131   // CHECK64-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 15, i1 false, i32 5, i32 5)
132 
133   dx5x5_t m_a2 = __builtin_matrix_column_major_load(Ptr, 5, 5, 2 * 3 + 9);
134 }
135 
136 void column_major_load_with_variable_stride_ull_float(float *Ptr, unsigned long long S) {
137   // COMMON-LABEL: define{{.*}} void @column_major_load_with_variable_stride_ull_float(float* %Ptr, i64 %S)
138   // CHECK32:         [[S:%.*]] = load i64, i64* %S.addr, align 8
139   // CHECK32-NEXT:    [[STRIDE_TRUNC:%.*]] = trunc i64 [[S]] to i32
140   // CHECK32-NEXT:    [[PTR:%.*]] = load float*, float** %Ptr.addr, align 4
141   // CHECK32-NEXT:    call <6 x float> @llvm.matrix.column.major.load.v6f32.i32(float* align 4 [[PTR]], i32 [[STRIDE_TRUNC]], i1 false, i32 2, i32 3)
142 
143   // CHECK64:         [[S:%.*]] = load i64, i64* %S.addr, align 8
144   // CHECK64-NEXT:    [[PTR:%.*]] = load float*, float** %Ptr.addr, align 8
145   // CHECK64-NEXT:    call <6 x float> @llvm.matrix.column.major.load.v6f32.i64(float* align 4 [[PTR]], i64 [[S]], i1 false, i32 2, i32 3)
146 
147   fx2x3_t m_b = __builtin_matrix_column_major_load(Ptr, 2, 3, S);
148 }
149 
150 void column_major_load_with_stride_math_int(int *Ptr, int S) {
151   // COMMON-LABEL: define{{.*}} void @column_major_load_with_stride_math_int(i32* %Ptr, i32 %S)
152   // COMMON:         [[S:%.*]] = load i32, i32* %S.addr, align 4
153   // COMMON-NEXT:    [[STRIDE:%.*]] = add nsw i32 [[S]], 32
154   // CHECK32-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4
155   // CHECK32-NEXT:   call <80 x i32> @llvm.matrix.column.major.load.v80i32.i32(i32* align 4 [[PTR]], i32 [[STRIDE]], i1 false, i32 4, i32 20)
156   //
157   // CHECK64-NEXT:   [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64
158   // CHECK64-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8
159   // CHECK64-NEXT:   call <80 x i32> @llvm.matrix.column.major.load.v80i32.i64(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 4, i32 20)
160 
161   ix4x20_t m_c = __builtin_matrix_column_major_load(Ptr, 4, 20, S + 32);
162 }
163 
164 void column_major_load_with_stride_math_s_int(int *Ptr, short S) {
165   // COMMON-LABEL:  define{{.*}} void @column_major_load_with_stride_math_s_int(i32* %Ptr, i16 signext %S)
166   // COMMON:         [[S:%.*]] = load i16, i16* %S.addr, align 2
167   // COMMON-NEXT:    [[S_EXT:%.*]] = sext i16 [[S]] to i32
168   // COMMON-NEXT:    [[STRIDE:%.*]] = add nsw i32 [[S_EXT]], 32
169   // CHECK32-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4
170   // CHECK32-NEXT:   %matrix = call <80 x i32> @llvm.matrix.column.major.load.v80i32.i32(i32* align 4 [[PTR]], i32 [[STRIDE]], i1 false, i32 4, i32 20)
171   //
172   // CHECK64-NEXT:   [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64
173   // CHECK64-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8
174   // CHECK64-NEXT:   %matrix = call <80 x i32> @llvm.matrix.column.major.load.v80i32.i64(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 4, i32 20)
175 
176   ix4x20_t m_c = __builtin_matrix_column_major_load(Ptr, 4, 20, S + 32);
177 }
178 
179 void column_major_load_array1(double Ptr[25]) {
180   // COMMON-LABEL: define{{.*}} void @column_major_load_array1(double* %Ptr)
181   // CHECK32:         [[ADDR:%.*]] = load double*, double** %Ptr.addr, align 4
182   // CHECK32-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[ADDR]], i32 5, i1 false, i32 5, i32 5)
183 
184   // CHECK64:         [[ADDR:%.*]] = load double*, double** %Ptr.addr, align 8
185   // CHECK64-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[ADDR]], i64 5, i1 false, i32 5, i32 5)
186 
187   dx5x5_t m = __builtin_matrix_column_major_load(Ptr, 5, 5, 5);
188 }
189 
190 void column_major_load_array2() {
191   // COMMON-LABEL: define{{.*}} void @column_major_load_array2() #0 {
192   // COMMON-NEXT:  entry:
193   // CHECK32-NEXT:    [[PTR:%.*]] = alloca [25 x double], align 8
194   // CHECK32:         [[ARRAY_DEC:%.*]] = getelementptr inbounds [25 x double], [25 x double]* [[PTR]], i32 0, i32 0
195   // CHECK32-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 8 [[ARRAY_DEC]], i32 5, i1 false, i32 5, i32 5)
196 
197   // CHECK64-NEXT:    [[PTR:%.*]] = alloca [25 x double], align 16
198   // CHECK64:         [[ARRAY_DEC:%.*]] = getelementptr inbounds [25 x double], [25 x double]* [[PTR]], i64 0, i64 0
199   // CHECK64-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 16 [[ARRAY_DEC]], i64 5, i1 false, i32 5, i32 5)
200 
201   double Ptr[25];
202   dx5x5_t m = __builtin_matrix_column_major_load(Ptr, 5, 5, 5);
203 }
204 
205 void column_major_load_const(const double *Ptr) {
206   // COMMON-LABEL: define{{.*}} void @column_major_load_const(double* %Ptr)
207   // CHECK32:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
208   // CHECK32-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5)
209   //
210   // CHECK64:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
211   // CHECK64-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5)
212 
213   dx5x5_t m_a1 = __builtin_matrix_column_major_load(Ptr, 5, 5, 5);
214 }
215 
216 void column_major_load_volatile(volatile double *Ptr) {
217   // COMMON-LABEL: define{{.*}} void @column_major_load_volatile(double* %Ptr)
218   // CHECK32:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
219   // CHECK32-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 5, i1 true, i32 5, i32 5)
220   //
221   // CHECK64:         [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
222   // CHECK64-NEXT:    call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 5, i1 true, i32 5, i32 5)
223 
224   dx5x5_t m_a1 = __builtin_matrix_column_major_load(Ptr, 5, 5, 5);
225 }
226 
227 void column_major_store_with_const_stride_double(double *Ptr) {
228   // COMMON-LABEL: define{{.*}} void @column_major_store_with_const_stride_double(double* %Ptr)
229   // CHECK32:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4
230   // CHECK32-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
231   // CHECK32-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5)
232   //
233   // CHECK64:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
234   // CHECK64-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
235   // CHECK64-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5)
236 
237   dx5x5_t m;
238   __builtin_matrix_column_major_store(m, Ptr, 5);
239 }
240 
241 void column_major_store_with_const_stride2_double(double *Ptr) {
242   // COMMON-LABEL: define{{.*}} void @column_major_store_with_const_stride2_double(double* %Ptr)
243   // CHECK32:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4
244   // CHECK32-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
245   // CHECK32-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 15, i1 false, i32 5, i32 5)
246   //
247   // CHECK64:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
248   // CHECK64-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
249   // CHECK64-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 15, i1 false, i32 5, i32 5)
250   //
251   dx5x5_t m;
252   __builtin_matrix_column_major_store(m, Ptr, 2 * 3 + 9);
253 }
254 
255 void column_major_store_with_stride_math_int(int *Ptr, int S) {
256   // COMMON-LABEL: define{{.*}} void @column_major_store_with_stride_math_int(i32* %Ptr, i32 %S)
257   // COMMON:         [[M:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4
258   // CHECK32-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4
259   // CHECK64-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8
260   // COMMON-NEXT:    [[S:%.*]] = load i32, i32* %S.addr, align 4
261   // COMMON-NEXT:    [[ADD:%.*]] = add nsw i32 [[S]], 32
262   // CHECK32-NEXT:   call void @llvm.matrix.column.major.store.v80i32.i32(<80 x i32> [[M]], i32* align 4 [[PTR]], i32 [[ADD]], i1 false, i32 4, i32 20)
263   //
264   // CHECK64-NEXT:   [[IDX:%.*]] = sext i32 [[ADD]] to i64
265   // CHECK64-NEXT:   call void @llvm.matrix.column.major.store.v80i32.i64(<80 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX]], i1 false, i32 4, i32 20)
266 
267   ix4x20_t m;
268   __builtin_matrix_column_major_store(m, Ptr, S + 32);
269 }
270 
271 void column_major_store_with_stride_math_s_int(int *Ptr, short S) {
272   // COMMON-LABEL: define{{.*}} void @column_major_store_with_stride_math_s_int(i32* %Ptr, i16 signext %S)
273   // COMMON:         [[M:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4
274   // CHECK32-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4
275   // CHECK64-NEXT:   [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8
276   // COMMON-NEXT:    [[S:%.*]] = load i16, i16* %S.addr, align 2
277   // COMMON-NEXT:    [[EXT:%.*]] = sext i16 [[S]] to i32
278   // COMMON-NEXT:    [[ADD:%.*]] = add nsw i32 [[EXT]], 2
279   // CHECK32-NEXT:   call void @llvm.matrix.column.major.store.v80i32.i32(<80 x i32> [[M]], i32* align 4 [[PTR]], i32 [[ADD]], i1 false, i32 4, i32 20)
280   //
281   // CHECK64-NEXT:   [[IDX:%.*]] = sext i32 [[ADD]] to i64
282   // CHECK64-NEXT:   call void @llvm.matrix.column.major.store.v80i32.i64(<80 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX]], i1 false, i32 4, i32 20)
283 
284   ix4x20_t m;
285   __builtin_matrix_column_major_store(m, Ptr, S + 2);
286 }
287 
288 void column_major_store_array1(double Ptr[25]) {
289   // COMMON-LABEL: define{{.*}} void @column_major_store_array1(double* %Ptr)
290   // CHECK32:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4
291   // CHECK32-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
292   // CHECK32-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5)
293   //
294   // CHECK64:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
295   // CHECK64-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
296   // CHECK64-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5)
297 
298   dx5x5_t m;
299   __builtin_matrix_column_major_store(m, Ptr, 5);
300 }
301 
302 void column_major_store_array2() {
303   // COMMON-LABEL: define{{.*}} void @column_major_store_array2()
304   // CHECK32:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4
305   // CHECK32-NEXT:    [[PTR:%.*]] = getelementptr inbounds [25 x double], [25 x double]* %Ptr, i32 0, i32 0
306   // CHECK32-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 8 [[PTR]], i32 5, i1 false, i32 5, i32 5)
307   //
308   // CHECK64:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
309   // CHECK64-NEXT:    [[PTR:%.*]] = getelementptr inbounds [25 x double], [25 x double]* %Ptr, i64 0, i64 0
310   // CHECK64-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 16 [[PTR]], i64 5, i1 false, i32 5, i32 5)
311 
312   double Ptr[25];
313   dx5x5_t m;
314   __builtin_matrix_column_major_store(m, Ptr, 5);
315 }
316 
317 void column_major_store_volatile(volatile double *Ptr) {
318   // COMMON-LABEL: define{{.*}} void @column_major_store_volatile(double* %Ptr) #0 {
319   // CHECK32:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4
320   // CHECK32-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4
321   // CHECK32-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 5, i1 true, i32 5, i32 5)
322   //
323   // CHECK64:         [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8
324   // CHECK64-NEXT:    [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8
325   // CHECK64-NEXT:    call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 true, i32 5, i32 5)
326 
327   dx5x5_t m;
328   __builtin_matrix_column_major_store(m, Ptr, 5);
329 }
330