[v2,08/11] Native complex ops: Add explicit vector of complex
Checks
Commit Message
Summary:
Allow the creation and usage of builtins vectors of complex
in C, using __attribute__ ((vector_size ()))
gcc/c-family/ChangeLog:
* c-attribs.cc (vector_mode_valid_p): Add cases for
vectors of complex
(handle_mode_attribute): Likewise
(type_valid_for_vector_size): Likewise
* c-common.cc (c_common_type_for_mode): Likewise
(vector_types_compatible_elements_p): Likewise
gcc/ChangeLog:
* fold-const.cc (fold_binary_loc): Likewise
gcc/c/ChangeLog:
* c-typeck.cc (build_unary_op): Likewise
---
gcc/c-family/c-attribs.cc | 12 ++++++++++--
gcc/c-family/c-common.cc | 21 +++++++++++++++++++--
gcc/c/c-typeck.cc | 8 ++++++--
gcc/fold-const.cc | 1 +
4 files changed, 36 insertions(+), 6 deletions(-)
Comments
On Tue, 12 Sep 2023, Sylvain Noiry via Gcc-patches wrote:
> Summary:
> Allow the creation and usage of builtins vectors of complex
> in C, using __attribute__ ((vector_size ()))
If you're adding a new language feature like this, you need to update
extend.texi to explain the valid uses of the attribute for complex types,
and (under "Vector Extensions") the valid uses of the resulting vectors.
You also need to add testcases to the testsuite for such vectors - both
execution tests covering valid uses of the vectors, and tests that invalid
declarations or uses of such vectors (uses with any operator, or other
operand to such operator, that aren't valid) are properly rejected - go
through all cases of operators, with one or two complex vector operands,
of the same or different types, and with different choices for what type
the other operand might be when one has complex vector type, and make sure
they are all properly tested and do have the desired and documented
semantics.
If the intended semantics are the same for C and C++, the tests should be
c-c++-common tests. Any cases where the intended semantics are different
will need separate tests for each language or appropriately conditional
test assertions in c-c++-common.
On Tue, Sep 12, 2023 at 7:26 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Tue, 12 Sep 2023, Sylvain Noiry via Gcc-patches wrote:
>
> > Summary:
> > Allow the creation and usage of builtins vectors of complex
> > in C, using __attribute__ ((vector_size ()))
>
> If you're adding a new language feature like this, you need to update
> extend.texi to explain the valid uses of the attribute for complex types,
> and (under "Vector Extensions") the valid uses of the resulting vectors.
> You also need to add testcases to the testsuite for such vectors - both
> execution tests covering valid uses of the vectors, and tests that invalid
> declarations or uses of such vectors (uses with any operator, or other
> operand to such operator, that aren't valid) are properly rejected - go
> through all cases of operators, with one or two complex vector operands,
> of the same or different types, and with different choices for what type
> the other operand might be when one has complex vector type, and make sure
> they are all properly tested and do have the desired and documented
> semantics.
>
> If the intended semantics are the same for C and C++, the tests should be
> c-c++-common tests. Any cases where the intended semantics are different
> will need separate tests for each language or appropriately conditional
> test assertions in c-c++-common.
And to add - in other related discussions we always rejected adding vector types
of composite types. I realize that if the hardware supports vector complex
arithmetic instructions this might be the first true good reason to allow these.
Richard.
> --
> Joseph S. Myers
> joseph@codesourcery.com
@@ -2019,6 +2019,8 @@ vector_mode_valid_p (machine_mode mode)
/* Doh! What's going on? */
if (mclass != MODE_VECTOR_INT
&& mclass != MODE_VECTOR_FLOAT
+ && mclass != MODE_VECTOR_COMPLEX_INT
+ && mclass != MODE_VECTOR_COMPLEX_FLOAT
&& mclass != MODE_VECTOR_FRACT
&& mclass != MODE_VECTOR_UFRACT
&& mclass != MODE_VECTOR_ACCUM
@@ -2125,6 +2127,8 @@ handle_mode_attribute (tree *node, tree name, tree args,
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
+ case MODE_VECTOR_COMPLEX_INT:
+ case MODE_VECTOR_COMPLEX_FLOAT:
case MODE_VECTOR_FRACT:
case MODE_VECTOR_UFRACT:
case MODE_VECTOR_ACCUM:
@@ -4361,9 +4365,13 @@ type_valid_for_vector_size (tree type, tree atname, tree args,
if ((!INTEGRAL_TYPE_P (type)
&& !SCALAR_FLOAT_TYPE_P (type)
+ && !COMPLEX_INTEGER_TYPE_P (type)
+ && !COMPLEX_FLOAT_TYPE_P (type)
&& !FIXED_POINT_TYPE_P (type))
- || (!SCALAR_FLOAT_MODE_P (orig_mode)
- && GET_MODE_CLASS (orig_mode) != MODE_INT
+ || ((!SCALAR_FLOAT_MODE_P (orig_mode)
+ && GET_MODE_CLASS (orig_mode) != MODE_INT)
+ && (!COMPLEX_FLOAT_MODE_P (orig_mode)
+ && GET_MODE_CLASS (orig_mode) != MODE_COMPLEX_INT)
&& !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
|| !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
|| TREE_CODE (type) == BOOLEAN_TYPE
@@ -2441,7 +2441,23 @@ c_common_type_for_mode (machine_mode mode, int unsignedp)
: make_signed_type (precision));
}
- if (COMPLEX_MODE_P (mode))
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
+ && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+ {
+ unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
+ GET_MODE_NUNITS (mode));
+ tree bool_type = build_nonstandard_boolean_type (elem_bits);
+ return build_vector_type_for_mode (bool_type, mode);
+ }
+ else if (VECTOR_MODE_P (mode)
+ && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+ {
+ machine_mode inner_mode = GET_MODE_INNER (mode);
+ tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+ if (inner_type != NULL_TREE)
+ return build_vector_type_for_mode (inner_type, mode);
+ }
+ else if (COMPLEX_MODE_P (mode))
{
machine_mode inner_mode;
tree inner_type;
@@ -8360,10 +8376,11 @@ vector_types_compatible_elements_p (tree t1, tree t2)
gcc_assert ((INTEGRAL_TYPE_P (t1)
|| c1 == REAL_TYPE
+ || c1 == COMPLEX_TYPE
|| c1 == FIXED_POINT_TYPE)
&& (INTEGRAL_TYPE_P (t2)
|| c2 == REAL_TYPE
- || c2 == FIXED_POINT_TYPE));
+ || c2 == COMPLEX_TYPE || c2 == FIXED_POINT_TYPE));
t1 = c_common_signed_type (t1);
t2 = c_common_signed_type (t2);
@@ -4576,7 +4576,9 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
if (typecode == INTEGER_TYPE
|| typecode == BITINT_TYPE
|| (gnu_vector_type_p (TREE_TYPE (arg))
- && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))))
+ && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))
+ && !COMPLEX_INTEGER_TYPE_P (TREE_TYPE (TREE_TYPE (arg)))
+ && !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg)))))
{
tree e = arg;
@@ -4599,7 +4601,9 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
if (!noconvert)
arg = default_conversion (arg);
}
- else if (typecode == COMPLEX_TYPE)
+ else if (typecode == COMPLEX_TYPE
+ || COMPLEX_INTEGER_TYPE_P (TREE_TYPE (TREE_TYPE (arg)))
+ || COMPLEX_FLOAT_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
{
code = CONJ_EXPR;
pedwarn (location, OPT_Wpedantic,
@@ -11365,6 +11365,7 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
to __complex__ ( x, y ). This is not the same for SNaNs or
if signed zeros are involved. */
if (!HONOR_SNANS (arg0)
+ && !(VECTOR_TYPE_P (TREE_TYPE (arg0)))
&& !HONOR_SIGNED_ZEROS (arg0)
&& COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
{