On 24 August 2016 at 15:32, Richard Biener <[email protected]> wrote:
> On Mon, Aug 22, 2016 at 8:40 PM, Prasad Ghangal
> <[email protected]> wrote:
>> On 22 August 2016 at 16:55, Trevor Saunders <[email protected]> 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 <[email protected]>
+
+ * 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 <[email protected]>
* 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 <[email protected]>
+
+ * 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 <[email protected]>
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 <[email protected]>
+
+ * 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 <[email protected]>
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 <[email protected]>
+
+ * 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 <[email protected]>
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();
+}