[v3] c-family: Add __builtin_assoc_barrier

Message ID 2187370.SNQ7YSdzHs@excalibur
State Committed
Commit efb7c51024ccad9df293e6caf134d78b3d00cf89
Headers
Series [v3] c-family: Add __builtin_assoc_barrier |

Commit Message

Matthias Kretz Nov. 11, 2021, 8:49 a.m. UTC
  On Wednesday, 8 September 2021 15:49:27 CET Matthias Kretz wrote:
> On Wednesday, 8 September 2021 15:44:28 CEST Jason Merrill wrote:
> > On 9/8/21 5:37 AM, Matthias Kretz wrote:
> > > 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?
> > 
> > I agree about constexpr, but why wouldn't template instantiations be
> > affected by -fassociative-math like any other function?
> 
> Oh, that seems like a major misunderstanding on my part. I assumed
> tsubst_copy_and_build would evaluate the expressions in template arguments
> ?. I'll expand the test and will fix.

Sorry for the long delay. New patch is attached. OK for trunk?


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:

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

Comments

Jason Merrill Nov. 17, 2021, 6:35 p.m. UTC | #1
On 11/11/21 03:49, Matthias Kretz wrote:
> On Wednesday, 8 September 2021 15:49:27 CET Matthias Kretz wrote:
>> On Wednesday, 8 September 2021 15:44:28 CEST Jason Merrill wrote:
>>> On 9/8/21 5:37 AM, Matthias Kretz wrote:
>>>> 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?
>>>
>>> I agree about constexpr, but why wouldn't template instantiations be
>>> affected by -fassociative-math like any other function?
>>
>> Oh, that seems like a major misunderstanding on my part. I assumed
>> tsubst_copy_and_build would evaluate the expressions in template arguments
>> ?. I'll expand the test and will fix.
> 
> Sorry for the long delay. New patch is attached. OK for trunk?

OK.

> 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:
> 
>          * 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.
> ---
>   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(-)
>   create mode 100644 gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c
> 
>
  

Patch

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 436df45df68..dd2a3d5da9e 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 186fa1692c1..f7407a31d9b 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -10619,6 +10619,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 80dd61d599e..3770b09998d 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 453007c686b..0548570afe3 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6837,6 +6837,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 f387b5036d2..5adcd661406 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)
@@ -4040,12 +4041,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 32de97b08bd..12c598798db 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<tree, va_gc> *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 b2916f8aa4b..be79f70f30c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21003,7 +21003,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 2443d032749..402f5a5556a 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 <int x>
+  constexpr int
+  f()
+  {
+    return x;
+  }
+#endif
+
+template <class T>
+  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<int(pm(1.f, 1.e20f))>();
+  if (x != normal())
+    __builtin_abort();
+  if (y != 0)
+    __builtin_abort();
+#endif
+}
+#else
+void test1() {}
+#endif
+
+int main()
+{
+  test0();
+  test1();
+  return 0;
+}