On Wednesday, 14 July 2021 10:14:55 CEST Richard Biener wrote: > > > There's one "related" IL feature used by the Fortran frontend - > > > PAREN_EXPR > > > prevents association across it. So for Fortran (when not > > > -fno-protect-parens which is enabled by -Ofast), (a + b) - b cannot be > > > optimized to a. Eventually this could be used to wrap intrinsic results > > > since most of the issues in the end require association. Note > > > PAREN_EXPR > > > isn't exposed to the C family frontends but we could of course add a > > > builtin-like thing for this _Noassoc ( .... ) or so. Note PAREN_EXPR > > > survives -Ofast so it's the frontends that would need to choose to emit > > > or > > > not emit it (or always emit it). > > > > Interesting. I want that builtin in C++. Currently I use inline asm to > > achieve a similar effect. But the inline asm hammer is really too big for > > the problem. > > I think implementing it similar to how we do __builtin_shufflevector would > be easily possible. PAREN_EXPR is a tree code.
Like this? If you like it, I'll write the missing documentation and do real regression testing. --- New builtin to enable explicit use of PAREN_EXPR in C & C++ code. Signed-off-by: Matthias Kretz <m.kr...@gsi.de> gcc/testsuite/ChangeLog: * c-c++-common/builtin-noassoc-1.c: New test. gcc/cp/ChangeLog: * cp-objcp-common.c (names_builtin_p): Handle RID_BUILTIN_NOASSOC. * parser.c (cp_parser_postfix_expression): Handle RID_BUILTIN_NOASSOC. gcc/c-family/ChangeLog: * c-common.c (c_common_reswords): Add __builtin_noassoc. * c-common.h (enum rid): Add RID_BUILTIN_NOASSOC. gcc/c/ChangeLog: * c-decl.c (names_builtin_p): Handle RID_BUILTIN_NOASSOC. * c-parser.c (c_parser_postfix_expression): Likewise. --- 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/cp-objcp-common.c | 1 + gcc/cp/parser.c | 14 +++++++++++ .../c-c++-common/builtin-noassoc-1.c | 24 +++++++++++++++++++ 7 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/c-c++-common/builtin-noassoc-1.c -- ────────────────────────────────────────────────────────────────────────── Dr. Matthias Kretz https://mattkretz.github.io GSI Helmholtz Centre for Heavy Ion Research https://gsi.de std::experimental::simd https://github.com/VcDevel/std-simd ──────────────────────────────────────────────────────────────────────────
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 681fcc972f4..e74123d896c 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_noassoc", RID_BUILTIN_NOASSOC, 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 50ca8fb6ebd..b772cf9c5e9 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_NOASSOC, 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 983d65e930c..7b7ecba026f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -10557,6 +10557,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: + case RID_BUILTIN_NOASSOC: 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 9a56e0c04c6..2b40dc8253e 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -8931,6 +8931,7 @@ c_parser_predefined_identifier (c_parser *parser) assignment-expression , assignment-expression, ) __builtin_convertvector ( assignment-expression , type-name ) + __builtin_noassoc ( assignment-expression ) offsetof-member-designator: identifier @@ -10076,6 +10077,25 @@ c_parser_postfix_expression (c_parser *parser) } } break; + case RID_BUILTIN_NOASSOC: + { + 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/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index ee255732d5a..2492094508b 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -395,6 +395,7 @@ names_builtin_p (const char *name) case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: case RID_BUILTIN_LAUNDER: + case RID_BUILTIN_NOASSOC: case RID_BUILTIN_BIT_CAST: case RID_OFFSETOF: case RID_HAS_NOTHROW_ASSIGN: diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 62f3465539b..49f2dcc0bfd 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7316,6 +7316,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_NOASSOC: { vec<tree, va_gc> *vec; @@ -7358,6 +7359,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } break; + case RID_BUILTIN_NOASSOC: + 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_noassoc%>"); + postfix_expression = error_mark_node; + } + break; + case RID_BUILTIN_SHUFFLE: if (vec->length () == 2) postfix_expression diff --git a/gcc/testsuite/c-c++-common/builtin-noassoc-1.c b/gcc/testsuite/c-c++-common/builtin-noassoc-1.c new file mode 100644 index 00000000000..ff55c666264 --- /dev/null +++ b/gcc/testsuite/c-c++-common/builtin-noassoc-1.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ + +float a = 1.f; +float b = 1.e20f; + +__attribute__((optimize("-ffast-math"))) +float +fast() +{ + return __builtin_noassoc (a + b) - b; +} + +float +normal() +{ + return a + b - b; +} + +int main() +{ + if (fast() != normal()) + __builtin_abort(); + return 0; +}