c-family: Add __builtin_assoc_barrier

Message ID 2312888.R4OtGj9PrH@excalibur
State New
Headers show
Series
  • c-family: Add __builtin_assoc_barrier
Related show

Commit Message

Matthias Kretz July 19, 2021, 7:33 a.m.
tested on x86_64-pc-linux-gnu with no new failures. OK for master?

New builtin to enable explicit use of PAREN_EXPR in C & C++ code.

Signed-off-by: Matthias Kretz <m.kretz@gsi.de>

gcc/testsuite/ChangeLog:

	* c-c++-common/builtin-assoc-barrier-1.c: New test.

gcc/cp/ChangeLog:

	* cp-objcp-common.c (names_builtin_p): Handle
	RID_BUILTIN_ASSOC_BARRIER.
	* parser.c (cp_parser_postfix_expression): Handle
	RID_BUILTIN_ASSOC_BARRIER.

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.
---
 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 +++++++++++
 gcc/doc/extend.texi                           | 18 ++++++++++++++
 .../c-c++-common/builtin-assoc-barrier-1.c    | 24 +++++++++++++++++++
 8 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/c-c++-common/builtin-assoc-barrier-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
──────────────────────────────────────────────────────────────────────────

Comments

Richard Biener July 19, 2021, 12:34 p.m. | #1
On Mon, 19 Jul 2021, Matthias Kretz wrote:

> tested on x86_64-pc-linux-gnu with no new failures. OK for master?


I think now that PAREN_EXPR can appear in C++ code you need to
adjust some machiner to expect it (constexpr folding?  template stuff?).
I suggest to add some testcases covering templates and constexpr
functions.

+@deftypefn {Built-in Function} @var{type} __builtin_assoc_barrier
(@var{type} @var{expr})
+This built-in represents a re-association barrier for the floating-point
+expression @var{expr} with operations following the built-in. The
expression
+@var{expr} itself can be reordered, and the whole expression @var{expr} 
can
be
+reordered with operations after the barrier.

What operations follow the built-in also applies to operations leading
the builtin?  Maybe "This built-in represents a re-association barrier
for the floating-point expression @var{expr} with the expression
consuming its value."  But I'm not an english speaker - I guess
I'm mostly confused about "follow" here.

I'm not sure if there are better C/C++ language terms describing what
the builtin does, but basically it appears as opaque operand to the
surrounding expression and the surrounding expression is opaque
to the expression inside the parens.

 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
+

Otherwise the patch looks OK, but of course C/C++ frontend maintainers
would want to chime in here (I've CCed two).

Richard.


> New builtin to enable explicit use of PAREN_EXPR in C & C++ code.

> 

> Signed-off-by: Matthias Kretz <m.kretz@gsi.de>

> 

> gcc/testsuite/ChangeLog:

> 

> 	* c-c++-common/builtin-assoc-barrier-1.c: New test.

> 

> gcc/cp/ChangeLog:

> 

> 	* cp-objcp-common.c (names_builtin_p): Handle

> 	RID_BUILTIN_ASSOC_BARRIER.

> 	* parser.c (cp_parser_postfix_expression): Handle

> 	RID_BUILTIN_ASSOC_BARRIER.

> 

> 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.

> ---

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

>  gcc/doc/extend.texi                           | 18 ++++++++++++++

>  .../c-c++-common/builtin-assoc-barrier-1.c    | 24 +++++++++++++++++++

>  8 files changed, 80 insertions(+), 1 deletion(-)

>  create mode 100644 gcc/testsuite/c-c++-common/builtin-assoc-barrier-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

> ──────────────────────────────────────────────────────────────────────────


-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)
David Malcolm via Gcc-patches July 20, 2021, 8:22 p.m. | #2
On 7/19/21 8:34 AM, Richard Biener wrote:
> On Mon, 19 Jul 2021, Matthias Kretz wrote:

> 

>> tested on x86_64-pc-linux-gnu with no new failures. OK for master?

> 

> I think now that PAREN_EXPR can appear in C++ code you need to

> adjust some machiner to expect it (constexpr folding?  template stuff?).

> I suggest to add some testcases covering templates and constexpr

> functions.


Yes.

The C++ front end already uses PAREN_EXPR in templates to indicate 
parenthesized initializers in cases where that matters for 
decltype(auto).  It should be fine to use it for both that and 
__builtin_assoc_barrier, but you probably want to distinguish them with 
a TREE_LANG_FLAG, and change tsubst_copy_and_build to keep the 
PAREN_EXPR in this case.

For constexpr you probably just need to add handling to 
cxx_eval_constant_expression to evaluate its operand instead.

> +@deftypefn {Built-in Function} @var{type} __builtin_assoc_barrier

> (@var{type} @var{expr})

> +This built-in represents a re-association barrier for the floating-point

> +expression @var{expr} with operations following the built-in. The

> expression

> +@var{expr} itself can be reordered, and the whole expression @var{expr}

> can

> be

> +reordered with operations after the barrier.

> 

> What operations follow the built-in also applies to operations leading

> the builtin?  Maybe "This built-in represents a re-association barrier

> for the floating-point expression @var{expr} with the expression

> consuming its value."  But I'm not an english speaker - I guess

> I'm mostly confused about "follow" here.

> 

> I'm not sure if there are better C/C++ language terms describing what

> the builtin does, but basically it appears as opaque operand to the

> surrounding expression and the surrounding expression is opaque

> to the expression inside the parens.

> 

>   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

> +

> 

> Otherwise the patch looks OK, but of course C/C++ frontend maintainers

> would want to chime in here (I've CCed two).

> 

> Richard.

> 

> 

>> New builtin to enable explicit use of PAREN_EXPR in C & C++ code.

>>

>> Signed-off-by: Matthias Kretz <m.kretz@gsi.de>

>>

>> gcc/testsuite/ChangeLog:

>>

>> 	* c-c++-common/builtin-assoc-barrier-1.c: New test.

>>

>> gcc/cp/ChangeLog:

>>

>> 	* cp-objcp-common.c (names_builtin_p): Handle

>> 	RID_BUILTIN_ASSOC_BARRIER.

>> 	* parser.c (cp_parser_postfix_expression): Handle

>> 	RID_BUILTIN_ASSOC_BARRIER.

>>

>> 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.

>> ---

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

>>   gcc/doc/extend.texi                           | 18 ++++++++++++++

>>   .../c-c++-common/builtin-assoc-barrier-1.c    | 24 +++++++++++++++++++

>>   8 files changed, 80 insertions(+), 1 deletion(-)

>>   create mode 100644 gcc/testsuite/c-c++-common/builtin-assoc-barrier-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

>> ──────────────────────────────────────────────────────────────────────────

>

Patch

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 681fcc972f4..c62a6398a47 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 50ca8fb6ebd..f34dc47c2ba 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 983d65e930c..dcf4a2d7c32 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_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 9a56e0c04c6..fffd81f4e5b 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_assoc_barrier ( assignment-expression )
 
    offsetof-member-designator:
      identifier
@@ -10076,6 +10077,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/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index ee255732d5a..04522a23eda 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_ASSOC_BARRIER:
     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..4ee7899ce66 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_ASSOC_BARRIER:
       {
 	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_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/doc/extend.texi b/gcc/doc/extend.texi
index 96640ba156f..cb08f830940 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13951,6 +13951,24 @@  int g (int c)
 
 @end deftypefn
 
+@deftypefn {Built-in Function} @var{type} __builtin_assoc_barrier (@var{type} @var{expr})
+This built-in represents a re-association barrier for the floating-point
+expression @var{expr} with operations following the built-in. The expression
+@var{expr} itself can be reordered, and the whole expression @var{expr} can be
+reordered with operations 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..51efb1ab96c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-assoc-barrier-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_assoc_barrier (a + b) - b;
+}
+
+float
+normal()
+{
+  return a + b - b;
+}
+
+int main()
+{
+  if (fast() != normal())
+    __builtin_abort();
+  return 0;
+}