From: Matthias Kretz <m.kretz@gsi.de>
To: Richard Biener <rguenther@suse.de>, Jason Merrill <jason@redhat.com>
Cc: <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH v2] c-family: Add __builtin_assoc_barrier
Date: Wed, 8 Sep 2021 11:37:36 +0200 [thread overview]
Message-ID: <2776155.2yzvbfQdsk@excalibur> (raw)
In-Reply-To: <f8ebc816-e893-33dc-adfa-765a48755ffd@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1425 bytes --]
On Tuesday, 7 September 2021 19:36:22 CEST Jason Merrill wrote:
> > 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
> > + RETURN (RECUR (TREE_OPERAND (t, 0)));
>
> I think you need to build a new PAREN_EXPR in the assoc barrier case as
> well, for it to have any effect in templates.
My intent was to ignore __builtin_assoc_barrier in templates / constexpr
evaluation since it's not affected by -fassociative-math anyway. Or do you
mean something else?
> Please also add a comment mentioning __builtin_assoc_barrier.
I added a comment to that effect to both the cp/pt.c and cp/constexpr.c
changes.
New patch attached.
--
──────────────────────────────────────────────────────────────────────────
Dr. Matthias Kretz https://mattkretz.github.io
GSI Helmholtz Centre for Heavy Ion Research https://gsi.de
stdₓ::simd
──────────────────────────────────────────────────────────────────────────
[-- Attachment #2: 0001-c-family-Add-__builtin_assoc_barrier.patch --]
[-- Type: text/x-patch, Size: 11180 bytes --]
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/constexpr.c b/gcc/cp/constexpr.c
index 31fa5b66865..6e964837d24 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6730,6 +6730,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 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/cp-tree.h b/gcc/cp/cp-tree.h
index 792849c361c..354f9ca4f26 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -475,7 +475,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)
@@ -4026,12 +4027,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 8fcd9840ea5..ec5f42e5038 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/cp/pt.c b/gcc/cp/pt.c
index c7bf7d412ca..0e9c151aced 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -20826,7 +20826,12 @@ 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
+ /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in
+ tsubst since it's unaffected by -fassociative-math. */
+ RETURN (RECUR (TREE_OPERAND (t, 0)));
case VEC_PERM_EXPR:
{
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b97dc1f6624..837fdaa041c 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 96640ba156f..60cafe0b3e3 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 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..6fc90ccc33c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c
@@ -0,0 +1,48 @@
+// { 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;
+}
+
+#ifdef __cpp_constexpr
+constexpr float
+pm(float x, float y)
+{
+ return __builtin_assoc_barrier(x + y) - y;
+}
+
+template <int x>
+ constexpr int
+ f()
+ {
+ return x;
+ }
+#endif
+
+int main()
+{
+ if (fast() != normal())
+ __builtin_abort();
+#ifdef __cpp_constexpr
+ constexpr float x = pm(1.f, 1.e20f);
+ constexpr int y = f<int(pm(1.f, 1.e20f))>();
+ if (x != normal())
+ __builtin_abort();
+ if (y != 0)
+ __builtin_abort();
+#endif
+ return 0;
+}
next prev parent reply other threads:[~2021-09-08 9:37 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-19 7:33 [PATCH] " Matthias Kretz
2021-07-19 12:34 ` Richard Biener
2021-07-20 20:22 ` Jason Merrill
2021-09-06 12:21 ` [PATCH v2] " Matthias Kretz
2021-09-06 12:40 ` Richard Biener
2021-09-06 12:47 ` Matthias Kretz
2021-09-06 12:59 ` Richard Biener
2021-09-06 15:15 ` Matthias Kretz
2021-09-07 17:36 ` Jason Merrill
2021-09-08 9:37 ` Matthias Kretz [this message]
2021-09-08 13:44 ` Jason Merrill
2021-09-08 13:49 ` Matthias Kretz
2021-11-11 8:49 ` [PATCH v3] " Matthias Kretz
2021-11-17 18:35 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2776155.2yzvbfQdsk@excalibur \
--to=m.kretz@gsi.de \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
--cc=rguenther@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).