This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[trans-mem] implement transaction expressions for C


Howdy.

The patch below implements transaction expressions as per the language
specs.  For example:

	x = __transaction (york);

On x86-64, we'd generate something like this.

        call    _ITM_beginTransaction
        movl    $york, %edi
        call    _ITM_RU4
        movl    %eax, %ebx
        call    _ITM_commitTransaction
        movl    %ebx, x(%rip)

The read of [york] is evaluated inside a transaction, and when we're
sure we've read, then we copy the value into [x].

I would've liked to reimplement c_parser_transaction() to handle
statements and expressions, but we have to parse through the TM
attributes before we know it's either an expression or a statement.  All
in all, it seemed like it was cleaner to duplicate some of the existing
code for transaction statements.

Tested on x86-64 Linux.  OK for branch?

p.s. I'll work on the C++ parser next.

	* tree.h: Add documentation for TRANSACTION_EXPR_OUTER AND
	TRANSACTION_EXPR_RELAXED.
	* gimplify.c (voidify_wrapper_expr): Handle TRANSACTION_EXPR.
	(gimplify_transaction): Call and handle voidify_wrapper_expr.
	* tree.def (TRANSACTION_EXPR): Change into an expression.
	* c-parser.c (c_parser_unary_expression): Handle RID_TRANSACTION.
	(c_parser_transaction_expression): New.

Index: tree.h
===================================================================
--- tree.h	(revision 159008)
+++ tree.h	(working copy)
@@ -458,6 +458,9 @@ struct GTY(()) tree_common {
        CALL_CANNOT_INLINE_P in
            CALL_EXPR
 
+       TRANSACTION_EXPR_OUTER in
+           TRANSACTION_EXPR
+
    public_flag:
 
        TREE_OVERFLOW in
@@ -485,6 +488,9 @@ struct GTY(()) tree_common {
        OMP_CLAUSE_PRIVATE_DEBUG in
            OMP_CLAUSE_PRIVATE
 
+       TRANSACTION_EXPR_RELAXED in
+           TRANSACTION_EXPR
+
    private_flag:
 
        TREE_PRIVATE in
Index: testsuite/c-c++-common/tm/trxn-expr.c
===================================================================
--- testsuite/c-c++-common/tm/trxn-expr.c	(revision 0)
+++ testsuite/c-c++-common/tm/trxn-expr.c	(revision 0)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */
+
+int y, x, york;
+
+void foobar(void)
+{
+  x = y + __transaction (york);
+}
+
+/* { dg-final { scan-tree-dump-times "_ITM_RU.*york" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "_ITM_RU" 1 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 158830)
+++ gimplify.c	(working copy)
@@ -1024,6 +1024,12 @@ voidify_wrapper_expr (tree wrapper, tree
 		}
 	      break;
 
+	    case TRANSACTION_EXPR:
+	      TREE_SIDE_EFFECTS (*p) = 1;
+	      TREE_TYPE (*p) = void_type_node;
+	      p = &TRANSACTION_EXPR_BODY (*p);
+	      break;
+
 	    default:
 	      goto out;
 	    }
@@ -6373,19 +6379,20 @@ gimplify_omp_atomic (tree *expr_p, gimpl
    return GS_ALL_DONE;
 }
 
-/* Gimplify the contents of a TRANSACTION_EXPR statement.  This involves
-   gimplification of the body, and adding some EH bits.  */
+/* Gimplify a TRANSACTION_EXPR.  This involves gimplification of the
+   body, and adding some EH bits.  */
 
 static enum gimplify_status
 gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
 {
-  tree expr = *expr_p;
+  tree expr = *expr_p, temp;
   gimple g;
   gimple_seq body = NULL;
   struct gimplify_ctx gctx;
   int subcode = 0;
 
   push_gimplify_context (&gctx);
+  temp = voidify_wrapper_expr (*expr_p, NULL);
 
   g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
   if (g && gimple_code (g) == GIMPLE_BIND)
@@ -6401,8 +6408,14 @@ gimplify_transaction (tree *expr_p, gimp
   gimple_transaction_set_subcode (g, subcode);
 
   gimplify_seq_add_stmt (pre_p, g);
-  *expr_p = NULL_TREE;
 
+  if (temp)
+    {
+      *expr_p = temp;
+      return GS_OK;
+    }
+
+  *expr_p = NULL_TREE;
   return GS_ALL_DONE;
 }
 
Index: tree.def
===================================================================
--- tree.def	(revision 158824)
+++ tree.def	(working copy)
@@ -1047,8 +1047,8 @@ DEFTREECODE (OMP_ATOMIC, "omp_atomic", t
 DEFTREECODE (OMP_CLAUSE, "omp_clause", tcc_exceptional, 0)
 
 /* TRANSACTION_EXPR tree code.
-   Operand 0: BODY: contains body of the transaction.*/
-DEFTREECODE (TRANSACTION_EXPR, "transaction_expr", tcc_statement, 1)
+   Operand 0: BODY: contains body of the transaction.  */
+DEFTREECODE (TRANSACTION_EXPR, "transaction_expr", tcc_expression, 1)
 
 /* Reduction operations.
    Operations that take a vector of elements and "reduce" it to a scalar
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 158824)
+++ c-parser.c	(working copy)
@@ -941,6 +941,7 @@ static struct c_expr c_parser_postfix_ex
 								location_t loc,
 								struct c_expr);
 static tree c_parser_transaction (c_parser *);
+static struct c_expr c_parser_transaction_expression (c_parser *);
 static tree c_parser_transaction_cancel (c_parser *);
 static struct c_expr c_parser_expression (c_parser *);
 static struct c_expr c_parser_expression_conv (c_parser *);
@@ -5106,6 +5107,11 @@ c_parser_cast_expression (c_parser *pars
    unary-operator: one of
      __extension__ __real__ __imag__
 
+   Transactional Memory:
+
+   unary-expression:
+     transaction-expression
+
    In addition, the GNU syntax treats ++ and -- as unary operators, so
    they may be applied to cast expressions with errors for non-lvalues
    given later.  */
@@ -5213,6 +5219,8 @@ c_parser_unary_expression (c_parser *par
 	  op = c_parser_cast_expression (parser, NULL);
 	  op = default_function_array_conversion (exp_loc, op);
 	  return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
+	case RID_TRANSACTION:
+	  return c_parser_transaction_expression (parser);
 	default:
 	  return c_parser_postfix_expression (parser);
 	}
@@ -8821,6 +8829,62 @@ c_parser_transaction (c_parser *parser)
   return stmt;
 }
 
+/* Parse a __transaction expression (GCC Extension).
+
+   transaction-expression:
+     __transaction attributes[opt] ( expression )
+
+   Note that the only valid attributes are: "atomic" and "relaxed".
+*/
+
+static struct c_expr
+c_parser_transaction_expression (c_parser *parser)
+{
+  struct c_expr ret;
+  unsigned int old_in = parser->in_transaction;
+  unsigned int this_in = 1;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree attrs;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION));
+  c_parser_consume_token (parser);
+
+  attrs = c_parser_transaction_attributes (parser);
+  if (attrs)
+    {
+      this_in |= parse_tm_stmt_attr (attrs, (TM_STMT_ATTR_ATOMIC
+					     | TM_STMT_ATTR_RELAXED));
+      /* The [[ atomic ]] attribute is the same as no attribute.  */
+      this_in &= ~TM_STMT_ATTR_ATOMIC;
+    }
+
+  parser->in_transaction = this_in;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      tree expr = c_parser_expression (parser).value;
+      ret.original_type = TREE_TYPE (expr);
+      ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
+      if (this_in & TM_STMT_ATTR_RELAXED)
+	TRANSACTION_EXPR_RELAXED (ret.value) = 1;
+      SET_EXPR_LOCATION (ret.value, loc);
+      ret.original_code = TRANSACTION_EXPR;
+    }
+  else
+    {
+      c_parser_error (parser, "expected %<(%>");
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+    }
+  parser->in_transaction = old_in;
+
+  if (!flag_tm)
+    error_at (loc, "%<__transaction%> without "
+	      "transactional memory support enabled");
+
+  return ret;
+}
+
 /* Parse a __transaction_cancel statement (GCC Extension).
 
    transaction-cancel-statement:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]