1 // RUN: %clang_cc1 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s 2 3 #if !__has_extension(matrix_types) 4 #error Expected extension 'matrix_types' to be enabled 5 #endif 6 7 typedef double dx5x5_t __attribute__((matrix_type(5, 5))); 8 9 // CHECK: %struct.Matrix = type { i8, [12 x float], float } 10 11 void load_store_double(dx5x5_t *a, dx5x5_t *b) { 12 // CHECK-LABEL: define void @load_store_double( 13 // CHECK-NEXT: entry: 14 // CHECK-NEXT: %a.addr = alloca [25 x double]*, align 8 15 // CHECK-NEXT: %b.addr = alloca [25 x double]*, align 8 16 // CHECK-NEXT: store [25 x double]* %a, [25 x double]** %a.addr, align 8 17 // CHECK-NEXT: store [25 x double]* %b, [25 x double]** %b.addr, align 8 18 // CHECK-NEXT: %0 = load [25 x double]*, [25 x double]** %b.addr, align 8 19 // CHECK-NEXT: %1 = bitcast [25 x double]* %0 to <25 x double>* 20 // CHECK-NEXT: %2 = load <25 x double>, <25 x double>* %1, align 8 21 // CHECK-NEXT: %3 = load [25 x double]*, [25 x double]** %a.addr, align 8 22 // CHECK-NEXT: %4 = bitcast [25 x double]* %3 to <25 x double>* 23 // CHECK-NEXT: store <25 x double> %2, <25 x double>* %4, align 8 24 // CHECK-NEXT: ret void 25 26 *a = *b; 27 } 28 29 typedef float fx3x4_t __attribute__((matrix_type(3, 4))); 30 void load_store_float(fx3x4_t *a, fx3x4_t *b) { 31 // CHECK-LABEL: define void @load_store_float( 32 // CHECK-NEXT: entry: 33 // CHECK-NEXT: %a.addr = alloca [12 x float]*, align 8 34 // CHECK-NEXT: %b.addr = alloca [12 x float]*, align 8 35 // CHECK-NEXT: store [12 x float]* %a, [12 x float]** %a.addr, align 8 36 // CHECK-NEXT: store [12 x float]* %b, [12 x float]** %b.addr, align 8 37 // CHECK-NEXT: %0 = load [12 x float]*, [12 x float]** %b.addr, align 8 38 // CHECK-NEXT: %1 = bitcast [12 x float]* %0 to <12 x float>* 39 // CHECK-NEXT: %2 = load <12 x float>, <12 x float>* %1, align 4 40 // CHECK-NEXT: %3 = load [12 x float]*, [12 x float]** %a.addr, align 8 41 // CHECK-NEXT: %4 = bitcast [12 x float]* %3 to <12 x float>* 42 // CHECK-NEXT: store <12 x float> %2, <12 x float>* %4, align 4 43 // CHECK-NEXT: ret void 44 45 *a = *b; 46 } 47 48 typedef int ix3x4_t __attribute__((matrix_type(4, 3))); 49 void load_store_int(ix3x4_t *a, ix3x4_t *b) { 50 // CHECK-LABEL: define void @load_store_int( 51 // CHECK-NEXT: entry: 52 // CHECK-NEXT: %a.addr = alloca [12 x i32]*, align 8 53 // CHECK-NEXT: %b.addr = alloca [12 x i32]*, align 8 54 // CHECK-NEXT: store [12 x i32]* %a, [12 x i32]** %a.addr, align 8 55 // CHECK-NEXT: store [12 x i32]* %b, [12 x i32]** %b.addr, align 8 56 // CHECK-NEXT: %0 = load [12 x i32]*, [12 x i32]** %b.addr, align 8 57 // CHECK-NEXT: %1 = bitcast [12 x i32]* %0 to <12 x i32>* 58 // CHECK-NEXT: %2 = load <12 x i32>, <12 x i32>* %1, align 4 59 // CHECK-NEXT: %3 = load [12 x i32]*, [12 x i32]** %a.addr, align 8 60 // CHECK-NEXT: %4 = bitcast [12 x i32]* %3 to <12 x i32>* 61 // CHECK-NEXT: store <12 x i32> %2, <12 x i32>* %4, align 4 62 // CHECK-NEXT: ret void 63 64 *a = *b; 65 } 66 67 typedef unsigned long long ullx3x4_t __attribute__((matrix_type(4, 3))); 68 void load_store_ull(ullx3x4_t *a, ullx3x4_t *b) { 69 // CHECK-LABEL: define void @load_store_ull( 70 // CHECK-NEXT: entry: 71 // CHECK-NEXT: %a.addr = alloca [12 x i64]*, align 8 72 // CHECK-NEXT: %b.addr = alloca [12 x i64]*, align 8 73 // CHECK-NEXT: store [12 x i64]* %a, [12 x i64]** %a.addr, align 8 74 // CHECK-NEXT: store [12 x i64]* %b, [12 x i64]** %b.addr, align 8 75 // CHECK-NEXT: %0 = load [12 x i64]*, [12 x i64]** %b.addr, align 8 76 // CHECK-NEXT: %1 = bitcast [12 x i64]* %0 to <12 x i64>* 77 // CHECK-NEXT: %2 = load <12 x i64>, <12 x i64>* %1, align 8 78 // CHECK-NEXT: %3 = load [12 x i64]*, [12 x i64]** %a.addr, align 8 79 // CHECK-NEXT: %4 = bitcast [12 x i64]* %3 to <12 x i64>* 80 // CHECK-NEXT: store <12 x i64> %2, <12 x i64>* %4, align 8 81 // CHECK-NEXT: ret void 82 83 *a = *b; 84 } 85 86 typedef __fp16 fp16x3x4_t __attribute__((matrix_type(4, 3))); 87 void load_store_fp16(fp16x3x4_t *a, fp16x3x4_t *b) { 88 // CHECK-LABEL: define void @load_store_fp16( 89 // CHECK-NEXT: entry: 90 // CHECK-NEXT: %a.addr = alloca [12 x half]*, align 8 91 // CHECK-NEXT: %b.addr = alloca [12 x half]*, align 8 92 // CHECK-NEXT: store [12 x half]* %a, [12 x half]** %a.addr, align 8 93 // CHECK-NEXT: store [12 x half]* %b, [12 x half]** %b.addr, align 8 94 // CHECK-NEXT: %0 = load [12 x half]*, [12 x half]** %b.addr, align 8 95 // CHECK-NEXT: %1 = bitcast [12 x half]* %0 to <12 x half>* 96 // CHECK-NEXT: %2 = load <12 x half>, <12 x half>* %1, align 2 97 // CHECK-NEXT: %3 = load [12 x half]*, [12 x half]** %a.addr, align 8 98 // CHECK-NEXT: %4 = bitcast [12 x half]* %3 to <12 x half>* 99 // CHECK-NEXT: store <12 x half> %2, <12 x half>* %4, align 2 100 // CHECK-NEXT: ret void 101 102 *a = *b; 103 } 104 105 typedef float fx3x3_t __attribute__((matrix_type(3, 3))); 106 107 void parameter_passing(fx3x3_t a, fx3x3_t *b) { 108 // CHECK-LABEL: define void @parameter_passing( 109 // CHECK-NEXT: entry: 110 // CHECK-NEXT: %a.addr = alloca [9 x float], align 4 111 // CHECK-NEXT: %b.addr = alloca [9 x float]*, align 8 112 // CHECK-NEXT: %0 = bitcast [9 x float]* %a.addr to <9 x float>* 113 // CHECK-NEXT: store <9 x float> %a, <9 x float>* %0, align 4 114 // CHECK-NEXT: store [9 x float]* %b, [9 x float]** %b.addr, align 8 115 // CHECK-NEXT: %1 = load <9 x float>, <9 x float>* %0, align 4 116 // CHECK-NEXT: %2 = load [9 x float]*, [9 x float]** %b.addr, align 8 117 // CHECK-NEXT: %3 = bitcast [9 x float]* %2 to <9 x float>* 118 // CHECK-NEXT: store <9 x float> %1, <9 x float>* %3, align 4 119 // CHECK-NEXT: ret void 120 *b = a; 121 } 122 123 fx3x3_t return_matrix(fx3x3_t *a) { 124 // CHECK-LABEL: define <9 x float> @return_matrix 125 // CHECK-NEXT: entry: 126 // CHECK-NEXT: %a.addr = alloca [9 x float]*, align 8 127 // CHECK-NEXT: store [9 x float]* %a, [9 x float]** %a.addr, align 8 128 // CHECK-NEXT: %0 = load [9 x float]*, [9 x float]** %a.addr, align 8 129 // CHECK-NEXT: %1 = bitcast [9 x float]* %0 to <9 x float>* 130 // CHECK-NEXT: %2 = load <9 x float>, <9 x float>* %1, align 4 131 // CHECK-NEXT: ret <9 x float> %2 132 return *a; 133 } 134 135 typedef struct { 136 char Tmp1; 137 fx3x4_t Data; 138 float Tmp2; 139 } Matrix; 140 141 void matrix_struct(Matrix *a, Matrix *b) { 142 // CHECK-LABEL: define void @matrix_struct( 143 // CHECK-NEXT: entry: 144 // CHECK-NEXT: %a.addr = alloca %struct.Matrix*, align 8 145 // CHECK-NEXT: %b.addr = alloca %struct.Matrix*, align 8 146 // CHECK-NEXT: store %struct.Matrix* %a, %struct.Matrix** %a.addr, align 8 147 // CHECK-NEXT: store %struct.Matrix* %b, %struct.Matrix** %b.addr, align 8 148 // CHECK-NEXT: %0 = load %struct.Matrix*, %struct.Matrix** %a.addr, align 8 149 // CHECK-NEXT: %Data = getelementptr inbounds %struct.Matrix, %struct.Matrix* %0, i32 0, i32 1 150 // CHECK-NEXT: %1 = bitcast [12 x float]* %Data to <12 x float>* 151 // CHECK-NEXT: %2 = load <12 x float>, <12 x float>* %1, align 4 152 // CHECK-NEXT: %3 = load %struct.Matrix*, %struct.Matrix** %b.addr, align 8 153 // CHECK-NEXT: %Data1 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %3, i32 0, i32 1 154 // CHECK-NEXT: %4 = bitcast [12 x float]* %Data1 to <12 x float>* 155 // CHECK-NEXT: store <12 x float> %2, <12 x float>* %4, align 4 156 // CHECK-NEXT: ret void 157 b->Data = a->Data; 158 } 159 160 typedef double dx4x4_t __attribute__((matrix_type(4, 4))); 161 void matrix_inline_asm_memory_readwrite() { 162 // CHECK-LABEL: define void @matrix_inline_asm_memory_readwrite() 163 // CHECK-NEXT: entry: 164 // CHECK-NEXT: [[ALLOCA:%.+]] = alloca [16 x double], align 8 165 // CHECK-NEXT: [[PTR1:%.+]] = bitcast [16 x double]* [[ALLOCA]] to <16 x double>* 166 // CHECK-NEXT: [[PTR2:%.+]] = bitcast [16 x double]* [[ALLOCA]] to <16 x double>* 167 // CHECK-NEXT: [[VAL:%.+]] = load <16 x double>, <16 x double>* [[PTR2]], align 8 168 // CHECK-NEXT: call void asm sideeffect "", "=*r|m,0,~{memory},~{dirflag},~{fpsr},~{flags}"(<16 x double>* [[PTR1]], <16 x double> [[VAL]]) 169 // CHECK-NEXT: ret void 170 171 dx4x4_t m; 172 asm volatile("" 173 : "+r,m"(m) 174 : 175 : "memory"); 176 } 177