On 24 August 2016 at 15:32, Richard Biener <richard.guent...@gmail.com> wrote:
> On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
> <prasad.ghan...@gmail.com> wrote:
>> On 22 August 2016 at 16:55, Trevor Saunders <tbsau...@tbsaunde.org> wrote:
>>> On Sun, Aug 21, 2016 at 10:35:17PM +0530, Prasad Ghangal wrote:
>>>> Hi all,
>>>>
>>>> As a part of my gsoc project. I have completed the following tasks:
>>>>
>>>> * Parsed gimple-expression
>>>> * Parsed gimple-labels
>>>> * Parsed local declaration
>>>> * Parsed gimple-goto statement
>>>> * Parsed gimple-if-else statement
>>>> * Parsed gimple-switch statement
>>>> * Parsed gimple-return statement
>>>> * Parsed gimple-PHI function
>>>> * Parsed gimple ssa-names along with default def
>>>> * Parsed gimple-call
>>>>
>>>> * Hacked pass manager to add support for startwith (pass-name) to skip
>>>> early opt passes
>>>> * Modified gimple dump for making it parsable
>>>>
>>>> I am willing to continue work on the project, some TODOs for the projects 
>>>> are:
>>>>
>>>> * Error handling
>>>> * Parse more gimple syntax
>>>> * Add startwith support for IPA passes
>>>>
>>>> The complete code of gimple fe project can be found at
>>>> https://github.com/PrasadG193/gcc_gimple_fe
>>>>
>>>>
>>>> PFA patch for complete project (rebased for latest trunk revision).
>>>> I have successfully bootstrapped and tested on x86_64-pc-linux-gnu.
>>>> Some testcases failed due to modified gimple dump as expected.
>>>>
>>>>
>>>> Thanks,
>>>> Prasad
>>>
>>> only some rather minor comments
>>>
>>>
>>> +++ b/gcc/c/c-parser.c
>>> @@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
>>>  #include "gimple-expr.h"
>>>  #include "context.h"
>>>  #include "gcc-rich-location.h"
>>> +#include "tree-vrp.h"
>>>
>>> given that you need these headers it might be better to put most of the
>>> gimple parsing in its own file so only what actually needs to know about
>>> this part of the compiler does now about it.
>>>
>>> +void
>>> +c_parser_parse_gimple_body (c_parser *parser)
>>> +{
>>> +  bool return_p = false;
>>> +  gimple_seq seq;
>>> +  gimple_seq body;
>>> +  tree stmt = push_stmt_list ();
>>>
>>> it would be nice to move the declarations down to their first use.
>>>
>>> +      gimple *ret;
>>> +      ret = gimple_build_return (NULL);
>>>
>>> there's no reason for a separate declaration and assignment ;)
>>>
>>> +  tree block = NULL;
>>> +  block = pop_scope ();
>>>
>>> same here, and a number of other places.
>>>
>>> +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
>>> +{
>>> +  bool return_p = false;
>>> +
>>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>>> +      return return_p;
>>>
>>> return false would work fine.
>>>
>>> +
>>> +  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
>>> +    {
>>> +      c_parser_consume_token (parser);
>>> +      goto out;
>>>
>>> I don't see the need for the gotos, there's no cleanup in this function.
>>>
>>> +  /* gimple PHI expression.  */
>>> +  if (c_parser_next_token_is_keyword (parser, RID_PHI))
>>> +    {
>>> +      c_parser_consume_token (parser);
>>> +
>>> +      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
>>> +       {
>>> +         return;
>>> +       }
>>> +
>>> +      gcall *call_stmt;
>>> +      tree arg = NULL_TREE;
>>> +      vec<tree> vargs = vNULL;
>>>
>>> I think you can use auto_vec here, as is I think this leaks the vectors
>>> storage.
>>>
>>> +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code 
>>> *subcode)
>>>
>>> you can skip the explicit 'enum' keyword.
>>>
>>> +  struct {
>>> +    /* The expression at this stack level.  */
>>> +    struct c_expr expr;
>>>
>>> similar with struct here.
>>>
>>> +    /* The precedence of the operator on its left, PREC_NONE at the
>>> +       bottom of the stack.  */
>>> +    enum c_parser_prec prec;
>>> +    /* The operation on its left.  */
>>> +    enum tree_code op;
>>> +    /* The source location of this operation.  */
>>> +    location_t loc;
>>> +  } stack[2];
>>> +  int sp;
>>> +  /* Location of the binary operator.  */
>>> +  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
>>> +#define POP                                                                
>>>   \
>>>
>>> it seems like it would be nicer to name the type, and then make this a
>>> function.
>>>
>>> +                                       RO_UNARY_STAR);
>>> +       ret.src_range.m_start = op_loc;
>>> +       ret.src_range.m_finish = finish;
>>> +       return ret;
>>> +      }
>>> +    case CPP_PLUS:
>>> +      if (!c_dialect_objc () && !in_system_header_at (input_location))
>>> +       warning_at (op_loc,
>>> +                   OPT_Wtraditional,
>>> +                   "traditional C rejects the unary plus operator");
>>>
>>> does it really make sense to warn about C issues when compiling gimple?
>>>
>>> +c_parser_parse_ssa_names (c_parser *parser)
>>> +{
>>> +  tree id = NULL_TREE;
>>> +  c_expr ret;
>>> +  char *var_name, *var_version, *token;
>>> +  ret.original_code = ERROR_MARK;
>>> +  ret.original_type = NULL;
>>> +
>>> +  /* ssa token string.  */
>>> +  const char *ssa_token = NULL;
>>> +  ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
>>> +  token = new char [strlen (ssa_token)];
>>>
>>> I'm not sure I see why you need this copy, and getting rid of it would
>>> mean you don't need to free it.
>>>
>>> +  strcpy (token, ssa_token);
>>> +
>>> +  /* seperate var name and version.  */
>>> +  var_version = strrchr (token, '_');
>>> +  if (var_version)
>>> +    {
>>> +      var_name = new char[var_version - token + 1];
>>>
>>> you should free this when done with it.
>>>
>>> +c_parser_gimple_postfix_expression (c_parser *parser)
>>> +{
>>> +  struct c_expr expr;
>>> +  location_t loc = c_parser_peek_token (parser)->location;;
>>>
>>> extra ;
>>>
>>> +    case CPP_OBJC_STRING:
>>> +      gcc_assert (c_dialect_objc ());
>>> +      expr.value
>>> +       = objc_build_string_object (c_parser_peek_token (parser)->value);
>>> +      set_c_expr_source_range (&expr, tok_range);
>>> +      c_parser_consume_token (parser);
>>> +      break;
>>>
>>> is there a reason to support objc stuff in gimple?
>>>
>>> +c_parser_gimple_expr_list (c_parser *parser, bool convert_p,
>>> +                   vec<tree, va_gc> **p_orig_types,
>>> +                   location_t *sizeof_arg_loc, tree *sizeof_arg,
>>> +                   vec<location_t> *locations,
>>> +                   unsigned int *literal_zero_mask)
>>> +{
>>> +  vec<tree, va_gc> *ret;
>>> +  vec<tree, va_gc> *orig_types;
>>> +  struct c_expr expr;
>>> +  location_t loc = c_parser_peek_token (parser)->location;
>>> +  location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
>>> +  unsigned int idx = 0;
>>> +
>>> +  ret = make_tree_vector ();
>>> +  if (p_orig_types == NULL)
>>> +    orig_types = NULL;
>>> +  else
>>> +    orig_types = make_tree_vector ();
>>> +
>>> +  if (sizeof_arg != NULL
>>> +      && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
>>> +    cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
>>> +  if (literal_zero_mask)
>>> +    c_parser_check_literal_zero (parser, literal_zero_mask, 0);
>>> +  expr = c_parser_gimple_unary_expression (parser);
>>> +  if (convert_p)
>>> +    expr = convert_lvalue_to_rvalue (loc, expr, true, true);
>>> +  ret->quick_push (expr.value);
>>>
>>>  That kind of relies on the details of make_tree_vector (), so it seems
>>>  somewhat safer to use vec_safe_push.
>>>
>>> +  if (orig_types)
>>> +    orig_types->quick_push (expr.original_type);
>>>
>>> same
>>>
>>> +c_parser_gimple_declaration (c_parser *parser)
>>> +{
>>> +  struct c_declspecs *specs;
>>> +  struct c_declarator *declarator;
>>> +  specs = build_null_declspecs ();
>>> +  c_parser_declspecs (parser, specs, true, true, true,
>>> +                     true, true, cla_nonabstract_decl);
>>> +  finish_declspecs (specs);
>>> +  bool auto_type_p = specs->typespec_word == cts_auto_type;
>>>
>>> is it useful to support auto here in gimple?
>>>
>>> +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
>>> +{
>>> +  c_expr cond_expr;
>>> +  tree case_label, label;
>>> +  vec<tree> labels = vNULL;
>>>
>>> auto_vec?
>>>
>>> +static void
>>> +c_finish_gimple_return (location_t loc, tree retval)
>>> +{
>>> +  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
>>> +
>>> +  /* Use the expansion point to handle cases such as returning NULL
>>> +     in a function returning void.  */
>>> +  source_location xloc = expansion_point_location_if_in_system_header 
>>> (loc);
>>> +
>>> +  if (TREE_THIS_VOLATILE (current_function_decl))
>>> +    warning_at (xloc, 0,
>>> +               "function declared %<noreturn%> has a %<return%> 
>>> statement");
>>> +
>>> +  if (!retval)
>>> +    {
>>> +      current_function_returns_null = 1;
>>> +      if ((warn_return_type || flag_isoc99)
>>>
>>> I'm not sure what to do about warnings, but checking the language we are
>>> compiling as seems kind of wrong when we're compiling gimple?
>>>
>>> @@ -228,6 +228,12 @@ struct GTY(()) function {
>>>    /* GIMPLE body for this function.  */
>>>    gimple_seq gimple_body;
>>>
>>> +  /* GIMPLEFE pass to start with */
>>> +  opt_pass *pass_startwith = NULL;
>>>
>>> I'm guessing you've only compiled in C++11 mode? because I'm pretty sure
>>> you are using a C++11 feature here (the default member value you
>>> assign).
>>>
>>> Thanks!
>>>
>>> Trev
>>>
>>
>> Hi Trevor,
>>
>> Thanks for your feedback. I had missed removing some unwanted code
>> while code cleanup. I have updated the patch.
>> I am not sure if we should move all gimple parsing related functions
>> to the new file (?)
>
> I think it might be good to make the parts of the C parser you use more
> obvious (you'd need to export functions like c_parser_next_token_is).
>
> The easiest way to "force" that is to put all of the gimple parsing into
> a separate file.
>
> Note I am not so much concerned about this at the moment, the parts to
> improve would be avoiding more of the C-isms like convert_lvalue_to_rvalue,
> handling of SIZEOF_EXPR and other stuff that looks redundant (you've
> probably copied this from the C parsing routines and refactored it).
> Also the GIMPLE parser shouldn't do any warnings (just spotted
> a call to warn_for_memset).
>
PFA updated patch (successfully bootstrapped and tested on
x86_64-pc-linux-gnu). I have removed unnecessary code. On side I am
also trying to move gimple parser related functions to new file. But
for it we also have to move structs like c_token, c_parser. Won't it
disturb the c-parser code structure ?


Thanks,
Prasad

> Thanks,
> Richard.
>
>> I am not getting what did you mean by C++11 mode (I am not explicitly
>> giving any option while configure or make). I also have successfully
>> bootstrapped and tested the project on another system. Is there any
>> way to check that ?
>>
>>
>> Thanks,
>> Prasad
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1929ba8..cded23f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,55 @@
+2016-08-21  Prasad Ghangal  <prasad.ghan...@gmail.com>
+	
+	* cgraphunit.c (cgraph_node::assemble_thunks_and_aliases): New variable.
+	(cgraph_node::expand): Add new argument to function.
+	execute_pass_list, guard gcc_assert (TREE_ASM_WRITTEN (decl)) with 
+	condition.
+	* coretypes.h (tree_node *const_tree): New decl, add headers, new
+	variables.
+	* function.h (struct GTY()) function): Add new member to store
+	startwith pass also add new member as a flag.
+	* gimple-pretty-print.c (dump_gimple_switch): Change dumping formats.
+	(dump_gimple_label): Remove condition for DECL_NONLOCAL, flags & 
+	TDF_EH, EH_LANDING_PAD_NR. Change dumping format.
+	(dump_ssaname_info_to_file): Change passing arguments of dump_gimple_phi
+	(dump_gimple_phi): Remove condition for comment, change format of
+	dumping PHI and PHI arguments.
+	(pp_gimple_stmt_1): Remove argument of dump_gimple_phi function.
+	(dump_gimple_bb_header): Change format of dumping gimple basic block
+	header.
+	(dump_phi_nodes): Remove argument of dump_gimple_phi function.
+	(pp_cfg_jump): Remove stmt, remove condition for GIMPLE_LABEL, change 
+	dumping format of gimple basic block header.
+	(gimple_dump_bb_for_graph): Change format of dumping gimple basic block
+	* gimplify.c (gimplify_function_tree): Add condition for presence of
+	gimple body in the cfun.
+	* internal-fn.c (expand_PHI): New function.
+	* internal-fn.h (expand_PHI): Declared here.
+	* internal-fn.def: New defination for PHI.
+	* passes.c (do_per_function_toporder): Add new argument flag, add new
+	argument in callback function call.
+	(execute_one_pass): Add new function argument, add condition for 
+	skipping passes until startwith pass.
+	(execute_pass_list_1): Add new function argument, add condition to 
+	check starwith flag.
+	(execute_ipa_pass_list): New variable, add condition to check and skip
+	passes for startwith pass, pass new argument to function 
+	do_per_function_toporder.
+	* tree-pass.h (execute_one_pass): Add new argument to the function.
+	(execute_pass_list): Likewise.
+	* tree-cfg.c (lower_phi_internal_fn): New function.
+	(verify_gimple_call): Condition for passing label as arg in internal
+	function PHI.
+	(dump_function_to_file): Change format of gimple dump.
+	* tree-into-ssa.c (rewrite_add_phi_arguments): New variable, add 
+	condition for avoiding ssa name versions.
+	* tree-pretty-print.c (dump_decl_name): Change format of dumping gimple
+	labels.
+	(dump_function_header): Change format of gimple dump header
+	* tree-ssanames.c (make_ssa_name_fn): New argument, check for version
+	and assign proper version for parsed ssa names.
+	* tree-ssanames.h (make_ssa_name_fn): Add new argument to the function.
+
 2016-08-20  Kugan Vivekanandarajah  <kug...@linaro.org>
 
 	* Makefile.in: Add tree-vrp.h to GTFILES.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index bec37cf..a8c0ab1 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-08-21  Prasad Ghangal  <prasad.ghan...@gmail.com>
+	
+	* c-common.h (c_common_resword): Add RID_GIMPLE, RID_PHI types.
+	* c-common.h (enum rid): Add RID_GIMPLE, RID_PHI.
+	* c.opt (fgimple): New option.
+
 2016-08-19  Joseph Myers  <jos...@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8d9d4aa..71e78f3 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,29 @@
+2016-08-21  Prasad Ghangal  <prasad.ghan...@gmail.com>
+	
+	* c_parser.c: Add headers.
+	(c_parser_parse_gimple_body): New function.
+	(c_parser_gimple_compound_statement): Likewise.
+	(c_parser_gimple_label): Likewise.
+	(c_parser_gimple_expression): Likewise
+	(c_parser_gimple_binary_expression): Likewise.
+	(c_parser_gimple_unary_expression): Likewise.
+	(c_parser_gimple_postfix_expression): Likewise.
+	(c_parser_gimple_postfix_expression_after_primary): Likewise.
+	(c_parser_gimple_pass_list): Likewise.
+	(c_parser_gimple_pass_list_params): Likewise.
+	(c_parser_gimple_declaration): Likewise.
+	(c_parser_gimple_goto_stmt): Likewise.
+	(c_parser_gimple_if_stmt): Likewise.
+	(c_parser_gimple_switch_stmt): Likewise.
+	(c_parser_gimple_return_stmt): Likewise.
+	(c_finish_gimple_return): Likewise.
+	(c_parser_parse_ssa_names): Likewise.
+	(c_parser_gimple_paren_condition): Likewise.
+	(c_parser_gimple_expr_list): Likewise.
+	(c_parser_declaration_or_fndef): New decls. Call function.
+	c_parser_gimple_pass_list, set startwith passes, call
+	c_parser_parse_gimple_body.
+
 2016-08-19  Joseph Myers  <jos...@codesourcery.com>
 
 	PR c/32187
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6201e0c..3da6354 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2016-08-21  Prasad Ghangal  <prasad.ghan...@gmail.com>
+
+	* gcc.dg/gimplefe-1.c: New testcase.
+	* gcc.dg/gimplefe-2.c: Likewise.
+	* gcc.dg/gimplefe-3.c: Likewise.
+	* gcc.dg/gimplefe-4.c: Likewise.
+	* gcc.dg/gimplefe-5.c: Likewise.
+	* gcc.dg/gimplefe-6.c: Likewise.
+	* gcc.dg/gimplefe-7.c: Likewise.
+	* gcc.dg/gimplefe-8.c: Likewise.
+	* gcc.dg/gimplefe-9.c: Likewise.
+	* gcc.dg/gimplefe-10.c: Likewise.
+	* gcc.dg/gimplefe-11.c: Likewise.
+	* gcc.dg/gimplefe-12.c: Likewise.
+	* gcc.dg/gimplefe-13.c: Likewise.
+
 2016-08-20  Kugan Vivekanandarajah  <kug...@linaro.org>
 
 	PR tree-optimization/61839

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 32468ca..5b43016 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -522,6 +522,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
+  { "__GIMPLE",		RID_GIMPLE,	D_CONLY },
+  { "__PHI",		RID_PHI,	D_CONLY},
   { "alignas",		RID_ALIGNAS,	D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "alignof",		RID_ALIGNOF,	D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "asm",		RID_ASM,	D_ASM },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index bc22baa..17dc91e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -118,6 +118,12 @@ enum rid
 
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
 
+  /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
+  RID_GIMPLE,
+
+  /* "__PHI", for parsing PHI function in GIMPLE FE.  */
+  RID_PHI,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index a5358ed..3c4d2cc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -200,6 +200,10 @@ F
 Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
 -F <dir>	Add <dir> to the end of the main framework include path.
 
+fgimple
+C Var(flag_gimple) Init(0)
+Enable parsing GIMPLE
+
 H
 C ObjC C++ ObjC++
 Print the name of header files as they are used.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fe0c95f..fab8694 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -59,6 +59,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "context.h"
 #include "gcc-rich-location.h"
+#include "tree-vrp.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
+#include "pass_manager.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-dfa.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -1417,6 +1429,30 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
 static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
 static void c_parser_cilk_grainsize (c_parser *, bool *);
 
+/* Gimple parsing functions.  */
+static void c_parser_parse_gimple_body (c_parser *);
+static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_parser_gimple_label (c_parser *, gimple_seq *);
+static void c_parser_gimple_expression (c_parser *, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *);
+static struct c_expr c_parser_gimple_unary_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
+								       location_t,
+								       struct c_expr);
+static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
+static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
+static void c_parser_gimple_declaration (c_parser *);
+static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
+static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *);
+static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *);
+static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *);
+static void c_finish_gimple_return (location_t, tree);
+static c_expr c_parser_parse_ssa_names (c_parser *);
+static tree c_parser_gimple_paren_condition (c_parser *);
+static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *,
+		    vec<tree, va_gc> **, vec<location_t> *);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -1659,6 +1695,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
   tree all_prefix_attrs;
   bool diagnosed_no_specs = false;
   location_t here = c_parser_peek_token (parser)->location;
+  bool gimple_body_p = false;
+  opt_pass *pass = NULL;
+  bool startwith_p = false;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1743,6 +1782,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       c_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
+
+  if (c_parser_next_token_is (parser, CPP_KEYWORD))
+    {
+      c_token *kw_token = c_parser_peek_token (parser);
+      if (kw_token->keyword == RID_GIMPLE)
+	{
+	  gimple_body_p = true;
+	  c_parser_consume_token (parser);
+	  c_parser_gimple_pass_list (parser, &pass, &startwith_p);
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected %<)%>");
+	}
+    }
+
   finish_declspecs (specs);
   bool auto_type_p = specs->typespec_word == cts_auto_type;
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
@@ -2144,6 +2197,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	c_parser_declaration_or_fndef (parser, false, false, false,
 				       true, false, NULL, vNULL);
       store_parm_decls ();
+
+      if (pass)
+	{
+	  cfun->pass_startwith = pass;
+	  cfun->startwith = startwith_p;
+	}
+
       if (omp_declare_simd_clauses.exists ()
 	  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 	c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
@@ -2152,6 +2212,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
+
+      if (gimple_body_p && flag_gimple)
+	{
+	  bool saved = in_late_binary_op;
+	  in_late_binary_op = true;
+	  c_parser_parse_gimple_body (parser);
+	  in_late_binary_op = saved;
+	  cgraph_node::finalize_function (current_function_decl, false);
+	  set_cfun (NULL);
+	  current_function_decl = NULL;
+	  timevar_pop (tv);
+	  return;
+	}
+
       fnbody = c_parser_compound_statement (parser);
       if (flag_cilkplus && contains_array_notation_expr (fnbody))
 	fnbody = expand_array_notation_exprs (fnbody);
@@ -18194,4 +18268,1338 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
   return value_tree;
 }
 
+/* Parse the body of a function declaration marked with "__GIMPLE".  */
+
+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+  gimple_seq seq = NULL;
+  gimple_seq body = NULL;
+  tree stmt = push_stmt_list ();
+  push_scope ();
+  location_t loc1 = c_parser_peek_token (parser)->location;
+
+  init_tree_ssa (cfun);
+
+  if (!c_parser_gimple_compound_statement (parser, &seq))
+    {
+      gimple *ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (&seq, ret);
+    }
+
+  tree block = pop_scope ();
+  stmt = pop_stmt_list (stmt);
+  stmt = c_build_bind_expr (loc1, block, stmt);
+
+  block = DECL_INITIAL (current_function_decl);
+  BLOCK_SUBBLOCKS (block) = NULL_TREE;
+  BLOCK_CHAIN (block) = NULL_TREE;
+  TREE_ASM_WRITTEN (block) = 1;
+
+  gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+					BIND_EXPR_BLOCK (stmt));
+  gimple_bind_set_body (bind_stmt, seq);
+  gimple_seq_add_stmt (&body, bind_stmt);
+  gimple_set_body (current_function_decl, body);
+  cfun->curr_properties = PROP_gimple_any;
+
+  return;
+}
+
+/* Parse a compound statement in gimple function body.
+
+   gimple-statement:
+     gimple-statement
+     gimple-declaration-statement
+     gimple-if-statement
+     gimple-switch-statement
+     gimple-labeled-statement
+     gimple-expression-statement
+     gimple-goto-statement
+     gimple-phi-statement
+     gimple-return-statement
+*/
+
+static bool
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+  bool return_p = false;
+
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    return false;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_error (parser, "expected declaration or statement");
+      c_parser_consume_token (parser);
+      return false;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+
+      if (parser->error)
+	{
+	  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+	  return return_p;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	c_parser_gimple_label (parser, seq);
+
+      else if (c_parser_next_tokens_start_declaration (parser))
+	c_parser_gimple_declaration (parser);
+
+      else if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  c_parser_error (parser, "expected declaration or statement");
+	  return return_p;
+	}
+
+      else
+	{
+	  switch (c_parser_peek_token (parser)->type)
+	    {
+	    case CPP_KEYWORD:
+	      switch (c_parser_peek_token (parser)->keyword)
+		{
+		case RID_IF:
+		  c_parser_gimple_if_stmt (parser, seq);
+		  break;
+		case RID_SWITCH:
+		  c_parser_gimple_switch_stmt (parser, seq);
+		  break;
+		case RID_GOTO:
+		    {
+		      location_t loc = c_parser_peek_token (parser)->location;
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_NAME))
+			{
+			  c_parser_gimple_goto_stmt (loc,
+						     c_parser_peek_token (parser)->value,
+						     seq);
+			  c_parser_consume_token (parser);
+			  if (!c_parser_require (parser, CPP_SEMICOLON,
+						 "expected %<;%>"))
+			    return return_p;
+			}
+		    }
+		  break;
+		case RID_RETURN:
+		  return_p = true;
+		  c_parser_gimple_return_stmt (parser, seq);
+		  if (!c_parser_require (parser, CPP_SEMICOLON,
+					 "expected %<;%>"))
+		    return return_p;
+		  break;
+		default:
+		  goto expr_stmt;
+		}
+	      break;
+	    case CPP_SEMICOLON:
+	      c_parser_consume_token (parser);
+	      break;
+	    default:
+	    expr_stmt:
+	      c_parser_gimple_expression (parser, seq);
+	      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+		return return_p;
+	    }
+	}
+    }
+  c_parser_consume_token (parser);
+  return return_p; 
+}
+
+/* Parse a gimple expression.
+
+   gimple-expression:
+     gimple-unary-expression
+     gimple-call-statement
+     gimple-binary-expression
+     gimple-assign-expression
+     gimple-cast-expression
+
+*/
+
+static void
+c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
+{
+  struct c_expr lhs, rhs;
+  gimple *assign = NULL;
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc;
+  tree arg = NULL_TREE;
+  auto_vec<tree> vargs;
+
+  lhs = c_parser_gimple_unary_expression (parser);
+  rhs.value = error_mark_node;
+
+  if (c_parser_next_token_is (parser, CPP_EQ))
+    {
+      c_parser_consume_token (parser);
+    }
+
+  loc = EXPR_LOCATION (lhs.value);
+
+  /* gimple call expression. */
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON) &&
+      TREE_CODE (lhs.value) == CALL_EXPR)
+    {
+      gimple *call;
+      call = gimple_build_call_from_tree (lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  /* cast expression.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      rhs = c_parser_cast_expression (parser, NULL);	  //TODO: have a gimple_cast_expr function
+      if (lhs.value != error_mark_node &&
+	  rhs.value != error_mark_node)
+	{
+	  assign = gimple_build_assign (lhs.value, rhs.value);
+	  gimple_seq_add_stmt (seq, assign);
+	  gimple_set_location (assign, loc);
+	  return;
+	}
+    }
+
+  if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
+    {
+      STRIP_USELESS_TYPE_CONVERSION (rhs.value);
+      if (!useless_type_conversion_p (TREE_TYPE (lhs.value),
+				      TREE_TYPE (rhs.value)))
+	rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
+    }
+
+  /* pointer expression.  */
+  if (TREE_CODE (lhs.value) == INDIRECT_REF)
+    {
+      tree save_expr = lhs.value;
+      bool volatilep = TREE_THIS_VOLATILE (lhs.value);
+      bool notrap = TREE_THIS_NOTRAP (lhs.value);
+      tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0));
+
+      lhs.value = fold_indirect_ref_loc (loc, lhs.value);
+      if (lhs.value == save_expr)
+	{
+	  lhs.value = fold_build2_loc (input_location, MEM_REF,
+				       TREE_TYPE (lhs.value),
+				       TREE_OPERAND (lhs.value, 0),
+				       build_int_cst (saved_ptr_type, 0));
+	  TREE_THIS_VOLATILE (lhs.value) = volatilep;
+	  TREE_THIS_NOTRAP (lhs.value) = notrap;
+	}
+    }
+
+  if (c_parser_next_token_is (parser, CPP_AND) ||
+      c_parser_next_token_is (parser, CPP_MULT) ||
+      c_parser_next_token_is (parser, CPP_PLUS) ||
+      c_parser_next_token_is (parser, CPP_MINUS) ||
+      c_parser_next_token_is (parser, CPP_COMPL) ||
+      c_parser_next_token_is (parser, CPP_NOT))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      assign = gimple_build_assign (lhs.value, rhs.value);
+      gimple_set_location (assign, loc);
+      gimple_seq_add_stmt (seq, assign);
+      return;
+    }
+
+  /* gimple PHI expression.  */
+  if (c_parser_next_token_is_keyword (parser, RID_PHI))
+    {
+      c_parser_consume_token (parser);
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+	{
+	  return;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+	c_parser_consume_token (parser);
+
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	{
+	  if (c_parser_next_token_is (parser, CPP_NAME) &&
+	      c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+	    {
+	      arg = lookup_label_for_goto (loc,
+					   c_parser_peek_token (parser)->value);
+	      c_parser_consume_token (parser);
+
+	      if (c_parser_next_token_is (parser, CPP_COLON))
+		c_parser_consume_token (parser);
+	      vargs.safe_push (arg);
+	    }
+	  else if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	    }
+	  else
+	    {
+	      arg = c_parser_parse_ssa_names (parser).value;
+	      vargs.safe_push (arg);
+	    }
+	}
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				 "expected %<)%>");
+
+      /* build internal function for PHI. */
+      gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+      gimple_call_set_lhs (call_stmt, lhs.value);
+      gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+      gimple_seq_add_stmt (seq, call_stmt);
+      return;
+    }
+
+  /* gimple call with lhs. */
+  if (c_parser_next_token_is (parser, CPP_NAME) &&
+      c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN &&
+      lookup_name (c_parser_peek_token (parser)->value))
+    {
+      rhs = c_parser_gimple_unary_expression (parser);
+      gimple *call = gimple_build_call_from_tree (rhs.value);
+      gimple_call_set_lhs (call, lhs.value);
+      gimple_seq_add_stmt (seq, call);
+      gimple_set_location (call, loc);
+      return;
+    }
+
+  rhs = c_parser_gimple_binary_expression (parser, &subcode);
+
+  if (lhs.value != error_mark_node &&
+      rhs.value != error_mark_node)
+    {
+      if (subcode == NOP_EXPR)
+	assign = gimple_build_assign (lhs.value, rhs.value);
+      else
+	assign = gimple_build_assign (lhs.value, subcode,
+				      TREE_OPERAND (rhs.value, 0),
+				      TREE_OPERAND (rhs.value, 1));
+      gimple_seq_add_stmt (seq, assign);
+      gimple_set_location (assign, loc);
+    }
+  return;
+}
+
+/* Parse gimple binary expr.
+
+   gimple-multiplicative-expression:
+     gimple-unary-expression * gimple-unary-expression
+     gimple-unary-expression / gimple-unary-expression
+     gimple-unary-expression % gimple-unary-expression
+
+   gimple-additive-expression:
+     gimple-unary-expression + gimple-unary-expression
+     gimple-unary-expression - gimple-unary-expression
+
+   gimple-shift-expression:
+     gimple-unary-expression << gimple-unary-expression
+     gimple-unary-expression >> gimple-unary-expression
+
+   gimple-relational-expression:
+     gimple-unary-expression < gimple-unary-expression
+     gimple-unary-expression > gimple-unary-expression
+     gimple-unary-expression <= gimple-unary-expression
+     gimple-unary-expression >= gimple-unary-expression
+
+   gimple-equality-expression:
+     gimple-unary-expression == gimple-unary-expression
+     gimple-unary-expression != gimple-unary-expression
+
+   gimple-AND-expression:
+     gimple-unary-expression & gimple-unary-expression
+
+   gimple-exclusive-OR-expression:
+     gimple-unary-expression ^ gimple-unary-expression
+
+   gimple-inclusive-OR-expression:
+     gimple-unary-expression | gimple-unary-expression
+
+   gimple-logical-AND-expression:
+     gimple-unary-expression && gimple-unary-expression
+
+   gimple-logical-OR-expression:
+     gimple-unary-expression || gimple-unary-expression
+
+*/
+
+static c_expr
+c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
+{
+  struct {
+    /* The expression at this stack level.  */
+    struct c_expr expr;
+    /* The operation on its left.  */
+    enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
+  } stack[2];
+  int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+#define POP								      \
+  do {									      \
+    if (sp == 1								      \
+	&& c_parser_peek_token (parser)->type == CPP_SEMICOLON		      \
+	&& (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND)      \
+	       | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT)))     \
+	&& stack[sp].op != TRUNC_MOD_EXPR				      \
+	&& stack[0].expr.value != error_mark_node			      \
+	&& stack[1].expr.value != error_mark_node)			      \
+      stack[0].expr.value						      \
+	= build2 (stack[1].op, TREE_TYPE (stack[0].expr.value),		      \
+		  stack[0].expr.value, stack[1].expr.value);		      \
+    else								      \
+      stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,	      \
+						   stack[sp].op,	      \
+						   stack[sp - 1].expr,	      \
+						   stack[sp].expr);	      \
+    sp--;								      \
+  } while (0)
+  stack[0].loc = c_parser_peek_token (parser)->location;
+  stack[0].expr = c_parser_gimple_unary_expression (parser);
+  sp = 0;
+  source_range src_range;
+  if (parser->error)
+    goto out;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_MULT:
+      *subcode = MULT_EXPR;
+      break;
+    case CPP_DIV:
+      *subcode = TRUNC_DIV_EXPR;
+      break;
+    case CPP_MOD:
+      *subcode = TRUNC_MOD_EXPR;
+      break;
+    case CPP_PLUS:
+      *subcode = PLUS_EXPR;
+      break;
+    case CPP_MINUS:
+      *subcode = MINUS_EXPR;
+      break;
+    case CPP_LSHIFT:
+      *subcode = LSHIFT_EXPR;
+      break;
+    case CPP_RSHIFT:
+      *subcode = RSHIFT_EXPR;
+      break;
+    case CPP_LESS:
+      *subcode = LT_EXPR;
+      break;
+    case CPP_GREATER:
+      *subcode = GT_EXPR;
+      break;
+    case CPP_LESS_EQ:
+      *subcode = LE_EXPR;
+      break;
+    case CPP_GREATER_EQ:
+      *subcode = GE_EXPR;
+      break;
+    case CPP_EQ_EQ:
+      *subcode = EQ_EXPR;
+      break;
+    case CPP_NOT_EQ:
+      *subcode = NE_EXPR;
+      break;
+    case CPP_AND:
+      *subcode = BIT_AND_EXPR;
+      break;
+    case CPP_XOR:
+      *subcode = BIT_XOR_EXPR;
+      break;
+    case CPP_OR:
+      *subcode = BIT_IOR_EXPR;
+      break;
+    case CPP_AND_AND:
+      *subcode = TRUTH_ANDIF_EXPR;
+      break;
+    case CPP_OR_OR:
+      *subcode = TRUTH_ORIF_EXPR;
+      break;
+    default:
+      /* Not a binary operator, so end of the binary
+	 expression.  */
+      *subcode = NOP_EXPR;
+      goto out;
+    }
+  binary_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  switch (*subcode)
+    {
+    case TRUTH_ANDIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    case TRUTH_ORIF_EXPR:
+      src_range = stack[sp].expr.src_range;
+      stack[sp].expr.value = c_objc_common_truthvalue_conversion
+	(stack[sp].loc, default_conversion (stack[sp].expr.value));
+      set_c_expr_source_range (&stack[sp].expr, src_range);
+      break;
+    default:
+      break;
+    }
+  sp++;
+  stack[sp].loc = binary_loc;
+  stack[sp].expr = c_parser_gimple_unary_expression (parser);
+  stack[sp].op = *subcode;
+out:
+  while (sp > 0)
+    POP;
+  return stack[0].expr;
+#undef POP
+
+}
+
+/* Parse gimple unary expression.
+
+   gimple-unary-expression:
+     gimple-postfix-expression
+     unary-operator cast-expression
+
+   unary-operator: one of
+     & * + - ~ !
+*/
+
+static c_expr
+c_parser_gimple_unary_expression (c_parser *parser)
+{
+  struct c_expr ret, op;
+  if (c_parser_peek_token (parser)->value
+      && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
+      && !lookup_name (c_parser_peek_token (parser)->value))
+    return c_parser_parse_ssa_names (parser);
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t finish;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_AND:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+    case CPP_MULT:
+      {
+	c_parser_consume_token (parser);
+	op = c_parser_cast_expression (parser, NULL);
+	finish = op.get_finish ();
+	location_t combined_loc = make_location (op_loc, op_loc, finish);
+	ret.value = build_indirect_ref (combined_loc, op.value,
+					RO_UNARY_STAR);
+	ret.src_range.m_start = op_loc;
+	ret.src_range.m_finish = finish;
+	return ret;
+      }
+    case CPP_PLUS:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+    case CPP_MINUS:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+    case CPP_COMPL:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+    case CPP_NOT:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+    default:
+      return c_parser_gimple_postfix_expression (parser);
+    }
+}
+
+/* Parse gimple ssa names.  */
+
+static c_expr
+c_parser_parse_ssa_names (c_parser *parser)
+{
+  tree id = NULL_TREE;
+  c_expr ret;
+  char *var_name = NULL, *var_version = NULL, *token = NULL;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+
+  /* ssa token string.  */
+  const char *ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+  token = new char [strlen (ssa_token)];
+  strcpy (token, ssa_token);
+
+  /* seperate var name and version.  */
+  var_version = strrchr (token, '_');
+  if (var_version)
+    {
+      var_name = new char[var_version - token + 1];
+      memcpy (var_name, token, var_version - token);
+      var_name[var_version - token] = '\0';
+      id = get_identifier (var_name);
+
+      /* lookup for parent decl.  */
+      if (lookup_name (id))
+	{
+	  var_version++;
+	  unsigned int version;
+	  version = atoi (var_version);
+	  if (var_version && version)
+	    {
+	      ret.value = NULL_TREE;
+	      if (version < num_ssa_names)
+		ret.value = ssa_name (version);
+	      if (!ret.value)
+		ret.value = make_ssa_name_fn (cfun, lookup_name (id),
+					      gimple_build_nop (), version);
+	      c_parser_consume_token (parser);
+	    }
+	}
+    }
+
+  /* for default defination ssa names.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (!strcmp ("D", ssa_token))
+	{
+	  set_ssa_default_def (cfun, lookup_name (id), ret.value);
+	  c_parser_consume_token (parser);
+	}
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	goto out;
+    }
+
+  out:
+  free (var_name);
+  free (token);
+  return ret;
+}
+
+/* Parse gimple postfix expression.
+
+   gimple-postfix-expression:
+     gimple-primary-expression
+     gimple-primary-xpression [ gimple-primary-expression ]
+     gimple-primary-expression ( gimple-argument-expression-list[opt] )
+
+   gimple-argument-expression-list:
+     gimple-unary-expression
+     gimple-argument-expression-list , gimple-unary-expression
+
+   gimple-primary-expression:
+     identifier
+     constant
+     string-literal
+
+*/
+
+static struct c_expr
+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  source_range tok_range = c_parser_peek_token (parser)->get_range ();
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_NUMBER:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
+    case CPP_WCHAR:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      c_parser_consume_token (parser);
+      break;
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      expr.value = c_parser_peek_token (parser)->value;
+      set_c_expr_source_range (&expr, tok_range);
+      expr.original_code = STRING_CST;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_NAME:
+      if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
+	{
+	  tree id = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	  expr.value = build_external_ref (loc, id,
+					   (c_parser_peek_token (parser)->type
+					    == CPP_OPEN_PAREN),
+					   &expr.original_type);
+	  set_c_expr_source_range (&expr, tok_range);
+	  break;
+	}
+      else
+	{
+	  c_parser_error (parser, "expected expression");
+	  expr.set_error ();
+	  break;
+	}
+      break;
+    default:
+      c_parser_error (parser, "expected expression");
+      expr.set_error ();
+      break;
+    }
+  return c_parser_gimple_postfix_expression_after_primary
+    (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
+}
+
+/* Parse a gimple postfix expression after the initial primary or compound
+   literal.  */
+
+static struct c_expr
+c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+						  location_t expr_loc,
+						  struct c_expr expr)
+{
+  struct c_expr orig_expr;
+  vec<tree, va_gc> *exprlist;
+  vec<tree, va_gc> *origtypes = NULL;
+  vec<location_t> arg_loc = vNULL;
+  location_t start;
+  location_t finish;
+
+  location_t op_loc = c_parser_peek_token (parser)->location;
+
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_OPEN_SQUARE:
+	{
+	  c_parser_consume_token (parser);
+	  tree idx = c_parser_gimple_unary_expression (parser).value;
+
+	  if (!c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
+	    break;
+
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].location;
+	  expr.value = build_array_ref (op_loc, expr.value, idx);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  expr.original_type = NULL;
+	  break;
+	}
+    case CPP_OPEN_PAREN:
+	{
+	  /* Function call */
+	  c_parser_consume_token (parser);
+	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+	    exprlist = NULL;
+	  else
+	    exprlist = c_parser_gimple_expr_list (parser, &origtypes, 
+						  &arg_loc);
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected %<)%>");
+	  orig_expr = expr;
+	  start = expr.get_start ();
+	  finish = parser->tokens_buf[0].get_finish ();
+	  expr.value
+	    = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
+					 exprlist, origtypes);
+	  set_c_expr_source_range (&expr, start, finish);
+
+	  expr.original_code = ERROR_MARK;
+	  if (TREE_CODE (expr.value) == INTEGER_CST
+	      && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+	      && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+	      && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+	    expr.original_code = C_MAYBE_CONST_EXPR;
+	  expr.original_type = NULL;
+	  if (exprlist)
+	    {
+	      release_tree_vector (exprlist);
+	      release_tree_vector (origtypes);
+	    }
+	  arg_loc.release ();
+	  break;
+	default:
+	  return expr;
+
+	}
+    }
+  return expr;
+}
+
+/* Parse expression list.
+
+   gimple-expr-list:
+     gimple-unary-expression
+     gimple-expr-list , gimple-unary-expression
+
+ */
+
+static vec<tree, va_gc> *
+c_parser_gimple_expr_list (c_parser *parser, vec<tree, va_gc> **p_orig_types,
+			   vec<location_t> *locations)
+{
+  vec<tree, va_gc> *ret;
+  vec<tree, va_gc> *orig_types;
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
+  expr = c_parser_gimple_unary_expression (parser);
+  vec_safe_push (ret, expr.value);
+  if (orig_types)
+    vec_safe_push (orig_types, expr.original_type);
+  if (locations)
+    locations->safe_push (loc);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
+      expr = c_parser_gimple_unary_expression (parser);
+      vec_safe_push (ret, expr.value);
+      if (orig_types)
+	vec_safe_push (orig_types, expr.original_type);
+      if (locations)
+	locations->safe_push (loc);
+    }
+  if (orig_types)
+    *p_orig_types = orig_types;
+  return ret;
+}
+
+/* Parse gimple label.
+
+   gimple-label:
+     identifier :
+     case constant-expression :
+     default :
+
+*/
+
+static void
+c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+{
+  tree name = c_parser_peek_token (parser)->value;
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+  c_parser_consume_token (parser);
+  gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+  c_parser_consume_token (parser);
+  tree label = define_label (loc1, name);
+  gimple_seq_add_stmt (seq, gimple_build_label (label));
+  return;
+}
+
+/* Parse gimple pass list.
+
+   gimple-pass-list:
+     startwith("pass-name")
+ */
+
+static void
+c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
+			   bool *startwith_p)
+{
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      c_parser_consume_token (parser);
+      if (!strcmp (op, "startwith"))
+	{
+	  *pass = c_parser_gimple_pass_list_params (parser, pass);
+	  if (!(*pass))
+	    return;
+
+	  *startwith_p = true;
+	  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	    return;
+	}
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid operation");
+	  return;
+	}
+    }
+  else if (c_parser_next_token_is (parser, CPP_EOF))
+    {
+      c_parser_error (parser, "expected parameters");
+      return;
+    }
+
+  return;
+}
+
+/* Support function for c_parser_gimple_pass_list.  */
+
+static opt_pass *
+c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
+{
+  opt_pass *pass_start = NULL, *new_pass;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      return NULL;
+    }
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      return NULL;
+    }
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+    {
+      if (c_parser_next_token_is (parser, CPP_EOF))
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "expected pass names");
+	  return NULL;
+	}
+
+      if (c_parser_next_token_is (parser, CPP_STRING))
+	{
+	  const char *name = NULL;
+	  name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  new_pass = g->get_passes ()->get_pass_by_name (name);
+
+	  if (!new_pass)
+	    {
+	      error_at (c_parser_peek_token (parser)->location,
+			"invalid pass name");
+	      parser->error = true;
+	      c_parser_consume_token (parser);
+	      return NULL;
+	    }
+	  if (*pass)
+	    {
+	      (*pass)->next = new_pass;
+	      (*pass) = (*pass)->next;
+	    }
+	  else
+	    {
+	      *pass = new_pass;
+	      pass_start = *pass;
+	    }
+	}
+      else if (c_parser_next_token_is (parser, CPP_COMMA))
+	c_parser_consume_token (parser);
+      else
+	{
+	  error_at (c_parser_peek_token (parser)->location,
+		    "invalid pass name");
+	  c_parser_consume_token (parser);
+	  return NULL;
+	}
+    }
+  return pass_start;
+}
+
+/* Parse gimple local declaration.
+
+   declaration-specifiers:
+     storage-class-specifier declaration-specifiers[opt]
+     type-specifier declaration-specifiers[opt]
+     type-qualifier declaration-specifiers[opt]
+     function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
+
+   storage-class-specifier:
+     typedef
+     extern
+     static
+     auto
+     register
+
+   type-specifier:
+     void
+     char
+     short
+     int
+     long
+     float
+     double
+     signed
+     unsigned
+     _Bool
+     _Complex
+
+   type-qualifier:
+     const
+     restrict
+     volatile
+     address-space-qualifier
+     _Atomic
+
+ */
+
+static void
+c_parser_gimple_declaration (c_parser *parser)
+{
+  struct c_declarator *declarator;
+  struct c_declspecs *specs = build_null_declspecs ();
+  c_parser_declspecs (parser, specs, true, true, true,
+		      true, true, cla_nonabstract_decl);
+  finish_declspecs (specs);
+
+  /* Provide better error recovery.  Note that a type name here is usually
+     better diagnosed as a redeclaration.  */
+  if (c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>");
+      parser->error = false;
+      return;
+    }
+
+  bool dummy = false;
+  declarator = c_parser_declarator (parser,
+				    specs->typespec_kind != ctsk_none,
+				    C_DTR_NORMAL, &dummy);
+
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      tree postfix_attrs = NULL_TREE;
+      tree all_prefix_attrs = specs->attrs;
+      specs->attrs = NULL;
+      tree decl = start_decl (declarator, specs, false,
+			 chainon (postfix_attrs, all_prefix_attrs));
+      if (decl)
+	{
+	  finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE,
+		       NULL_TREE, NULL_TREE);
+	}
+    }
+  else
+    {
+      c_parser_error (parser, "expected %<;%>");
+      return;
+    }
+}
+
+/* Parse gimple goto statement.  */
+
+static void
+c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+{
+  tree decl = lookup_label_for_goto (loc, label);
+  gimple_seq_add_stmt (seq, gimple_build_goto (decl));
+  return;
+}
+
+/* Parse a parenthesized condition.
+   gimple-condition:
+     ( gimple-binary-expression )    */
+
+static tree
+c_parser_gimple_paren_condition (c_parser *parser)
+{
+  enum tree_code subcode = NOP_EXPR;
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return error_mark_node;
+  tree cond = c_parser_gimple_binary_expression (parser, &subcode).value;
+  cond = c_objc_common_truthvalue_conversion (loc, cond);
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return error_mark_node;
+  return cond;
+}
+
+/* Parse gimple if-else statement.
+
+   if-statement:
+     if ( gimple-binary-expression ) gimple-goto-statement
+     if ( gimple-binary-expression ) gimple-goto-statement \
+					else gimple-goto-statement
+ */
+
+static void
+c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+{
+  tree t_label, f_label, label;
+  location_t loc;
+  c_parser_consume_token (parser);
+  tree cond = c_parser_gimple_paren_condition (parser);
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      t_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+    c_parser_consume_token (parser);
+  else
+    {
+      c_parser_error (parser, "expected else statement");
+      return;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      label = c_parser_peek_token (parser)->value;
+      f_label = lookup_label_for_goto (loc, label);
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+	return;
+    }
+  else
+    {
+      c_parser_error (parser, "expected goto expression");
+      return;
+    }
+
+  gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+							 f_label));
+}
+
+/* Parse gimple switch-statement.
+
+   gimple-switch-statement:
+     switch (gimple-unary-expression) gimple-case-statement
+
+   gimple-case-statement:
+     gimple-case-statement
+     gimple-label-statement : gimple-goto-statment
+*/
+
+static void
+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+  c_expr cond_expr;
+  tree case_label, label;
+  auto_vec<tree> labels;
+  tree default_label = NULL_TREE;
+  gimple_seq switch_body = NULL;
+  location_t loc;
+  c_parser_consume_token (parser);
+
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      cond_expr = c_parser_gimple_unary_expression (parser);
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+	return;
+    }
+
+  if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+	{
+	  if (c_parser_next_token_is (parser, CPP_EOF))
+	    {
+	      c_parser_error (parser, "expected statement");
+	      return;
+	    }
+
+	  switch (c_parser_peek_token (parser)->keyword)
+	    {
+	    case RID_CASE:
+		{
+		  c_expr exp1;
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+
+		  if (c_parser_next_token_is (parser, CPP_NAME) ||
+		      c_parser_peek_token (parser)->type == CPP_NUMBER)
+		    exp1 = c_parser_gimple_unary_expression (parser);
+		  else
+		    c_parser_error (parser, "expected expression");
+
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      label = create_artificial_label (loc);
+		      case_label = build_case_label (exp1.value, NULL_TREE,
+						     label);
+		      labels.safe_push (case_label);
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (case_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_DEFAULT:
+		{
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_COLON))
+		    {
+		      c_parser_consume_token (parser);
+		      default_label = build_case_label (NULL_TREE, NULL_TREE,
+							create_artificial_label
+							(UNKNOWN_LOCATION));
+		      gimple_seq_add_stmt (&switch_body,
+					   gimple_build_label
+					   (CASE_LABEL (default_label)));
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_SEMICOLON,
+					     "expected %<:%>"))
+			return;
+		    }
+		}
+	      break;
+	    case RID_GOTO:
+		{
+		  loc = c_parser_peek_token (parser)->location;
+		  c_parser_consume_token (parser);
+		  if (c_parser_next_token_is (parser, CPP_NAME))
+		    {
+		      c_parser_gimple_goto_stmt (loc,
+						 c_parser_peek_token (parser)->value,
+						 &switch_body);
+		      c_parser_consume_token (parser);
+		      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+			c_parser_consume_token (parser);
+		      else
+			{
+			  c_parser_error (parser, "expected semicolon");
+			  return;
+			}
+		    }
+		  else
+		    {
+		      if (!c_parser_require (parser, CPP_NAME,
+					     "expected label"))
+			return;
+		    }
+		}
+	      break;
+	    default:
+	      c_parser_error (parser, "expected case label or goto statement");
+	      return;
+	    }
+
+	}
+    }
+  if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+    return;
+  gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
+						 default_label, labels));
+  gimple_seq_add_seq (seq, switch_body);
+  labels.release();
+}
+
+/* Parse gimple return statement.  */
+
+static void
+c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  gimple *ret = NULL;
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_finish_gimple_return (loc, NULL_TREE);
+      ret = gimple_build_return (NULL);
+      gimple_seq_add_stmt (seq, ret);
+    }
+  else
+    {
+      location_t xloc = c_parser_peek_token (parser)->location;
+      c_expr expr = c_parser_gimple_unary_expression (parser);
+      c_finish_gimple_return (xloc, expr.value);
+      ret = gimple_build_return (expr.value);
+      gimple_seq_add_stmt (seq, ret);
+    }
+}
+
+/* Support function for c_parser_gimple_return_stmt.  */
+
+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+  /* Use the expansion point to handle cases such as returning NULL
+     in a function returning void.  */
+  source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+  if (TREE_THIS_VOLATILE (current_function_decl))
+    warning_at (xloc, 0,
+		"function declared %<noreturn%> has a %<return%> statement");
+
+  if (!retval)
+    {
+      current_function_returns_null = 1;
+    }  
+  else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+    {
+      current_function_returns_null = 1;
+      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+	{
+	  error_at
+	    (xloc, "%<return%> with a value, in function returning void");
+	  inform (DECL_SOURCE_LOCATION (current_function_decl),
+		  "declared here");
+	}
+    }
+  else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
+    {
+      error_at
+	(xloc, "invalid conversion in return statement");
+      inform (DECL_SOURCE_LOCATION (current_function_decl),
+	      "declared here");
+    }
+  return;
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 6a1d126..cf6728f 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1944,6 +1944,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
 void
 cgraph_node::expand (void)
 {
+  bool startwith_p = true;
   location_t saved_loc;
 
   /* We ought to not compile any inline clones.  */
@@ -1982,7 +1983,7 @@ cgraph_node::expand (void)
   /* Signal the start of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
 
-  execute_pass_list (cfun, g->get_passes ()->all_passes);
+  execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p);
 
   /* Signal the end of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
@@ -2035,7 +2036,9 @@ cgraph_node::expand (void)
   timevar_pop (TV_REST_OF_COMPILATION);
 
   /* Make sure that BE didn't give up on compiling.  */
-  gcc_assert (TREE_ASM_WRITTEN (decl));
+  if (!(flag_gimple && cfun->pass_startwith))  /* FIXME : for gimplefe custom_pass_list */
+    gcc_assert (TREE_ASM_WRITTEN (decl));
+
   if (cfun)
     pop_cfun ();
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index fe1e984..ad6e5ac 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -85,6 +85,7 @@ typedef const union tree_node *const_tree;
 struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
+class opt_pass;
 
 /* Forward decls for leaf gimple subclasses (for individual gimple codes).
    Keep this in the same order as the corresponding codes in gimple.def.  */
@@ -405,6 +406,8 @@ typedef unsigned char uchar;
 #include "input.h"
 #include "is-a.h"
 #include "memory-block.h"
+#include "pass_manager.h"
+#include "tree-pass.h"
 #endif /* GENERATOR_FILE && !USED_FOR_TARGET */
 
 #endif /* coretypes.h */
diff --git a/gcc/function.h b/gcc/function.h
index 501ef68..38c00fd 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -228,6 +228,12 @@ struct GTY(()) function {
   /* GIMPLE body for this function.  */
   gimple_seq gimple_body;
 
+  /* GIMPLEFE pass to start with */
+  opt_pass *pass_startwith;
+
+  /* Startwith flag */
+  bool startwith;
+
   /* SSA and dataflow information.  */
   struct gimple_df *gimple_df;
 
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 12d9a9c..e4416a5 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -838,7 +838,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
     {
       pp_string (buffer, "switch (");
       dump_generic_node (buffer, gimple_switch_index (gs), spc, flags, true);
-      pp_string (buffer, ") <");
+      pp_string (buffer, ") {");
     }
 
   for (i = 0; i < gimple_switch_num_labels (gs); i++)
@@ -849,9 +849,9 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
       pp_space (buffer);
       dump_generic_node (buffer, CASE_LABEL (case_label), spc, flags, false);
       if (i < gimple_switch_num_labels (gs) - 1)
-        pp_string (buffer, ", ");
+        pp_string (buffer, "; ");
     }
-  pp_greater (buffer);
+  pp_string (buffer, "}");
 }
 
 
@@ -907,16 +907,11 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, int flags)
 {
   tree label = gimple_label_label (gs);
   if (flags & TDF_RAW)
-      dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, label);
+    dump_gimple_fmt (buffer, spc, flags, "%T", label);
   else
-    {
-      dump_generic_node (buffer, label, spc, flags, false);
-      pp_colon (buffer);
-    }
-  if (DECL_NONLOCAL (label))
-    pp_string (buffer, " [non-local]");
-  if ((flags & TDF_EH) && EH_LANDING_PAD_NR (label))
-    pp_printf (buffer, " [LP %d]", EH_LANDING_PAD_NR (label));
+    dump_generic_node (buffer, label, spc, flags, false);
+
+  pp_colon (buffer);
 }
 
 /* Dump a GIMPLE_GOTO tuple on the pretty_printer BUFFER, SPC
@@ -1966,8 +1961,7 @@ dump_ssaname_info_to_file (FILE *file, tree node, int spc)
    pretty printer.  If COMMENT is true, print this after #.  */
 
 static void
-dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
-		 int flags)
+dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, int flags)
 {
   size_t i;
   tree lhs = gimple_phi_result (phi);
@@ -1975,30 +1969,27 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment,
   if (flags & TDF_ALIAS)
     dump_ssaname_info (buffer, lhs, spc);
 
-  if (comment)
-    pp_string (buffer, "# ");
-
   if (flags & TDF_RAW)
     dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
 		     gimple_phi_result (phi));
   else
     {
       dump_generic_node (buffer, lhs, spc, flags, false);
-      pp_string (buffer, " = PHI <");
+      pp_string (buffer, " = __PHI (");
     }
   for (i = 0; i < gimple_phi_num_args (phi); i++)
     {
       if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
 	dump_location (buffer, gimple_phi_arg_location (phi, i));
+      pp_string (buffer, "bb_");
+      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
+      pp_string (buffer, ": ");
       dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags,
 			 false);
-      pp_left_paren (buffer);
-      pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
-      pp_right_paren (buffer);
       if (i < gimple_phi_num_args (phi) - 1)
 	pp_string (buffer, ", ");
     }
-  pp_greater (buffer);
+  pp_right_paren (buffer);
 }
 
 
@@ -2286,7 +2277,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, int flags)
       break;
 
     case GIMPLE_PHI:
-      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, false, flags);
+      dump_gimple_phi (buffer, as_a <gphi *> (gs), spc, flags);
       break;
 
     case GIMPLE_OMP_PARALLEL:
@@ -2447,7 +2438,7 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags)
     {
       gimple *stmt = first_stmt (bb);
       if (!stmt || gimple_code (stmt) != GIMPLE_LABEL)
-	fprintf (outf, "%*s<bb %d>:\n", indent, "", bb->index);
+	fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
     }
 }
 
@@ -2480,7 +2471,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
       if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS))
         {
           INDENT (indent);
-	  dump_gimple_phi (buffer, phi, indent, true, flags);
+	  dump_gimple_phi (buffer, phi, indent, flags);
           pp_newline (buffer);
         }
     }
@@ -2493,24 +2484,9 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
 static void
 pp_cfg_jump (pretty_printer *buffer, basic_block bb)
 {
-  gimple *stmt;
-
-  stmt = first_stmt (bb);
-
-  pp_string (buffer, "goto <bb ");
+  pp_string (buffer, "goto bb_");
   pp_decimal_int (buffer, bb->index);
-  pp_greater (buffer);
-  if (stmt && gimple_code (stmt) == GIMPLE_LABEL)
-    {
-      pp_string (buffer, " (");
-      dump_generic_node (buffer,
-			 gimple_label_label (as_a <glabel *> (stmt)),
-			 0, 0, false);
-      pp_right_paren (buffer);
-      pp_semicolon (buffer);
-    }
-  else
-    pp_semicolon (buffer);
+  pp_semicolon (buffer);
 }
 
 
@@ -2627,7 +2603,7 @@ gimple_dump_bb (FILE *file, basic_block bb, int indent, int flags)
 void
 gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
 {
-  pp_printf (pp, "<bb %d>:\n", bb->index);
+  pp_printf (pp, "bb_%d:\n", bb->index);
   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 
   for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4715332..12b9ec9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11848,7 +11848,22 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (fndecl, true);
+  if (!cfun->gimple_body)
+    bind = gimplify_body (fndecl, true);
+  else
+    {
+      gimple_seq seq;
+      gimple *outer_stmt;
+      seq = cfun->gimple_body;
+      outer_stmt = gimple_seq_first_stmt (seq);
+      if (gimple_code (outer_stmt) == GIMPLE_BIND
+	  && gimple_seq_first (seq) == gimple_seq_last (seq))
+	bind = as_a <gbind *> (outer_stmt);
+      else
+	bind = gimple_build_bind (NULL_TREE, seq, NULL);
+
+      DECL_SAVED_TREE (fndecl) = NULL_TREE;
+    }
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index cd4b625..3824fb7 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2412,3 +2412,9 @@ expand_internal_call (gcall *stmt)
 {
   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
 }
+
+void
+expand_PHI (internal_fn, gcall *)
+{
+    gcc_unreachable ();
+}
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 6701cd9..a5dd23e 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -169,6 +169,7 @@ DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
    other such optimizations.  The first argument distinguishes
    between uses.  See internal-fn.h for usage.  */
 DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (PHI, 0, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index bb31465..9c39dd67 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -174,5 +174,6 @@ extern bool set_edom_supported_p (void);
 
 extern void expand_internal_call (gcall *);
 extern void expand_internal_call (internal_fn, gcall *);
+extern void expand_PHI (internal_fn, gcall *);
 
 #endif
diff --git a/gcc/passes.c b/gcc/passes.c
index c7d7dbe..04caf39 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1685,12 +1685,13 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data)
    call CALLBACK on the current function.
    This function is global so that plugins can use it.  */
 void
-do_per_function_toporder (void (*callback) (function *, void *data), void *data)
+do_per_function_toporder (void (*callback) (function *, void *data, void *flag),
+			  void *data, void *flag)
 {
   int i;
 
   if (current_function_decl)
-    callback (cfun, data);
+    callback (cfun, data, flag);
   else
     {
       cgraph_node_hook_list *hook;
@@ -1725,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data)
 	    {
 	      struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
 	      push_cfun (fn);
-	      callback (fn, data);
+	      callback (fn, data, flag);
 	      pop_cfun ();
 	    }
 	}
@@ -2276,8 +2277,18 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status)
 /* Execute PASS. */
 
 bool
-execute_one_pass (opt_pass *pass)
+execute_one_pass (opt_pass *pass, bool startwith_p)
 {
+  /* For skipping passes until startwith pass */
+  if (cfun && startwith_p && cfun->startwith)
+    {
+      if (!strcmp (pass->name, cfun->pass_startwith->name)
+	  || !strcmp (pass->name, "*clean_state"))
+	cfun->startwith = false;
+      else
+	return true;
+    }
+
   unsigned int todo_after = 0;
 
   bool gate_status;
@@ -2417,7 +2428,7 @@ execute_one_pass (opt_pass *pass)
 }
 
 static void
-execute_pass_list_1 (opt_pass *pass)
+execute_pass_list_1 (opt_pass *pass, bool startwith_p)
 {
   do
     {
@@ -2426,18 +2437,23 @@ execute_pass_list_1 (opt_pass *pass)
 
       if (cfun == NULL)
 	return;
-      if (execute_one_pass (pass) && pass->sub)
-        execute_pass_list_1 (pass->sub);
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
+	execute_pass_list_1 (pass->sub, startwith_p);
       pass = pass->next;
     }
   while (pass);
 }
 
 void
-execute_pass_list (function *fn, opt_pass *pass)
+execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p)
 {
   gcc_assert (fn == cfun);
-  execute_pass_list_1 (pass);
+
+  if (startwith_p)
+    execute_pass_list_1 (pass, *startwith_p);
+  else
+    execute_pass_list_1 (pass, false);
+
   if (cfun && fn->cfg)
     {
       free_dominance_info (CDI_DOMINATORS);
@@ -2767,19 +2783,22 @@ ipa_read_optimization_summaries (void)
 void
 execute_ipa_pass_list (opt_pass *pass)
 {
+  bool startwith_p = false;
   do
     {
       gcc_assert (!current_function_decl);
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
-      if (execute_one_pass (pass) && pass->sub)
+      if (!strcmp (pass->name, "opt_local_passes"))
+	startwith_p = true;
+      if (execute_one_pass (pass, startwith_p) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
 	    {
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
-	      do_per_function_toporder ((void (*)(function *, void *))
+	      do_per_function_toporder ((void (*)(function *, void *, void *))
 					  execute_pass_list,
-					pass->sub);
+					pass->sub, &startwith_p);
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
 	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 57c8410..7fe994e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -170,6 +170,7 @@ static edge find_taken_edge_computed_goto (basic_block, tree);
 static edge find_taken_edge_cond_expr (basic_block, tree);
 static edge find_taken_edge_switch_expr (gswitch *, basic_block, tree);
 static tree find_case_label_for_value (gswitch *, tree);
+static void lower_phi_internal_fn ();
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -244,6 +245,7 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
   make_edges ();
   assign_discriminators ();
+  lower_phi_internal_fn ();
   cleanup_dead_labels ();
   delete discriminator_per_locus;
   discriminator_per_locus = NULL;
@@ -345,6 +347,50 @@ replace_loop_annotate (void)
     }
 }
 
+/* Lower internal PHI function from GIMPLE FE.  */
+
+static void
+lower_phi_internal_fn ()
+{
+  basic_block bb, pred = NULL;
+  gimple_stmt_iterator gsi;
+  tree lhs;
+  gphi *phi_node;
+  gimple *stmt;
+
+  /* After edge creation, handle __PHI function from GIMPLE FE.  */
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  stmt = gsi_stmt (gsi);
+	  if (gimple_code (stmt) != GIMPLE_CALL)
+	    continue;
+
+	  if (gimple_call_internal_p (stmt) &&
+	      gimple_call_internal_fn (stmt) == IFN_PHI)
+	    {
+	      gsi_remove (&gsi, true);
+	      unsigned int i;
+	      lhs = gimple_call_lhs (stmt);
+	      phi_node = create_phi_node (lhs, bb);
+
+	      /* Add arguments to the PHI node.  */
+	      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+		{
+		  tree arg = gimple_call_arg (stmt, i);
+		  if (TREE_CODE (arg) == LABEL_DECL)
+		    pred = label_to_block (arg);
+		  else
+		    {
+		      edge e = find_edge (pred, bb);
+		      add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION);
+		    }
+		}
+	    }
+	}
+    }
+}
 
 static unsigned int
 execute_build_cfg (void)
@@ -3340,6 +3386,11 @@ verify_gimple_call (gcall *stmt)
 	  debug_generic_stmt (fn);
 	  return true;
 	}
+      /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/
+      else if (gimple_call_internal_fn (stmt) == IFN_PHI)
+	{
+	  return false;
+	}
     }
   else
     {
@@ -7504,7 +7555,8 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
     }
 
   current_function_decl = fndecl;
-  fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
+  print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), dump_flags);
+  fprintf (file, "\n%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
   arg = DECL_ARGUMENTS (fndecl);
   while (arg)
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index ceafa68..ba3dc05 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1379,12 +1379,19 @@ rewrite_add_phi_arguments (basic_block bb)
       for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
 	   gsi_next (&gsi))
 	{
-	  tree currdef, res;
+	  tree currdef, res, argvar;
 	  location_t loc;
 
 	  phi = gsi.phi ();
 	  res = gimple_phi_result (phi);
-	  currdef = get_reaching_def (SSA_NAME_VAR (res));
+	  /* If we have pre-existing PHI its args may be different
+	     vars than existing vars */
+	  argvar = gimple_phi_arg_def (phi, e->dest_idx);
+	  if (argvar && TREE_CODE (argvar) == SSA_NAME)
+	    continue;
+	  if (!argvar)
+	    argvar = SSA_NAME_VAR (res);
+	  currdef = get_reaching_def (argvar);
 	  /* Virtual operand PHI args do not need a location.  */
 	  if (virtual_operand_p (res))
 	    loc = UNKNOWN_LOCATION;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c0059de..213070b 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -617,8 +617,9 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
 /* Current optimization pass.  */
 extern opt_pass *current_pass;
 
-extern bool execute_one_pass (opt_pass *);
-extern void execute_pass_list (function *, opt_pass *);
+extern bool execute_one_pass (opt_pass *, bool startwith_p = false);
+extern void execute_pass_list (function *, opt_pass *,
+			       bool *startwith_p = NULL);
 extern void execute_ipa_pass_list (opt_pass *);
 extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 734ecda..aa53bd2 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -260,7 +260,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
   if ((flags & TDF_UID) || DECL_NAME (node) == NULL_TREE)
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
-	pp_printf (pp, "L.%d", (int) LABEL_DECL_UID (node));
+	pp_printf (pp, "L_%d", (int) LABEL_DECL_UID (node));
       else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
 	{
 	  if (flags & TDF_NOUID)
@@ -274,7 +274,7 @@ dump_decl_name (pretty_printer *pp, tree node, int flags)
 	  if (flags & TDF_NOUID)
 	    pp_printf (pp, "%c.xxxx", c);
 	  else
-	    pp_printf (pp, "%c.%u", c, DECL_UID (node));
+	    pp_printf (pp, "%c_%u", c, DECL_UID (node));
 	}
     }
   if ((flags & TDF_ALIAS) && DECL_PT_UID (node) != DECL_UID (node))
@@ -3965,14 +3965,14 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
   else
     aname = "<unset-asm-name>";
 
-  fprintf (dump_file, "\n;; Function %s (%s, funcdef_no=%d",
+  fprintf (dump_file, "\n/* Function %s (%s, funcdef_no=%d",
 	   dname, aname, fun->funcdef_no);
   if (!(flags & TDF_NOUID))
     fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl));
   if (node)
     {
       fprintf (dump_file, ", cgraph_uid=%d", node->uid);
-      fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order,
+      fprintf (dump_file, ", symbol_order=%d)%s", node->order,
                node->frequency == NODE_FREQUENCY_HOT
                ? " (hot)"
                : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
@@ -3982,7 +3982,8 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
                : "");
     }
   else
-    fprintf (dump_file, ")\n\n");
+    fprintf (dump_file, ")");
+  fprintf (dump_file, "*/\n\n");
 }
 
 /* Dump double_int D to pretty_printer PP.  UNS is true
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 91a8f97..8b8863b 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -255,7 +255,8 @@ flush_ssaname_freelist (void)
    used without a preceding definition).  */
 
 tree
-make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
+make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
+		  unsigned int version)
 {
   tree t;
   use_operand_p imm;
@@ -265,8 +266,19 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt)
 	      || TREE_CODE (var) == RESULT_DECL
 	      || (TYPE_P (var) && is_gimple_reg_type (var)));
 
+  /* parsing ssa names with versions.	*/
+  if (version != 0)
+    {
+      t = make_node (SSA_NAME);
+      SSA_NAME_VERSION (t) = version;
+      if (version >= SSANAMES (fn)->length ())
+	vec_safe_grow_cleared (SSANAMES (fn), version + 1);
+      gcc_assert ((*SSANAMES (fn))[version] == NULL);
+      (*SSANAMES (fn))[version] = t;
+      ssa_name_nodes_created++;
+    }
   /* If our free list has an element, then use it.  */
-  if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
+  else if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
     {
       t = FREE_SSANAMES (fn)->pop ();
       ssa_name_nodes_reused++;
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 8e66ce6..3ce9327 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -74,7 +74,8 @@ extern bool ssa_name_has_boolean_range (tree);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (struct function *);
 extern void ssanames_print_statistics (void);
-extern tree make_ssa_name_fn (struct function *, tree, gimple *);
+extern tree make_ssa_name_fn (struct function *, tree, gimple *,
+			      unsigned int version = 0);
 extern void release_ssa_name_fn (struct function *, tree);
 extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *,
 				    unsigned int *);
diff --git a/gcc/testsuite/gcc.dg/gimplefe-1.c b/gcc/testsuite/gcc.dg/gimplefe-1.c
new file mode 100644
index 0000000..0786d47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int i;
+void __GIMPLE () foo()
+{
+  i = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-10.c b/gcc/testsuite/gcc.dg/gimplefe-10.c
new file mode 100644
index 0000000..7f63c58
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-10.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return b;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  b = bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-11.c b/gcc/testsuite/gcc.dg/gimplefe-11.c
new file mode 100644
index 0000000..e1483f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-11.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE() bar(int a, int b, int c)
+{
+  a = 1;
+  b = a + 1;
+  c = b * 4;
+  return;
+}
+
+void __GIMPLE() foo()
+{
+  int a;
+  int b;
+  int c;
+  bar(a, b, c);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c
new file mode 100644
index 0000000..cbaf8a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-12.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-ccp1")) foo ()
+{
+  int a;
+  int b;
+  a = b + 2;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c
new file mode 100644
index 0000000..c0da9fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-13.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE (startwith ("tree-dse1")) foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-2.c b/gcc/testsuite/gcc.dg/gimplefe-2.c
new file mode 100644
index 0000000..e3a23cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile }*/
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  b = a;
+  b = b + 1;
+  a = b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-3.c b/gcc/testsuite/gcc.dg/gimplefe-3.c
new file mode 100644
index 0000000..595365e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int *b;
+  *b = 1;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-4.c b/gcc/testsuite/gcc.dg/gimplefe-4.c
new file mode 100644
index 0000000..3600c7c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  char b;
+  a = (int) b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-5.c b/gcc/testsuite/gcc.dg/gimplefe-5.c
new file mode 100644
index 0000000..1dab4af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-5.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int a;
+void __GIMPLE () foo ()
+{
+  int b;
+  int c;
+
+bb_2:
+  b = a;
+  if (b > 3)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  b = c + 4;
+  goto bb_5;
+
+bb_4:
+  b = b + 1;
+  goto bb_5;
+
+bb_5:
+  a = b;
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-6.c b/gcc/testsuite/gcc.dg/gimplefe-6.c
new file mode 100644
index 0000000..242e08f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+  int b;
+  int c;
+  int d;
+
+bb_2:
+  a = ~b;
+  b = a << c;
+  c = a & b;
+  d = b | c;
+
+bb_3:
+  return;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-7.c b/gcc/testsuite/gcc.dg/gimplefe-7.c
new file mode 100644
index 0000000..6125541
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE () foo ()
+{
+  int a;
+
+bb_2:
+  if (a > 4)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_3:
+  a_2 = 10;
+  goto bb_5;
+
+bb_4:
+  a_3 = 20;
+
+bb_5:
+  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+  a_4 = a_1 + 4;
+
+return;
+}
+
diff --git a/gcc/testsuite/gcc.dg/gimplefe-8.c b/gcc/testsuite/gcc.dg/gimplefe-8.c
new file mode 100644
index 0000000..4936bec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-8.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE () foo ()
+{
+  int a;
+  int b;
+
+bb_2:
+  b = a_1(D) + 1;
+bb_3:
+  return b;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-9.c b/gcc/testsuite/gcc.dg/gimplefe-9.c
new file mode 100644
index 0000000..a24be273
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-9.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+int __GIMPLE() bar()
+{
+  int a;
+  a = a + 1;
+  return a;
+}
+
+void __GIMPLE() foo()
+{
+  int b;
+  b = bar();
+}

Reply via email to