diff mbox series

Add constructor parsing to the GIMPLE FE

Message ID alpine.LSU.2.20.1811301139520.1827@zhemvz.fhfr.qr
State New
Headers show
Series Add constructor parsing to the GIMPLE FE | expand

Commit Message

Richard Biener Nov. 30, 2018, 10:44 a.m. UTC
I failed to come up with ways using generic vector code to create
specific GIMPLE the vectorizer creates so the following fills
in the missing parsing of constructors in the GIMPLE FE.  Notably
aggregate assignments from empty constructors was also missing.
(the special case of clobbers still is)

In particular I was searching for the best way to represent

  movq mem, %xmm0

on GIMPLE.  Aka an 8 byte load into a vector register
implicitely zero-extending.  I settled with

 _2 = { v8qi, { 0,.... } };

but the explicit zero doesn't get optimized.  Expect a PR
for that now with a GIMPLE testcase ;)

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

Richard.

2018-11-30  Richard Biener  <rguenther@suse.de>

	c/
	* gimple-parser.c (c_parser_gimple_postfix_expression): Parse
	_Literal (type) { ... } as empty aggregate or vector constructor.

	* gcc.dg/gimplefe-34.c: New testcase.
	* gcc.dg/gimplefe-35.c: Likewise.
diff mbox series

Patch

Index: gcc/c/gimple-parser.c
===================================================================
--- gcc/c/gimple-parser.c	(revision 266657)
+++ gcc/c/gimple-parser.c	(working copy)
@@ -806,6 +806,7 @@  c_parser_gimple_call_internal (c_parser
      identifier
      constant
      string-literal
+     constructor
      gimple-call-internal
 
 */
@@ -934,7 +935,7 @@  c_parser_gimple_postfix_expression (c_pa
 	    }
 	  else if (strcmp (IDENTIFIER_POINTER (id), "_Literal") == 0)
 	    {
-	      /* _Literal '(' type-name ')' [ '-' ] constant */
+	      /* _Literal '(' type-name ')' ( [ '-' ] constant | constructor ) */
 	      c_parser_consume_token (parser);
 	      tree type = NULL_TREE;
 	      if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -946,28 +947,90 @@  c_parser_gimple_postfix_expression (c_pa
 		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 					     "expected %<)%>");
 		}
-	      bool neg_p;
-	      if ((neg_p = c_parser_next_token_is (parser, CPP_MINUS)))
-		c_parser_consume_token (parser);
-	      tree val = c_parser_gimple_postfix_expression (parser).value;
-	      if (! type
-		  || ! val
-		  || val == error_mark_node
-		  || ! CONSTANT_CLASS_P (val))
+	      if (! type)
 		{
 		  c_parser_error (parser, "invalid _Literal");
 		  return expr;
 		}
-	      if (neg_p)
+	      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 		{
-		  val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val);
-		  if (! val)
+		  c_parser_consume_token (parser);
+		  if (!AGGREGATE_TYPE_P (type)
+		      && !VECTOR_TYPE_P (type))
+		    {
+		      c_parser_error (parser, "invalid type for _Literal with "
+				      "constructor");
+		      c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+						 "expected %<}%>");
+		      return expr;
+		    }
+		  vec<constructor_elt, va_gc> *v = NULL;
+		  bool constant_p = true;
+		  if (VECTOR_TYPE_P (type)
+		      && !c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+		    {
+		      vec_alloc (v, TYPE_VECTOR_SUBPARTS (type).to_constant ());
+		      do
+			{
+			  tree val
+			    = c_parser_gimple_postfix_expression (parser).value;
+			  if (! val
+			      || val == error_mark_node
+			      || (! CONSTANT_CLASS_P (val)
+				  && ! SSA_VAR_P (val)))
+			    {
+			      c_parser_error (parser, "invalid _Literal");
+			      return expr;
+			    }
+			  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, val);
+			  if (! CONSTANT_CLASS_P (val))
+			    constant_p = false;
+			  if (c_parser_next_token_is (parser, CPP_COMMA))
+			    c_parser_consume_token (parser);
+			  else
+			    break;
+			}
+		      while (1);
+		    }
+		  if (c_parser_require (parser, CPP_CLOSE_BRACE,
+					"expected %<}%>"))
+		    {
+		      if (v && constant_p)
+			expr.value = build_vector_from_ctor (type, v);
+		      else
+			expr.value = build_constructor (type, v);
+		    }
+		  else
+		    {
+		      c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+						 "expected %<}%>");
+		      return expr;
+		    }
+		}
+	      else
+		{
+		  bool neg_p;
+		  if ((neg_p = c_parser_next_token_is (parser, CPP_MINUS)))
+		    c_parser_consume_token (parser);
+		  tree val = c_parser_gimple_postfix_expression (parser).value;
+		  if (! val
+		      || val == error_mark_node
+		      || ! CONSTANT_CLASS_P (val))
 		    {
 		      c_parser_error (parser, "invalid _Literal");
 		      return expr;
 		    }
+		  if (neg_p)
+		    {
+		      val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val);
+		      if (! val)
+			{
+			  c_parser_error (parser, "invalid _Literal");
+			  return expr;
+			}
+		    }
+		  expr.value = fold_convert (type, val);
 		}
-	      expr.value = fold_convert (type, val);
 	      return expr;
 	    }
 
Index: gcc/testsuite/gcc.dg/gimplefe-34.c
===================================================================
--- gcc/testsuite/gcc.dg/gimplefe-34.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/gimplefe-34.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+typedef unsigned char v16qi __attribute__((vector_size(16)));
+typedef unsigned char v8qi __attribute__((vector_size(8)));
+
+v16qi x;
+
+void __GIMPLE foo (unsigned char *p)
+{
+  v8qi _2;
+  v16qi _3;
+
+bb_2:
+  _2 = __MEM <v8qi, 8> (p_1(D));
+  _3 = _Literal (v16qi) { _2, _Literal (v8qi) { _Literal (unsigned char) 0, _Literal (unsigned char) 0, _Literal (unsigned char) 0, _Literal (unsigned char) 0, _Literal (unsigned char) 0, _Literal (unsigned char) 0, _Literal (unsigned char) 0 } };
+  x = _3;
+  return;
+}
+
Index: gcc/testsuite/gcc.dg/gimplefe-35.c
===================================================================
--- gcc/testsuite/gcc.dg/gimplefe-35.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/gimplefe-35.c	(working copy)
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+struct X { int i; } x;
+void __GIMPLE foo (void)
+{
+bb_2:
+  x = _Literal (struct X) {};
+  return;
+}
+