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;
+}

Reply via email to