diff options
author | Richard Biener <rguenther@suse.de> | 2021-05-21 11:33:30 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2021-05-31 08:46:04 +0200 |
commit | ef8176e0fac935c095cc39f4ecdfd43cdb8cb3f3 (patch) | |
tree | 89fad1f0a7e3560dc2a1682f62cd2beffe3b9e5d /gcc/cp | |
parent | df4e0359dad239854af0ea9eacb8e7e3719557d0 (diff) | |
download | gcc-ef8176e0fac935c095cc39f4ecdfd43cdb8cb3f3.zip gcc-ef8176e0fac935c095cc39f4ecdfd43cdb8cb3f3.tar.gz gcc-ef8176e0fac935c095cc39f4ecdfd43cdb8cb3f3.tar.bz2 |
c++/88601 - [C/C++] __builtin_shufflevector support
This adds support for the clang __builtin_shufflevector extension to
the C and C++ frontends. The builtin is lowered to VEC_PERM_EXPR.
Because VEC_PERM_EXPR does not support different sized vector inputs
or result or the special permute index of -1 (don't-care)
c_build_shufflevector applies lowering by widening inputs and output
to the widest vector, replacing -1 by a defined index and
subsetting the final vector if we produced a wider result than
desired.
Code generation thus can be sub-optimal, followup patches will
aim to fix that by recovering from part of the missing features
during RTL expansion and by relaxing the constraints of the GIMPLE
IL with regard to VEC_PERM_EXPR.
2021-05-21 Richard Biener <rguenther@suse.de>
PR c++/88601
gcc/c-family/
* c-common.c: Include tree-vector-builder.h and
vec-perm-indices.h.
(c_common_reswords): Add __builtin_shufflevector.
(c_build_shufflevector): New funtion.
* c-common.h (enum rid): Add RID_BUILTIN_SHUFFLEVECTOR.
(c_build_shufflevector): Declare.
gcc/c/
* c-decl.c (names_builtin_p): Handle RID_BUILTIN_SHUFFLEVECTOR.
* c-parser.c (c_parser_postfix_expression): Likewise.
gcc/cp/
* cp-objcp-common.c (names_builtin_p): Handle
RID_BUILTIN_SHUFFLEVECTOR.
* cp-tree.h (build_x_shufflevector): Declare.
* parser.c (cp_parser_postfix_expression): Handle
RID_BUILTIN_SHUFFLEVECTOR.
* pt.c (tsubst_copy_and_build): Handle IFN_SHUFFLEVECTOR.
* typeck.c (build_x_shufflevector): Build either a lowered
VEC_PERM_EXPR or an unlowered shufflevector via a temporary
internal function IFN_SHUFFLEVECTOR.
gcc/
* internal-fn.c (expand_SHUFFLEVECTOR): Define.
* internal-fn.def (SHUFFLEVECTOR): New.
* internal-fn.h (expand_SHUFFLEVECTOR): Declare.
* doc/extend.texi: Document __builtin_shufflevector.
gcc/testsuite/
* c-c++-common/builtin-shufflevector-2.c: New testcase.
* c-c++-common/torture/builtin-shufflevector-1.c: Likewise.
* g++.dg/ext/builtin-shufflevector-1.C: Likewise.
* g++.dg/ext/builtin-shufflevector-2.C: Likewise.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/cp-objcp-common.c | 1 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/parser.c | 15 | ||||
-rw-r--r-- | gcc/cp/pt.c | 9 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 36 |
5 files changed, 64 insertions, 0 deletions
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index 9847270..46b2248 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -390,6 +390,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_CONVERTVECTOR: case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: + case RID_BUILTIN_SHUFFLEVECTOR: case RID_BUILTIN_LAUNDER: case RID_BUILTIN_BIT_CAST: case RID_OFFSETOF: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index aa20271..c95a820 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7895,6 +7895,9 @@ extern tree cp_build_binary_op (const op_location_t &, extern tree build_x_vec_perm_expr (location_t, tree, tree, tree, tsubst_flags_t); +extern tree build_x_shufflevector (location_t, + vec<tree, va_gc> *, + tsubst_flags_t); #define cxx_sizeof(T) cxx_sizeof_or_alignof_type (input_location, T, SIZEOF_EXPR, false, true) extern tree build_simple_component_ref (tree, tree); extern tree build_ptrmemfunc_access_expr (tree, tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 84c6be8..4a46828 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7295,6 +7295,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, case RID_ADDRESSOF: case RID_BUILTIN_SHUFFLE: + case RID_BUILTIN_SHUFFLEVECTOR: case RID_BUILTIN_LAUNDER: { vec<tree, va_gc> *vec; @@ -7357,6 +7358,20 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } break; + case RID_BUILTIN_SHUFFLEVECTOR: + if (vec->length () < 3) + { + error_at (loc, "wrong number of arguments to " + "%<__builtin_shufflevector%>"); + postfix_expression = error_mark_node; + } + else + { + postfix_expression + = build_x_shufflevector (loc, vec, tf_warning_or_error); + } + break; + default: gcc_unreachable (); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b476ca8..3130280 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -20397,6 +20397,15 @@ tsubst_copy_and_build (tree t, RETURN (ret); break; + case IFN_SHUFFLEVECTOR: + { + ret = build_x_shufflevector (input_location, call_args, + complain); + if (ret != error_mark_node) + RETURN (ret); + break; + } + default: /* Unsupported internal function with arguments. */ gcc_unreachable (); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3df4117..dbb2370 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5989,6 +5989,42 @@ build_x_vec_perm_expr (location_t loc, orig_arg1, orig_arg2); return exp; } + +/* Build a VEC_PERM_EXPR. + This is a simple wrapper for c_build_shufflevector. */ +tree +build_x_shufflevector (location_t loc, vec<tree, va_gc> *args, + tsubst_flags_t complain) +{ + tree arg0 = (*args)[0]; + tree arg1 = (*args)[1]; + if (processing_template_decl) + { + for (unsigned i = 0; i < args->length (); ++i) + if (type_dependent_expression_p ((*args)[i])) + { + tree exp = build_min_nt_call_vec (NULL, args); + CALL_EXPR_IFN (exp) = IFN_SHUFFLEVECTOR; + return exp; + } + arg0 = build_non_dependent_expr (arg0); + arg1 = build_non_dependent_expr (arg1); + /* ??? Nothing needed for the index arguments? */ + } + auto_vec<tree, 16> mask; + for (unsigned i = 2; i < args->length (); ++i) + { + tree idx = maybe_constant_value ((*args)[i]); + mask.safe_push (idx); + } + tree exp = c_build_shufflevector (loc, arg0, arg1, mask, complain & tf_error); + if (processing_template_decl && exp != error_mark_node) + { + exp = build_min_non_dep_call_vec (exp, NULL, args); + CALL_EXPR_IFN (exp) = IFN_SHUFFLEVECTOR; + } + return exp; +} /* Return a tree for the sum or difference (RESULTCODE says which) of pointer PTROP and integer INTOP. */ |