1 // RUN: %clang_cc1 -Wno-error=return-type -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 2 3 typedef double dx5x5_t __attribute__((matrix_type(5, 5))); 4 typedef float fx3x4_t __attribute__((matrix_type(3, 4))); 5 6 // CHECK: %struct.Matrix = type { i8, [12 x float], float } 7 8 void load_store(dx5x5_t *a, dx5x5_t *b) { 9 // CHECK-LABEL: define{{.*}} void @_Z10load_storePu11matrix_typeILm5ELm5EdES0_( 10 // CHECK-NEXT: entry: 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 20 21 *a = *b; 22 } 23 24 typedef float fx3x3_t __attribute__((matrix_type(3, 3))); 25 26 void parameter_passing(fx3x3_t a, fx3x3_t *b) { 27 // CHECK-LABEL: define{{.*}} void @_Z17parameter_passingu11matrix_typeILm3ELm3EfEPS_( 28 // CHECK-NEXT: entry: 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 37 *b = a; 38 } 39 40 fx3x3_t return_matrix(fx3x3_t *a) { 41 // CHECK-LABEL: define{{.*}} <9 x float> @_Z13return_matrixPu11matrix_typeILm3ELm3EfE( 42 // CHECK-NEXT: entry: 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 48 return *a; 49 } 50 51 struct Matrix { 52 char Tmp1; 53 fx3x4_t Data; 54 float Tmp2; 55 }; 56 57 void matrix_struct_pointers(Matrix *a, Matrix *b) { 58 // CHECK-LABEL: define{{.*}} void @_Z22matrix_struct_pointersP6MatrixS0_( 59 // CHECK-NEXT: entry: 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 nuw %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 nuw %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 71 b->Data = a->Data; 72 } 73 74 void matrix_struct_reference(Matrix &a, Matrix &b) { 75 // CHECK-LABEL: define{{.*}} void @_Z23matrix_struct_referenceR6MatrixS0_( 76 // CHECK-NEXT: entry: 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 nuw %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 nuw %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 88 b.Data = a.Data; 89 } 90 91 class MatrixClass { 92 public: 93 int Tmp1; 94 fx3x4_t Data; 95 long Tmp2; 96 }; 97 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 nuw %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 nuw %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 112 b.Data = a.Data; 113 } 114 115 template <typename Ty, unsigned Rows, unsigned Cols> 116 class MatrixClassTemplate { 117 public: 118 using MatrixTy = Ty __attribute__((matrix_type(Rows, Cols))); 119 int Tmp1; 120 MatrixTy Data; 121 long Tmp2; 122 }; 123 124 template <typename Ty, unsigned Rows, unsigned Cols> 125 void matrix_template_reference(MatrixClassTemplate<Ty, Rows, Cols> &a, MatrixClassTemplate<Ty, Rows, Cols> &b) { 126 b.Data = a.Data; 127 } 128 129 MatrixClassTemplate<float, 10, 15> matrix_template_reference_caller(float *Data) { 130 // CHECK-LABEL: define{{.*}} void @_Z32matrix_template_reference_callerPf(ptr dead_on_unwind noalias writable 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 nuw %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 141 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 nuw %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 nuw %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 155 156 MatrixClassTemplate<float, 10, 15> Result, Arg; 157 Arg.Data = *((MatrixClassTemplate<float, 10, 15>::MatrixTy *)Data); 158 matrix_template_reference(Arg, Result); 159 return Result; 160 } 161 162 template <class T, unsigned long R, unsigned long C> 163 using matrix = T __attribute__((matrix_type(R, C))); 164 165 template <int N> 166 struct selector {}; 167 168 template <class T, unsigned long R, unsigned long C> 169 selector<0> use_matrix(matrix<T, R, C> &m) {} 170 171 template <class T, unsigned long R> 172 selector<1> use_matrix(matrix<T, R, 10> &m) {} 173 174 template <class T> 175 selector<2> use_matrix(matrix<T, 10, 10> &m) {} 176 177 template <class T, unsigned long C> 178 selector<3> use_matrix(matrix<T, 10, C> &m) {} 179 180 template <unsigned long R, unsigned long C> 181 selector<4> use_matrix(matrix<float, R, C> &m) {} 182 183 void test_template_deduction() { 184 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 208 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 215 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 222 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 229 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 236 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 243 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); 254 } 255 256 template <auto R> 257 void foo(matrix<int, R, 10> &m) { 258 } 259 260 void test_auto_t() { 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 266 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 272 273 matrix<int, 13, 10> m; 274 foo(m); 275 } 276 277 template <unsigned long R, unsigned long C> 278 matrix<float, R + 1, C + 2> use_matrix_2(matrix<int, R, C> &m) {} 279 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) {} 282 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) {} 285 286 template <unsigned long R> 287 matrix<float, R + R, R - 3> use_matrix_2(matrix<int, R, 10> &m1) {} 288 289 template <unsigned long R> 290 selector<2> use_matrix_3(matrix<int, R - 2, R> &m) {} 291 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 316 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 323 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 332 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 341 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 348 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 355 356 matrix<int, 4, 6> m1; 357 matrix<float, 5, 8> r1 = use_matrix_2(m1); 358 359 matrix<float, 2, 12> m2; 360 selector<0> r2 = use_matrix_2(m1, m2); 361 362 matrix<int, 13, 8> m3; 363 matrix<float, 5, 3> m4; 364 selector<1> r3 = use_matrix_2(m3, m4); 365 366 matrix<int, 5, 10> m5; 367 matrix<float, 10, 2> r4 = use_matrix_2(m5); 368 369 selector<2> r5 = use_matrix_3(m1); 370 } 371 372 // CHECK-LABEL: define void @_Z22test_pseudo_destructorv() 373 // CHECK-NEXT: entry: 374 // CHECK-NEXT: %a = alloca [25 x double], align 8 375 // CHECK-NEXT: %b = alloca [12 x float], align 4 376 // CHECK-NEXT: %0 = load <25 x double>, ptr %a, align 8 377 // CHECK-NEXT: call void @_Z17pseudo_destructorIu11matrix_typeILm5ELm5EdEEvT_(<25 x double> %0) 378 // CHECK-NEXT: %1 = load <12 x float>, ptr %b, align 4 379 // CHECK-NEXT: call void @_Z17pseudo_destructorIu11matrix_typeILm3ELm4EfEEvT_(<12 x float> %1) 380 // CHECK-NEXT: ret void 381 382 // CHECK-LABEL: define linkonce_odr void @_Z17pseudo_destructorIu11matrix_typeILm5ELm5EdEEvT_(<25 x double> %t) 383 // CHECK-NEXT: entry: 384 // CHECK-NEXT: %t.addr = alloca [25 x double], align 8 385 // CHECK-NEXT: store <25 x double> %t, ptr %t.addr, align 8 386 // CHECK-NEXT: ret void 387 388 // CHECK-LABEL: define linkonce_odr void @_Z17pseudo_destructorIu11matrix_typeILm3ELm4EfEEvT_(<12 x float> %t) 389 // CHECK-NEXT: entry: 390 // CHECK-NEXT: %t.addr = alloca [12 x float], align 4 391 // CHECK-NEXT: store <12 x float> %t, ptr %t.addr, align 4 392 // CHECK-NEXT: ret void 393 template <typename T> 394 void pseudo_destructor(T t) { 395 t.~T(); 396 } 397 398 void test_pseudo_destructor() { 399 dx5x5_t a; 400 fx3x4_t b; 401 pseudo_destructor(a); 402 pseudo_destructor(b); 403 } 404