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