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