1 // RUN: %clang_cc1 -ffast-math -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s 2 3 typedef double dx5x5_t __attribute__((matrix_type(5, 5))); 4 typedef float fx2x3_t __attribute__((matrix_type(2, 3))); 5 typedef int ix9x3_t __attribute__((matrix_type(9, 3))); 6 typedef unsigned long long ullx4x2_t __attribute__((matrix_type(4, 2))); 7 8 // Floating point matrix/scalar additions. 9 10 void add_matrix_matrix_double(dx5x5_t a, dx5x5_t b, dx5x5_t c) { 11 // CHECK-LABEL: define{{.*}} void @add_matrix_matrix_double(<25 x double> noundef nofpclass(nan inf) %a, <25 x double> noundef nofpclass(nan inf) %b, <25 x double> noundef nofpclass(nan inf) %c) 12 // CHECK: [[B:%.*]] = load <25 x double>, ptr {{.*}}, align 8 13 // CHECK-NEXT: [[C:%.*]] = load <25 x double>, ptr {{.*}}, align 8 14 // CHECK-NEXT: [[RES:%.*]] = fadd reassoc nnan ninf nsz arcp afn <25 x double> [[B]], [[C]] 15 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 16 17 a = b + c; 18 } 19 20 void add_compound_assign_matrix_double(dx5x5_t a, dx5x5_t b) { 21 // CHECK-LABEL: define{{.*}} void @add_compound_assign_matrix_double(<25 x double> noundef nofpclass(nan inf) %a, <25 x double> noundef nofpclass(nan inf) %b) 22 // CHECK: [[B:%.*]] = load <25 x double>, ptr {{.*}}, align 8 23 // CHECK-NEXT: [[A:%.*]] = load <25 x double>, ptr {{.*}}, align 8 24 // CHECK-NEXT: [[RES:%.*]] = fadd reassoc nnan ninf nsz arcp afn <25 x double> [[A]], [[B]] 25 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 26 27 a += b; 28 } 29 30 void subtract_compound_assign_matrix_double(dx5x5_t a, dx5x5_t b) { 31 // CHECK-LABEL: define{{.*}} void @subtract_compound_assign_matrix_double(<25 x double> noundef nofpclass(nan inf) %a, <25 x double> noundef nofpclass(nan inf) %b) 32 // CHECK: [[B:%.*]] = load <25 x double>, ptr {{.*}}, align 8 33 // CHECK-NEXT: [[A:%.*]] = load <25 x double>, ptr {{.*}}, align 8 34 // CHECK-NEXT: [[RES:%.*]] = fsub reassoc nnan ninf nsz arcp afn <25 x double> [[A]], [[B]] 35 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 36 37 a -= b; 38 } 39 40 void add_matrix_scalar_double_float(dx5x5_t a, float vf) { 41 // CHECK-LABEL: define{{.*}} void @add_matrix_scalar_double_float(<25 x double> noundef nofpclass(nan inf) %a, float noundef nofpclass(nan inf) %vf) 42 // CHECK: [[MATRIX:%.*]] = load <25 x double>, ptr {{.*}}, align 8 43 // CHECK-NEXT: [[SCALAR:%.*]] = load float, ptr %vf.addr, align 4 44 // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[SCALAR]] to double 45 // CHECK-NEXT: [[SCALAR_EMBED:%.*]] = insertelement <25 x double> poison, double [[SCALAR_EXT]], i64 0 46 // CHECK-NEXT: [[SCALAR_EMBED1:%.*]] = shufflevector <25 x double> [[SCALAR_EMBED]], <25 x double> poison, <25 x i32> zeroinitializer 47 // CHECK-NEXT: [[RES:%.*]] = fadd reassoc nnan ninf nsz arcp afn <25 x double> [[MATRIX]], [[SCALAR_EMBED1]] 48 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 49 50 a = a + vf; 51 } 52 53 void add_compound_matrix_scalar_double_float(dx5x5_t a, float vf) { 54 // CHECK-LABEL: define{{.*}} void @add_compound_matrix_scalar_double_float(<25 x double> noundef nofpclass(nan inf) %a, float noundef nofpclass(nan inf) %vf) 55 // CHECK: [[SCALAR:%.*]] = load float, ptr %vf.addr, align 4 56 // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[SCALAR]] to double 57 // CHECK-NEXT: [[MATRIX:%.*]] = load <25 x double>, ptr {{.*}}, align 8 58 // CHECK-NEXT: [[SCALAR_EMBED:%.*]] = insertelement <25 x double> poison, double [[SCALAR_EXT]], i64 0 59 // CHECK-NEXT: [[SCALAR_EMBED1:%.*]] = shufflevector <25 x double> [[SCALAR_EMBED]], <25 x double> poison, <25 x i32> zeroinitializer 60 // CHECK-NEXT: [[RES:%.*]] = fadd reassoc nnan ninf nsz arcp afn <25 x double> [[MATRIX]], [[SCALAR_EMBED1]] 61 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 62 63 a += vf; 64 } 65 66 void subtract_compound_matrix_scalar_double_float(dx5x5_t a, float vf) { 67 // CHECK-LABEL: define{{.*}} void @subtract_compound_matrix_scalar_double_float(<25 x double> noundef nofpclass(nan inf) %a, float noundef nofpclass(nan inf) %vf) 68 // CHECK: [[SCALAR:%.*]] = load float, ptr %vf.addr, align 4 69 // CHECK-NEXT: [[SCALAR_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[SCALAR]] to double 70 // CHECK-NEXT: [[MATRIX:%.*]] = load <25 x double>, ptr {{.*}}, align 8 71 // CHECK-NEXT: [[SCALAR_EMBED:%.*]] = insertelement <25 x double> poison, double [[SCALAR_EXT]], i64 0 72 // CHECK-NEXT: [[SCALAR_EMBED1:%.*]] = shufflevector <25 x double> [[SCALAR_EMBED]], <25 x double> poison, <25 x i32> zeroinitializer 73 // CHECK-NEXT: [[RES:%.*]] = fsub reassoc nnan ninf nsz arcp afn <25 x double> [[MATRIX]], [[SCALAR_EMBED1]] 74 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 75 76 a -= vf; 77 } 78 79 // Tests for matrix multiplication. 80 81 void multiply_matrix_matrix_double(dx5x5_t b, dx5x5_t c) { 82 // CHECK-LABEL: @multiply_matrix_matrix_double( 83 // CHECK: [[B:%.*]] = load <25 x double>, ptr {{.*}}, align 8 84 // CHECK-NEXT: [[C:%.*]] = load <25 x double>, ptr {{.*}}, align 8 85 // CHECK-NEXT: [[RES:%.*]] = call reassoc nnan ninf nsz arcp afn <25 x double> @llvm.matrix.multiply.v25f64.v25f64.v25f64(<25 x double> [[B]], <25 x double> [[C]], i32 5, i32 5, i32 5) 86 // CHECK-NEXT: store <25 x double> [[RES]], ptr %a, align 8 87 // CHECK-NEXT: ret void 88 // 89 90 dx5x5_t a; 91 a = b * c; 92 } 93 94 void multiply_compound_matrix_matrix_double(dx5x5_t b, dx5x5_t c) { 95 // CHECK-LABEL: @multiply_compound_matrix_matrix_double( 96 // CHECK: [[C:%.*]] = load <25 x double>, ptr {{.*}}, align 8 97 // CHECK-NEXT: [[B:%.*]] = load <25 x double>, ptr {{.*}}, align 8 98 // CHECK-NEXT: [[RES:%.*]] = call reassoc nnan ninf nsz arcp afn <25 x double> @llvm.matrix.multiply.v25f64.v25f64.v25f64(<25 x double> [[B]], <25 x double> [[C]], i32 5, i32 5, i32 5) 99 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 100 // CHECK-NEXT: ret void 101 b *= c; 102 } 103 104 // CHECK-LABEL: @multiply_double_matrix_scalar_float( 105 // CHECK: [[A:%.*]] = load <25 x double>, ptr {{.*}}, align 8 106 // CHECK-NEXT: [[S:%.*]] = load float, ptr %s.addr, align 4 107 // CHECK-NEXT: [[S_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[S]] to double 108 // CHECK-NEXT: [[VECINSERT:%.*]] = insertelement <25 x double> poison, double [[S_EXT]], i64 0 109 // CHECK-NEXT: [[VECSPLAT:%.*]] = shufflevector <25 x double> [[VECINSERT]], <25 x double> poison, <25 x i32> zeroinitializer 110 // CHECK-NEXT: [[RES:%.*]] = fmul reassoc nnan ninf nsz arcp afn <25 x double> [[A]], [[VECSPLAT]] 111 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 112 // CHECK-NEXT: ret void 113 // 114 void multiply_double_matrix_scalar_float(dx5x5_t a, float s) { 115 a = a * s; 116 } 117 118 // CHECK-LABEL: @multiply_compound_double_matrix_scalar_float 119 // CHECK: [[S:%.*]] = load float, ptr %s.addr, align 4 120 // CHECK-NEXT: [[S_EXT:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[S]] to double 121 // CHECK-NEXT: [[A:%.*]] = load <25 x double>, ptr {{.*}}, align 8 122 // CHECK-NEXT: [[VECINSERT:%.*]] = insertelement <25 x double> poison, double [[S_EXT]], i64 0 123 // CHECK-NEXT: [[VECSPLAT:%.*]] = shufflevector <25 x double> [[VECINSERT]], <25 x double> poison, <25 x i32> zeroinitializer 124 // CHECK-NEXT: [[RES:%.*]] = fmul reassoc nnan ninf nsz arcp afn <25 x double> [[A]], [[VECSPLAT]] 125 // CHECK-NEXT: store <25 x double> [[RES]], ptr {{.*}}, align 8 126 // CHECK-NEXT: ret void 127 // 128 void multiply_compound_double_matrix_scalar_float(dx5x5_t a, float s) { 129 a *= s; 130 } 131 132 // CHECK-LABEL: @divide_float_matrix_scalar_double( 133 // CHECK: [[MAT:%.*]] = load <6 x float>, ptr [[MAT_ADDR:%.*]], align 4 134 // CHECK-NEXT: [[S:%.*]] = load double, ptr %s.addr, align 8 135 // CHECK-NEXT: [[S_TRUNC:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[S]] to float 136 // CHECK-NEXT: [[VECINSERT:%.*]] = insertelement <6 x float> poison, float [[S_TRUNC]], i64 0 137 // CHECK-NEXT: [[VECSPLAT:%.*]] = shufflevector <6 x float> [[VECINSERT]], <6 x float> poison, <6 x i32> zeroinitializer 138 // CHECK-NEXT: [[RES:%.*]] = fdiv reassoc nnan ninf nsz arcp afn <6 x float> [[MAT]], [[VECSPLAT]] 139 // CHECK-NEXT: store <6 x float> [[RES]], ptr [[MAT_ADDR]], align 4 140 // CHECK-NEXT: ret void 141 // 142 void divide_float_matrix_scalar_double(fx2x3_t b, double s) { 143 b = b / s; 144 } 145