404 lines · cpp
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 %s2 3typedef double dx5x5_t __attribute__((matrix_type(5, 5)));4typedef float fx3x4_t __attribute__((matrix_type(3, 4)));5 6// CHECK: %struct.Matrix = type { i8, [12 x float], float }7 8void 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 812 // CHECK-NEXT: %b.addr = alloca ptr, align 813 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 814 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 815 // CHECK-NEXT: %0 = load ptr, ptr %b.addr, align 816 // CHECK-NEXT: %1 = load <25 x double>, ptr %0, align 817 // CHECK-NEXT: %2 = load ptr, ptr %a.addr, align 818 // CHECK-NEXT: store <25 x double> %1, ptr %2, align 819 // CHECK-NEXT: ret void20 21 *a = *b;22}23 24typedef float fx3x3_t __attribute__((matrix_type(3, 3)));25 26void 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 430 // CHECK-NEXT: %b.addr = alloca ptr, align 831 // CHECK-NEXT: store <9 x float> %a, ptr %a.addr, align 432 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 833 // CHECK-NEXT: %0 = load <9 x float>, ptr %a.addr, align 434 // CHECK-NEXT: %1 = load ptr, ptr %b.addr, align 835 // CHECK-NEXT: store <9 x float> %0, ptr %1, align 436 // CHECK-NEXT: ret void37 *b = a;38}39 40fx3x3_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 844 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 845 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 846 // CHECK-NEXT: %1 = load <9 x float>, ptr %0, align 447 // CHECK-NEXT: ret <9 x float> %148 return *a;49}50 51struct Matrix {52 char Tmp1;53 fx3x4_t Data;54 float Tmp2;55};56 57void 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 861 // CHECK-NEXT: %b.addr = alloca ptr, align 862 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 863 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 864 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 865 // CHECK-NEXT: %Data = getelementptr inbounds nuw %struct.Matrix, ptr %0, i32 0, i32 166 // CHECK-NEXT: %1 = load <12 x float>, ptr %Data, align 467 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 868 // CHECK-NEXT: %Data1 = getelementptr inbounds nuw %struct.Matrix, ptr %2, i32 0, i32 169 // CHECK-NEXT: store <12 x float> %1, ptr %Data1, align 470 // CHECK-NEXT: ret void71 b->Data = a->Data;72}73 74void 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 878 // CHECK-NEXT: %b.addr = alloca ptr, align 879 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 880 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 881 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 882 // CHECK-NEXT: %Data = getelementptr inbounds nuw %struct.Matrix, ptr %0, i32 0, i32 183 // CHECK-NEXT: %1 = load <12 x float>, ptr %Data, align 484 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 885 // CHECK-NEXT: %Data1 = getelementptr inbounds nuw %struct.Matrix, ptr %2, i32 0, i32 186 // CHECK-NEXT: store <12 x float> %1, ptr %Data1, align 487 // CHECK-NEXT: ret void88 b.Data = a.Data;89}90 91class MatrixClass {92public:93 int Tmp1;94 fx3x4_t Data;95 long Tmp2;96};97 98void 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 8102 // CHECK-NEXT: %b.addr = alloca ptr, align 8103 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8104 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8105 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8106 // CHECK-NEXT: %Data = getelementptr inbounds nuw %class.MatrixClass, ptr %0, i32 0, i32 1107 // CHECK-NEXT: %1 = load <12 x float>, ptr %Data, align 4108 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 8109 // CHECK-NEXT: %Data1 = getelementptr inbounds nuw %class.MatrixClass, ptr %2, i32 0, i32 1110 // CHECK-NEXT: store <12 x float> %1, ptr %Data1, align 4111 // CHECK-NEXT: ret void112 b.Data = a.Data;113}114 115template <typename Ty, unsigned Rows, unsigned Cols>116class MatrixClassTemplate {117public:118 using MatrixTy = Ty __attribute__((matrix_type(Rows, Cols)));119 int Tmp1;120 MatrixTy Data;121 long Tmp2;122};123 124template <typename Ty, unsigned Rows, unsigned Cols>125void matrix_template_reference(MatrixClassTemplate<Ty, Rows, Cols> &a, MatrixClassTemplate<Ty, Rows, Cols> &b) {126 b.Data = a.Data;127}128 129MatrixClassTemplate<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 %Data131 // CHECK-NEXT: entry:132 // CHECK-NEXT: %Data.addr = alloca ptr, align 8133 // CHECK-NEXT: %Arg = alloca %class.MatrixClassTemplate, align 8134 // CHECK-NEXT: store ptr %Data, ptr %Data.addr, align 8135 // CHECK-NEXT: %0 = load ptr, ptr %Data.addr, align 8136 // CHECK-NEXT: %1 = load <150 x float>, ptr %0, align 4137 // CHECK-NEXT: %Data1 = getelementptr inbounds nuw %class.MatrixClassTemplate, ptr %Arg, i32 0, i32 1138 // CHECK-NEXT: store <150 x float> %1, ptr %Data1, align 4139 // 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 void141 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 8145 // CHECK-NEXT: %b.addr = alloca ptr, align 8146 // CHECK-NEXT: store ptr %a, ptr %a.addr, align 8147 // CHECK-NEXT: store ptr %b, ptr %b.addr, align 8148 // CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8149 // CHECK-NEXT: %Data = getelementptr inbounds nuw %class.MatrixClassTemplate, ptr %0, i32 0, i32 1150 // CHECK-NEXT: %1 = load <150 x float>, ptr %Data, align 4151 // CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 8152 // CHECK-NEXT: %Data1 = getelementptr inbounds nuw %class.MatrixClassTemplate, ptr %2, i32 0, i32 1153 // CHECK-NEXT: store <150 x float> %1, ptr %Data1, align 4154 // CHECK-NEXT: ret void155 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 162template <class T, unsigned long R, unsigned long C>163using matrix = T __attribute__((matrix_type(R, C)));164 165template <int N>166struct selector {};167 168template <class T, unsigned long R, unsigned long C>169selector<0> use_matrix(matrix<T, R, C> &m) {}170 171template <class T, unsigned long R>172selector<1> use_matrix(matrix<T, R, 10> &m) {}173 174template <class T>175selector<2> use_matrix(matrix<T, 10, 10> &m) {}176 177template <class T, unsigned long C>178selector<3> use_matrix(matrix<T, 10, C> &m) {}179 180template <unsigned long R, unsigned long C>181selector<4> use_matrix(matrix<float, R, C> &m) {}182 183void 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 4188 // CHECK-NEXT: %w = alloca %struct.selector, align 1189 // CHECK-NEXT: %undef.agg.tmp = alloca %struct.selector, align 1190 // CHECK-NEXT: %m1 = alloca [100 x i32], align 4191 // CHECK-NEXT: %x = alloca %struct.selector.0, align 1192 // CHECK-NEXT: %undef.agg.tmp1 = alloca %struct.selector.0, align 1193 // CHECK-NEXT: %m2 = alloca [120 x i32], align 4194 // CHECK-NEXT: %y = alloca %struct.selector.1, align 1195 // CHECK-NEXT: %undef.agg.tmp2 = alloca %struct.selector.1, align 1196 // CHECK-NEXT: %m3 = alloca [144 x i32], align 4197 // CHECK-NEXT: %z = alloca %struct.selector.2, align 1198 // CHECK-NEXT: %undef.agg.tmp3 = alloca %struct.selector.2, align 1199 // CHECK-NEXT: %m4 = alloca [144 x float], align 4200 // CHECK-NEXT: %v = alloca %struct.selector.3, align 1201 // CHECK-NEXT: %undef.agg.tmp4 = alloca %struct.selector.3, align 1202 // 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 void208 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 8212 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8213 // CHECK-NEXT: call void @llvm.trap()214 // CHECK-NEXT: unreachable215 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 8219 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8220 // CHECK-NEXT: call void @llvm.trap()221 // CHECK-NEXT: unreachable222 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 8226 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8227 // CHECK-NEXT: call void @llvm.trap()228 // CHECK-NEXT: unreachable229 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 8233 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8234 // CHECK-NEXT: call void @llvm.trap()235 // CHECK-NEXT: unreachable236 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 8240 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8241 // CHECK-NEXT: call void @llvm.trap()242 // CHECK-NEXT: unreachable243 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 256template <auto R>257void foo(matrix<int, R, 10> &m) {258}259 260void test_auto_t() {261 // CHECK-LABEL: define{{.*}} void @_Z11test_auto_tv()262 // CHECK-NEXT: entry:263 // CHECK-NEXT: %m = alloca [130 x i32], align 4264 // CHECK-NEXT: call void @_Z3fooITnDaLm13EEvRu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(520) %m)265 // CHECK-NEXT: ret void266 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 8270 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8271 // CHECK-NEXT: ret void272 273 matrix<int, 13, 10> m;274 foo(m);275}276 277template <unsigned long R, unsigned long C>278matrix<float, R + 1, C + 2> use_matrix_2(matrix<int, R, C> &m) {}279 280template <unsigned long R, unsigned long C>281selector<0> use_matrix_2(matrix<int, R + 2, C / 2> &m1, matrix<float, R, C> &m2) {}282 283template <unsigned long R, unsigned long C>284selector<1> use_matrix_2(matrix<int, R + C, C> &m1, matrix<float, R, C - R> &m2) {}285 286template <unsigned long R>287matrix<float, R + R, R - 3> use_matrix_2(matrix<int, R, 10> &m1) {}288 289template <unsigned long R>290selector<2> use_matrix_3(matrix<int, R - 2, R> &m) {}291 292void 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 4296 // CHECK-NEXT: %r1 = alloca [40 x float], align 4297 // CHECK-NEXT: %m2 = alloca [24 x float], align 4298 // CHECK-NEXT: %r2 = alloca %struct.selector.2, align 1299 // CHECK-NEXT: %undef.agg.tmp = alloca %struct.selector.2, align 1300 // CHECK-NEXT: %m3 = alloca [104 x i32], align 4301 // CHECK-NEXT: %m4 = alloca [15 x float], align 4302 // CHECK-NEXT: %r3 = alloca %struct.selector.1, align 1303 // CHECK-NEXT: %undef.agg.tmp1 = alloca %struct.selector.1, align 1304 // CHECK-NEXT: %m5 = alloca [50 x i32], align 4305 // CHECK-NEXT: %r4 = alloca [20 x float], align 4306 // CHECK-NEXT: %r5 = alloca %struct.selector.0, align 1307 // CHECK-NEXT: %undef.agg.tmp3 = alloca %struct.selector.0, align 1308 // 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 4310 // 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 4314 // CHECK-NEXT: call void @_Z12use_matrix_3ILm6EE8selectorILi2EERu11matrix_typeIXmiT_Li2EEXT_EiE(ptr nonnull align 4 dereferenceable(96) %m1)315 // CHECK-NEXT: ret void316 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 8320 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8321 // CHECK-NEXT: call void @llvm.trap()322 // CHECK-NEXT: unreachable323 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 8327 // CHECK-NEXT: %m2.addr = alloca ptr, align 8328 // CHECK-NEXT: store ptr %m1, ptr %m1.addr, align 8329 // CHECK-NEXT: store ptr %m2, ptr %m2.addr, align 8330 // CHECK-NEXT: call void @llvm.trap()331 // CHECK-NEXT: unreachable332 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 8336 // CHECK-NEXT: %m2.addr = alloca ptr, align 8337 // CHECK-NEXT: store ptr %m1, ptr %m1.addr, align 8338 // CHECK-NEXT: store ptr %m2, ptr %m2.addr, align 8339 // CHECK-NEXT: call void @llvm.trap()340 // CHECK-NEXT: unreachable341 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 8345 // CHECK-NEXT: store ptr %m1, ptr %m1.addr, align 8346 // CHECK-NEXT: call void @llvm.trap()347 // CHECK-NEXT: unreachable348 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 8352 // CHECK-NEXT: store ptr %m, ptr %m.addr, align 8353 // CHECK-NEXT: call void @llvm.trap()354 // CHECK-NEXT: unreachable355 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 8375// CHECK-NEXT: %b = alloca [12 x float], align 4376// CHECK-NEXT: %0 = load <25 x double>, ptr %a, align 8377// CHECK-NEXT: call void @_Z17pseudo_destructorIu11matrix_typeILm5ELm5EdEEvT_(<25 x double> %0)378// CHECK-NEXT: %1 = load <12 x float>, ptr %b, align 4379// CHECK-NEXT: call void @_Z17pseudo_destructorIu11matrix_typeILm3ELm4EfEEvT_(<12 x float> %1)380// CHECK-NEXT: ret void381 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 8385// CHECK-NEXT: store <25 x double> %t, ptr %t.addr, align 8386// CHECK-NEXT: ret void387 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 4391// CHECK-NEXT: store <12 x float> %t, ptr %t.addr, align 4392// CHECK-NEXT: ret void393template <typename T>394void pseudo_destructor(T t) {395 t.~T();396}397 398void test_pseudo_destructor() {399 dx5x5_t a;400 fx3x4_t b;401 pseudo_destructor(a);402 pseudo_destructor(b);403}404