From b7e61f3668c515f07e5989a98c45d6662767be30 Mon Sep 17 00:00:00 2001
From: Yury Gribov <tetra2005@gmail.com>
Date: Sat, 12 Nov 2016 16:22:48 +0000
Subject: [PATCH] Optionally treat assertions as optimization hints (draft
 reincarnation of ancient patch by Paolo Bonzini).

---
 gcc/Makefile.in         |  1 +
 gcc/c-family/c-common.c |  1 +
 gcc/c-family/c-common.h |  1 +
 gcc/c/c-parser.c        | 24 ++++++++++++++++++++++++
 gcc/cp/parser.c         | 23 +++++++++++++++++++++++
 gcc/ginclude/assert.h   | 12 ++++++++++++
 6 files changed, 62 insertions(+)
 create mode 100755 gcc/ginclude/assert.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 513f9c5..bfbe481 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -416,6 +416,7 @@ USER_H = $(srcdir)/ginclude/float.h \
 	 $(srcdir)/ginclude/stdnoreturn.h \
 	 $(srcdir)/ginclude/stdalign.h \
 	 $(srcdir)/ginclude/stdatomic.h \
+	 $(srcdir)/ginclude/assert.h \
 	 $(EXTRA_HEADERS)
 
 USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d2e3ad4..f7140b3 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -458,6 +458,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 },
   { "__builtin_offsetof", RID_OFFSETOF, 0 },
   { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
+  { "__builtin_has_side_effects_p", RID_HAS_SIDE_EFFECTS_P, 0 },
   { "__builtin_va_arg",	RID_VA_ARG,	0 },
   { "__complex",	RID_COMPLEX,	0 },
   { "__complex__",	RID_COMPLEX,	0 },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index dd74d0d..dfb5b37 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -101,6 +101,7 @@ enum rid
   RID_ASM,       RID_TYPEOF,   RID_ALIGNOF,  RID_ATTRIBUTE,  RID_VA_ARG,
   RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL,      RID_CHOOSE_EXPR,
   RID_TYPES_COMPATIBLE_P,      RID_BUILTIN_COMPLEX,	     RID_BUILTIN_SHUFFLE,
+  RID_HAS_SIDE_EFFECTS_P,
   RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
 
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index c9eb8dd..161702a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -7407,6 +7407,7 @@ c_parser_generic_selection (c_parser *parser)
      __builtin_shuffle ( assignment-expression , 
 			 assignment-expression ,
 			 assignment-expression, )
+    __builtin_has_side_effects_p ( assignment-expression )
 
    offsetof-member-designator:
      identifier
@@ -7990,6 +7991,29 @@ c_parser_postfix_expression (c_parser *parser)
 	    set_c_expr_source_range (&expr, loc, close_paren_loc);
 	    break;
 	  }
+	case RID_HAS_SIDE_EFFECTS_P:
+	  c_parser_consume_token (parser);
+	  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+	    {
+	      expr.set_error ();
+	      break;
+	    }
+	  {
+	    c_expr ce = c_parser_expression (parser);
+	    location_t close_paren_loc = c_parser_peek_token (parser)->location;
+	    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				       "expected %<)%>");
+	    if (ce.value == error_mark_node)
+	      {
+		expr.set_error ();
+		break;
+	      }
+
+	    expr.value
+	      = TREE_SIDE_EFFECTS(ce.value) ? integer_one_node : integer_zero_node;
+	    set_c_expr_source_range (&expr, loc, close_paren_loc);
+	  }
+	  break;
 	case RID_AT_SELECTOR:
 	  gcc_assert (c_dialect_objc ());
 	  c_parser_consume_token (parser);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index df8e743..be7c946 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4675,6 +4675,7 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
      ( compound-statement )
      __builtin_va_arg ( assignment-expression , type-id )
      __builtin_offsetof ( type-id , offsetof-expression )
+     __builtin_has_side_effects_p ( assignment-expression )
 
    C++ Extensions:
      __has_nothrow_assign ( type-id )   
@@ -5063,6 +5064,28 @@ cp_parser_primary_expression (cp_parser *parser,
 	    return build_x_va_arg (combined_loc, expression, type);
 	  }
 
+	case RID_HAS_SIDE_EFFECTS_P:
+	  {
+	    location_t start_loc
+	      = cp_lexer_peek_token (parser->lexer)->location;
+	    cp_lexer_consume_token (parser->lexer);
+	    cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+
+	    location_t expr_loc
+	      = cp_lexer_peek_token (parser->lexer)->location;
+	    tree expr = cp_parser_assignment_expression (parser);
+
+	    location_t finish_loc
+	      = cp_lexer_peek_token (parser->lexer)->location;
+	    cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+	    location_t combined_loc
+	      = make_location (expr_loc, start_loc, finish_loc);
+
+	    tree res
+	      = TREE_SIDE_EFFECTS(expr) ? integer_one_node : integer_zero_node;
+	    return cp_expr (res, combined_loc);
+	  }
+
 	case RID_OFFSETOF:
 	  return cp_parser_builtin_offsetof (parser);
 
diff --git a/gcc/ginclude/assert.h b/gcc/ginclude/assert.h
new file mode 100755
index 0000000..1c39aa9
--- /dev/null
+++ b/gcc/ginclude/assert.h
@@ -0,0 +1,12 @@
+#ifdef _GCC_ASSERT_H
+# undef _GCC_ASSERT_H
+# undef assert
+#endif
+
+#define _GCC_ASSERT_H 1
+
+#if !defined NDEBUG && defined __OPTIMIZE__ && defined __ASSUME_ASSERTS__
+# define assert(cond) ((__builtin_has_side_effects_p((cond)) || (cond)) ? (void)0 : __builtin_unreachable())
+#else
+# include_next <assert.h>
+#endif
-- 
2.7.4

