xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/arm/arm-mve-builtins.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* ACLE support for Arm MVE
2    Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 
4    This file is part of GCC.
5 
6    GCC is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    GCC is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with GCC; see the file COPYING3.  If not see
18    <http://www.gnu.org/licenses/>.  */
19 
20 #define IN_TARGET_CODE 1
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "fold-const.h"
28 #include "langhooks.h"
29 #include "stringpool.h"
30 #include "attribs.h"
31 #include "diagnostic.h"
32 #include "arm-protos.h"
33 #include "arm-builtins.h"
34 #include "arm-mve-builtins.h"
35 
36 namespace arm_mve {
37 
38 /* Static information about each single-predicate or single-vector
39    ACLE type.  */
40 struct vector_type_info
41 {
42   /* The name of the type as declared by arm_mve.h.  */
43   const char *acle_name;
44 
45   /* Whether the type requires a floating point abi.  */
46   const bool requires_float;
47 };
48 
49 /* Flag indicating whether the arm MVE types have been handled.  */
50 static bool handle_arm_mve_types_p;
51 
52 /* Information about each single-predicate or single-vector type.  */
53 static CONSTEXPR const vector_type_info vector_types[] = {
54 #define DEF_MVE_TYPE(ACLE_NAME, SCALAR_TYPE) \
55   { #ACLE_NAME, REQUIRES_FLOAT },
56 #include "arm-mve-builtins.def"
57 #undef DEF_MVE_TYPE
58 };
59 
60 /* The scalar type associated with each vector type.  */
61 GTY(()) tree scalar_types[NUM_VECTOR_TYPES];
62 
63 /* The single-predicate and single-vector types, with their built-in
64    "__simd128_..._t" name.  Allow an index of NUM_VECTOR_TYPES, which always
65    yields a null tree.  */
66 static GTY(()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
67 
68 /* Same, but with the arm_mve.h names.  */
69 GTY(()) tree acle_vector_types[3][NUM_VECTOR_TYPES + 1];
70 
71 /* Return the MVE abi type with element of type TYPE.  */
72 static tree
arm_mve_type_for_scalar_type(tree eltype)73 arm_mve_type_for_scalar_type (tree eltype)
74 {
75   for (unsigned int i = 0; i < __TYPE_FINAL; ++i)
76       if (arm_simd_types[i].eltype == eltype
77 	  && GET_MODE_SIZE (arm_simd_types[i].mode) == 16)
78 	return arm_simd_types[i].itype;
79 
80   gcc_unreachable ();
81 }
82 
83 /* Register the built-in MVE ABI vector types, such as uint32x4_t.  */
84 static void
register_builtin_types()85 register_builtin_types ()
86 {
87 #define DEF_MVE_TYPE(ACLE_NAME, SCALAR_TYPE) \
88   scalar_types[VECTOR_TYPE_ ## ACLE_NAME] = SCALAR_TYPE;
89 #include "arm-mve-builtins.def"
90 #undef DEF_MVE_TYPE
91   for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i)
92     {
93       if (vector_types[i].requires_float && !TARGET_HAVE_MVE_FLOAT)
94 	continue;
95       tree eltype = scalar_types[i];
96       tree vectype;
97       if (eltype == boolean_type_node)
98 	{
99 	  vectype = get_typenode_from_name (UINT16_TYPE);
100 	  gcc_assert (GET_MODE_SIZE (TYPE_MODE (vectype)) == 2);
101 	}
102       else
103 	{
104 	  vectype = arm_mve_type_for_scalar_type (eltype);
105 	  gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype))
106 		      && GET_MODE_SIZE (TYPE_MODE (vectype)) == 16);
107 	}
108       abi_vector_types[i] = vectype;
109     }
110 }
111 
112 /* Register vector type TYPE under its arm_mve.h name.  */
113 static void
register_vector_type(vector_type_index type)114 register_vector_type (vector_type_index type)
115 {
116   if (vector_types[type].requires_float && !TARGET_HAVE_MVE_FLOAT)
117     return;
118   tree vectype = abi_vector_types[type];
119   tree id = get_identifier (vector_types[type].acle_name);
120   tree decl = build_decl (input_location, TYPE_DECL, id, vectype);
121   decl = lang_hooks.decls.pushdecl (decl);
122 
123   /* Record the new ACLE type if pushdecl succeeded without error.  Use
124      the ABI type otherwise, so that the type we record at least has the
125      right form, even if it doesn't have the right name.  This should give
126      better error recovery behavior than installing error_mark_node or
127      installing an incorrect type.  */
128   if (decl
129       && TREE_CODE (decl) == TYPE_DECL
130       && TREE_TYPE (decl) != error_mark_node
131       && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == vectype)
132     vectype = TREE_TYPE (decl);
133   acle_vector_types[0][type] = vectype;
134 }
135 
136 /* Register tuple type TYPE with NUM_VECTORS arity under its
137    arm_mve_types.h name.  */
138 static void
register_builtin_tuple_types(vector_type_index type)139 register_builtin_tuple_types (vector_type_index type)
140 {
141   const vector_type_info* info = &vector_types[type];
142   if (scalar_types[type] == boolean_type_node
143       || (info->requires_float && !TARGET_HAVE_MVE_FLOAT))
144     return;
145   const char *vector_type_name = info->acle_name;
146   char buffer[sizeof ("float32x4x2_t")];
147   for (unsigned int num_vectors = 2; num_vectors <= 4; num_vectors += 2)
148     {
149       snprintf (buffer, sizeof (buffer), "%.*sx%d_t",
150 		(int) strlen (vector_type_name) - 2, vector_type_name,
151 		num_vectors);
152 
153       tree vectype = acle_vector_types[0][type];
154       tree arrtype = build_array_type_nelts (vectype, num_vectors);
155       gcc_assert (TYPE_MODE_RAW (arrtype) == TYPE_MODE (arrtype));
156       tree field = build_decl (input_location, FIELD_DECL,
157 			       get_identifier ("val"), arrtype);
158 
159       tree t = lang_hooks.types.simulate_record_decl (input_location, buffer,
160 						      make_array_slice (&field,
161 									1));
162       gcc_assert (TYPE_MODE_RAW (t) == TYPE_MODE (t));
163       acle_vector_types[num_vectors >> 1][type] = TREE_TYPE (t);
164     }
165 }
166 
167 /* Implement #pragma GCC arm "arm_mve_types.h".  */
168 void
handle_arm_mve_types_h()169 handle_arm_mve_types_h ()
170 {
171   if (handle_arm_mve_types_p)
172     {
173       error ("duplicate definition of %qs", "arm_mve_types.h");
174       return;
175     }
176   handle_arm_mve_types_p = true;
177   if (!TARGET_HAVE_MVE)
178     {
179       error ("this definition requires the MVE ISA extension");
180       return;
181     }
182   register_builtin_types ();
183   for (unsigned int type_i = 0; type_i < NUM_VECTOR_TYPES; ++type_i)
184     {
185       vector_type_index type = vector_type_index (type_i);
186       register_vector_type (type);
187       if (type_i != VECTOR_TYPE_mve_pred16_t)
188 	register_builtin_tuple_types (type);
189     }
190 }
191 
192 } /* end namespace arm_mve */
193 
194 using namespace arm_mve;
195 
196 #include "gt-arm-mve-builtins.h"
197