From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7857) id A30B1385841C; Thu, 18 Nov 2021 10:24:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A30B1385841C MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Matthias Kretz To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-5368] c-family: Add __builtin_assoc_barrier X-Act-Checkin: gcc X-Git-Author: Matthias Kretz X-Git-Refname: refs/heads/master X-Git-Oldrev: edd2249b17fb7150da66b03adb1a4e381926047d X-Git-Newrev: efb7c51024ccad9df293e6caf134d78b3d00cf89 Message-Id: <20211118102419.A30B1385841C@sourceware.org> Date: Thu, 18 Nov 2021 10:24:19 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Nov 2021 10:24:19 -0000 https://gcc.gnu.org/g:efb7c51024ccad9df293e6caf134d78b3d00cf89 commit r12-5368-gefb7c51024ccad9df293e6caf134d78b3d00cf89 Author: Matthias Kretz Date: Fri Jul 16 10:46:24 2021 +0200 c-family: Add __builtin_assoc_barrier New builtin to enable explicit use of PAREN_EXPR in C & C++ code. Signed-off-by: Matthias Kretz gcc/testsuite/ChangeLog: * c-c++-common/builtin-assoc-barrier-1.c: New test. gcc/cp/ChangeLog: * constexpr.c (cxx_eval_constant_expression): Handle PAREN_EXPR via cxx_eval_constant_expression. * cp-objcp-common.c (names_builtin_p): Handle RID_BUILTIN_ASSOC_BARRIER. * cp-tree.h: Adjust TREE_LANG_FLAG documentation to include PAREN_EXPR in REF_PARENTHESIZED_P. (REF_PARENTHESIZED_P): Add PAREN_EXPR. * parser.c (cp_parser_postfix_expression): Handle RID_BUILTIN_ASSOC_BARRIER. * pt.c (tsubst_copy_and_build): If the PAREN_EXPR is not a parenthesized initializer, build a new PAREN_EXPR. * semantics.c (force_paren_expr): Simplify conditionals. Set REF_PARENTHESIZED_P on PAREN_EXPR. (maybe_undo_parenthesized_ref): Test PAREN_EXPR for REF_PARENTHESIZED_P. gcc/c-family/ChangeLog: * c-common.c (c_common_reswords): Add __builtin_assoc_barrier. * c-common.h (enum rid): Add RID_BUILTIN_ASSOC_BARRIER. gcc/c/ChangeLog: * c-decl.c (names_builtin_p): Handle RID_BUILTIN_ASSOC_BARRIER. * c-parser.c (c_parser_postfix_expression): Likewise. gcc/ChangeLog: * doc/extend.texi: Document __builtin_assoc_barrier. Diff: --- gcc/c-family/c-common.c | 1 + gcc/c-family/c-common.h | 2 +- gcc/c/c-decl.c | 1 + gcc/c/c-parser.c | 20 ++++++ gcc/cp/constexpr.c | 8 +++ gcc/cp/cp-objcp-common.c | 1 + gcc/cp/cp-tree.h | 12 ++-- gcc/cp/parser.c | 14 +++++ gcc/cp/pt.c | 10 ++- gcc/cp/semantics.c | 23 +++---- gcc/doc/extend.texi | 18 ++++++ .../c-c++-common/builtin-assoc-barrier-1.c | 71 ++++++++++++++++++++++ 12 files changed, 158 insertions(+), 23 deletions(-) diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index ca7d69c4f76..86c007f53de 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -384,6 +384,7 @@ const struct c_common_resword c_common_reswords[] = { "__builtin_convertvector", RID_BUILTIN_CONVERTVECTOR, 0 }, { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, + { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index d5dad99ff97..c089fda12e4 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -108,7 +108,7 @@ enum rid RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH, - RID_BUILTIN_HAS_ATTRIBUTE, + RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER, RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, /* TS 18661-3 keywords, in the same sequence as the TI_* values. */ diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 63d806a84c9..3e28a038095 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -10621,6 +10621,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: + case RID_BUILTIN_ASSOC_BARRIER: case RID_CHOOSE_EXPR: case RID_OFFSETOF: case RID_TYPES_COMPATIBLE_P: diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 40c46ec9682..81eea18dc88 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -8962,6 +8962,7 @@ c_parser_predefined_identifier (c_parser *parser) assignment-expression , assignment-expression, ) __builtin_convertvector ( assignment-expression , type-name ) + __builtin_assoc_barrier ( assignment-expression ) offsetof-member-designator: identifier @@ -10107,6 +10108,25 @@ c_parser_postfix_expression (c_parser *parser) } } break; + case RID_BUILTIN_ASSOC_BARRIER: + { + location_t start_loc = loc; + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + e1 = c_parser_expr_no_commas (parser, NULL); + mark_exp_read (e1.value); + location_t end_loc = c_parser_peek_token (parser)->get_finish (); + parens.skip_until_found_close (parser); + expr.value = build1_loc (loc, PAREN_EXPR, TREE_TYPE (e1.value), + e1.value); + set_c_expr_source_range (&expr, start_loc, end_loc); + } + break; case RID_AT_SELECTOR: { gcc_assert (c_dialect_objc ()); diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 69d9d3daeca..c8f9d5fa133 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -6901,6 +6901,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, non_constant_p, overflow_p); break; + case PAREN_EXPR: + gcc_assert (!REF_PARENTHESIZED_P (t)); + /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in + constant expressions since it's unaffected by -fassociative-math. */ + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, + non_constant_p, overflow_p); + break; + case NOP_EXPR: if (REINTERPRET_CAST_P (t)) { diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index 28f2d7bee71..38eae881f0c 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -404,6 +404,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: case RID_BUILTIN_LAUNDER: + case RID_BUILTIN_ASSOC_BARRIER: case RID_BUILTIN_BIT_CAST: case RID_OFFSETOF: case RID_HAS_NOTHROW_ASSIGN: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index acc98c9c452..3f56cb90d14 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -473,7 +473,8 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR) FNDECL_USED_AUTO (in FUNCTION_DECL) DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) - REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR) + REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF, + VIEW_CONVERT_EXPR, PAREN_EXPR) AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR) CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR) OVL_HIDDEN_P (in OVERLOAD) @@ -4041,12 +4042,13 @@ struct GTY(()) lang_decl { #define PAREN_STRING_LITERAL_P(NODE) \ TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE)) -/* Indicates whether a COMPONENT_REF or a SCOPE_REF has been parenthesized, or - an INDIRECT_REF comes from parenthesizing a _DECL. Currently only set some - of the time in C++14 mode. */ +/* Indicates whether a COMPONENT_REF or a SCOPE_REF has been parenthesized, an + INDIRECT_REF comes from parenthesizing a _DECL, or a PAREN_EXPR identifies a + parenthesized initializer relevant for decltype(auto). Currently only set + some of the time in C++14 mode. */ #define REF_PARENTHESIZED_P(NODE) \ - TREE_LANG_FLAG_2 (TREE_CHECK4 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR)) + TREE_LANG_FLAG_2 (TREE_CHECK5 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR, PAREN_EXPR)) /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a constructor call, rather than an ordinary function call. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 154b40e9aed..65f0f112011 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7354,6 +7354,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: case RID_BUILTIN_LAUNDER: + case RID_BUILTIN_ASSOC_BARRIER: { vec *vec; @@ -7396,6 +7397,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } break; + case RID_BUILTIN_ASSOC_BARRIER: + if (vec->length () == 1) + postfix_expression = build1_loc (loc, PAREN_EXPR, + TREE_TYPE ((*vec)[0]), + (*vec)[0]); + else + { + error_at (loc, "wrong number of arguments to " + "%<__builtin_assoc_barrier%>"); + postfix_expression = error_mark_node; + } + break; + case RID_BUILTIN_SHUFFLE: if (vec->length () == 2) postfix_expression diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 82bf7dc26f6..b27eea33272 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -21010,7 +21010,15 @@ tsubst_copy_and_build (tree t, integral_constant_expression_p)); case PAREN_EXPR: - RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0)))); + if (REF_PARENTHESIZED_P (t)) + RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0)))); + else + /* Recreate the PAREN_EXPR from __builtin_assoc_barrier. */ + { + tree op0 = RECUR (TREE_OPERAND (t, 0)); + RETURN (build1_loc (input_location, PAREN_EXPR, + TREE_TYPE (op0), op0)); + } case VEC_PERM_EXPR: { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 15404426bce..8f79f047c01 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2048,24 +2048,17 @@ force_paren_expr (tree expr, bool even_uneval) if (cp_unevaluated_operand && !even_uneval) return expr; - if (!DECL_P (tree_strip_any_location_wrapper (expr)) - && TREE_CODE (expr) != COMPONENT_REF - && TREE_CODE (expr) != SCOPE_REF) - return expr; - - location_t loc = cp_expr_location (expr); - if (TREE_CODE (expr) == COMPONENT_REF || TREE_CODE (expr) == SCOPE_REF) REF_PARENTHESIZED_P (expr) = true; - else if (processing_template_decl) - expr = build1_loc (loc, PAREN_EXPR, TREE_TYPE (expr), expr); - else + else if (DECL_P (tree_strip_any_location_wrapper (expr))) { - expr = build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr); + location_t loc = cp_expr_location (expr); + const tree_code code = processing_template_decl ? PAREN_EXPR + : VIEW_CONVERT_EXPR; + expr = build1_loc (loc, code, TREE_TYPE (expr), expr); REF_PARENTHESIZED_P (expr) = true; } - return expr; } @@ -2090,10 +2083,8 @@ maybe_undo_parenthesized_ref (tree t) || TREE_CODE (t) == STATIC_CAST_EXPR); t = TREE_OPERAND (t, 0); } - else if (TREE_CODE (t) == PAREN_EXPR) - t = TREE_OPERAND (t, 0); - else if (TREE_CODE (t) == VIEW_CONVERT_EXPR - && REF_PARENTHESIZED_P (t)) + else if ((TREE_CODE (t) == PAREN_EXPR || TREE_CODE (t) == VIEW_CONVERT_EXPR) + && REF_PARENTHESIZED_P (t)) t = TREE_OPERAND (t, 0); return t; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 6e6c580e329..ef654d7b878 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -14043,6 +14043,24 @@ int g (int c) @end deftypefn +@deftypefn {Built-in Function} @var{type} __builtin_assoc_barrier (@var{type} @var{expr}) +This built-in inhibits re-association of the floating-point expression +@var{expr} with expressions consuming the return value of the built-in. The +expression @var{expr} itself can be reordered, and the whole expression +@var{expr} can be reordered with operands after the barrier. The barrier is +only relevant when @code{-fassociative-math} is active, since otherwise +floating-point is not treated as associative. + +@smallexample +float x0 = a + b - b; +float x1 = __builtin_assoc_barrier(a + b) - b; +@end smallexample + +@noindent +means that, with @code{-fassociative-math}, @code{x0} can be optimized to +@code{x0 = a} but @code{x1} cannot. +@end deftypefn + @deftypefn {Built-in Function} {void *} __builtin_assume_aligned (const void *@var{exp}, size_t @var{align}, ...) This function returns its first argument, and allows the compiler to assume that the returned pointer is at least @var{align} bytes diff --git a/gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c b/gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c new file mode 100644 index 00000000000..3ff324982cf --- /dev/null +++ b/gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c @@ -0,0 +1,71 @@ +// { dg-options "-O2 -ffast-math" } +/* { dg-do run } */ + +float a = 1.f; +float b = 1.e20f; + +float +fast() +{ + return __builtin_assoc_barrier (a + b) - b; +} + +__attribute__((optimize("-fno-associative-math"))) +float +normal() +{ + return a + b - b; +} + +void test0() +{ + if (fast() != normal()) + __builtin_abort(); +} + +#ifdef __cplusplus +#ifdef __cpp_constexpr +constexpr float +pm(float x, float y) +{ + return __builtin_assoc_barrier(x + y) - y; +} + +template + constexpr int + f() + { + return x; + } +#endif + +template + T + pm(T x, T y) + { + return __builtin_assoc_barrier(x + y) - y; + } + +void test1() +{ + if (pm(a, b) != normal()) + __builtin_abort(); +#ifdef __cpp_constexpr + constexpr float x = pm(1.f, 1.e20f); + constexpr int y = f(); + if (x != normal()) + __builtin_abort(); + if (y != 0) + __builtin_abort(); +#endif +} +#else +void test1() {} +#endif + +int main() +{ + test0(); + test1(); + return 0; +}