Hi, I tried hacking pass manager to execute only given passes. For this I am adding new member as opt_pass *custom_pass_list to the function structure to store passes need to execute and providing the custom_pass_list to execute_pass_list() function instead of all passes
for test case like- int a; void __GIMPLE (execute ("tree-ccp1", "tree-fre1")) foo() { bb_1: a = 1 + a; } it will execute only given passes i.e. ccp1 and fre1 pass on the function and for test case like - int a; void __GIMPLE (startwith ("tree-ccp1")) foo() { bb_1: a = 1 + a; } it will act as a entry point to the pipeline and will execute passes starting from given pass. Thanks, Prasad Ghangal
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 4568cf6..f2e62ca 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -511,6 +511,7 @@ 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 }, { "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 0295532..23a401d 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -104,6 +104,9 @@ enum rid RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, 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, + /* C11 */ RID_ALIGNAS, RID_GENERIC, diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 918df16..8ab56af 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-decl.c b/gcc/c/c-decl.c index d79802e..d498f19 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -9154,6 +9154,7 @@ finish_function (void) invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, current_function_decl); current_function_decl = NULL; } + /* Check the declarations given in a for-loop for satisfying the C99 constraints. If exactly one such decl is found, return it. LOC is diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index bca8653..2d83281 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -58,6 +58,14 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-indentation.h" #include "gimple-expr.h" #include "context.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" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -1396,6 +1404,13 @@ static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context); 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 *); +static void c_parser_parse_gimple_body (c_parser *); +static void c_parser_gimple_compound_statement (c_parser *, gimple_seq *); +static void c_finish_gimple_expr_stmt (tree, gimple_seq *); +static void c_parser_gimple_basic_block (c_parser *, gimple_seq *); +static void c_parser_gimple_expression (c_parser *, gimple_seq *); +static void c_parser_pass_list (c_parser *, opt_pass **); +static opt_pass *c_parser_pass_list_params (c_parser *, opt_pass **); /* Parse a translation unit (C90 6.7, C99 6.9). @@ -1638,6 +1653,8 @@ 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; if (static_assert_ok && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) @@ -1687,6 +1704,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_pass_list (parser, &pass); + 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)) @@ -2093,6 +2124,10 @@ 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->custom_pass_list = pass; + 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, @@ -2102,6 +2137,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, oacc_routine_clauses, false, first, true); DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus = c_parser_peek_token (parser)->location; + + if (gimple_body_p && flag_gimple) + { + c_parser_parse_gimple_body (parser); + cgraph_node::finalize_function (current_function_decl, false); + timevar_pop (tv); + return; + } + fnbody = c_parser_compound_statement (parser); if (flag_cilkplus && contains_array_notation_expr (fnbody)) fnbody = expand_array_notation_exprs (fnbody); @@ -18070,4 +18114,288 @@ 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) +{ + debug_generic_expr (current_function_decl); + gimple_seq seq; + location_t loc1 = c_parser_peek_token (parser)->location; + inform (loc1, "start of GIMPLE"); + seq = NULL; + c_parser_gimple_compound_statement (parser, &seq); + + greturn *r = gimple_build_return (NULL); + gimple_seq_add_stmt (&seq, r); + + DECL_INITIAL (current_function_decl) = make_node (BLOCK); + BLOCK_SUPERCONTEXT (DECL_INITIAL (current_function_decl)) = current_function_decl; + + tree block = DECL_INITIAL (current_function_decl); + BLOCK_SUBBLOCKS (block) = NULL_TREE; + BLOCK_CHAIN (block) = NULL_TREE; + TREE_ASM_WRITTEN (block) = 1; + + gimple_set_body (current_function_decl, seq); + cfun->curr_properties = PROP_gimple_any; + + debug_gimple_seq (seq); + init_tree_ssa (cfun); + return; +} + +/* Parser a compound statement in gimple function body */ + +static void +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq) +{ + location_t brace_loc; + brace_loc = c_parser_peek_token (parser)->location; + if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + { + return; + } + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_consume_token (parser); + goto out; + } + + /* We must now have at least one statement, label or declaration. */ + + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_error (parser, "expected declaration or statement"); + c_parser_consume_token (parser); + goto out; + } + while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) + { + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + { + c_parser_gimple_basic_block (parser, seq); + } + else if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected declaration or statement"); + goto out; + } + else + { + switch (c_parser_peek_token (parser)->type) + { + case CPP_KEYWORD: + switch (c_parser_peek_token (parser)->keyword) + { + default: + goto expr_stmt; + } + break; + case CPP_SEMICOLON: + c_parser_consume_token (parser); + break; + default: + expr_stmt: + c_parser_gimple_expression (parser, seq); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + break; + } + } + parser->error = false; + } + c_parser_consume_token (parser); + + out: + return; +} + +/* Parse a gimple expression */ + +static void +c_parser_gimple_expression (c_parser *parser, gimple_seq *seq) +{ + c_expr lhs, rhs; + enum tree_code subcode; + lhs = c_parser_unary_expression (parser); + if (c_parser_next_token_is (parser, CPP_EQ)) + c_parser_consume_token (parser); + if (!(c_parser_next_token_is (parser, CPP_NAME) + || c_parser_next_token_is (parser, CPP_NUMBER))) + { + c_parser_error (parser, "expected expression"); + return; + } + switch (c_parser_peek_2nd_token (parser)->type) + { + case CPP_PLUS: + subcode = PLUS_EXPR; + break; + case CPP_MINUS: + subcode = MINUS_EXPR; + break; + case CPP_MULT: + subcode = MULT_EXPR; + break; + case CPP_DIV: + subcode = RDIV_EXPR; + break; + case CPP_SEMICOLON: + default: + gimple_seq_add_stmt (seq, gimple_build_assign (lhs.value, + c_parser_unary_expression (parser).value)); + return; + } +/* if (!(c_parser_next_token_is (parser, CPP_NAME) + || c_parser_next_token_is (parser, CPP_NUMBER))) + { + c_parser_error (parser, "invalid gimple expression"); + return; + }*/ + rhs = c_parser_binary_expression (parser, NULL, NULL); + gimple_seq_add_stmt (seq, gimple_build_assign (lhs.value, subcode, + TREE_OPERAND(rhs.value, 0), TREE_OPERAND(rhs.value, 1))); + return; +} + +/* Emit an expression as a statement. */ + +static void +c_finish_gimple_expr_stmt (tree expr, gimple_seq *seq) +{ + tree lhs, rhs; + gimple *stmt; + if (expr) + { + lhs = TREE_OPERAND (expr, 0); + rhs = TREE_OPERAND (expr, 1); + stmt = gimple_build_assign (lhs, rhs); + gimple_seq_add_stmt (seq, stmt); + return; + } +} + +/* Parse gimple basic block */ + +static void +c_parser_gimple_basic_block (c_parser *parser, gimple_seq *seq) +{ + tree bb; + 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); + bb = build_decl (loc1, LABEL_DECL, name, void_type_node); + DECL_CONTEXT (bb) = current_function_decl; + gimple_seq_add_stmt (seq, gimple_build_label (bb)); + return; +} + +/* Parse gimple pass list */ + +static void +c_parser_pass_list (c_parser *parser, opt_pass **pass) +{ + opt_pass *pass_start; + 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, "execute")) + { + pass_start = c_parser_pass_list_params (parser, pass); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + (*pass)->next = NULL; + *pass = pass_start; + } + else if (!strcmp (op, "startwith")) + { + *pass = c_parser_pass_list_params (parser, pass); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + } + else + { + c_parser_error (parser, "invalid operation"); + return; + } + } + else if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected parameters"); + return; + } + + return; +} + +static opt_pass * +c_parser_pass_list_params (c_parser *parser, opt_pass **pass) +{ + opt_pass *pass_start, *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)) + { + c_parser_error (parser, "expected pass names"); + return NULL; + } + + if (c_parser_next_token_is (parser, CPP_STRING)) + { + const char *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) + { + c_parser_error (parser, "invalid pass name"); + 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 + { + c_parser_error (parser, "expected pass names"); + return NULL; + } + } + return pass_start; +} + #include "gt-c-c-parser.h" diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 4bfcad7..7effd71 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1980,7 +1980,10 @@ 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); + if (flag_gimple && cfun->custom_pass_list) + execute_pass_list (cfun, cfun->custom_pass_list); + else + execute_pass_list (cfun, g->get_passes ()->all_passes); /* Signal the end of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); @@ -2033,7 +2036,10 @@ 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->custom_pass_list)) /* 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 b3a91a6..491573e 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. */ @@ -399,6 +400,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..f84b97b 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -228,6 +228,9 @@ struct GTY(()) function { /* GIMPLE body for this function. */ gimple_seq gimple_body; + /* GIMPLEFE Passes */ + opt_pass *custom_pass_list = NULL; + /* SSA and dataflow information. */ struct gimple_df *gimple_df; diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c index ed012cc..1b2310f 100644 --- a/gcc/gimple-expr.c +++ b/gcc/gimple-expr.c @@ -726,6 +726,9 @@ is_gimple_ip_invariant (const_tree t) bool is_gimple_reg (tree t) { + if (flag_gimple) /* FIXME : For GIMPLE FE gimple expr*/ + return true; + if (virtual_operand_p (t)) return false; diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 9ea17af..e56e81c 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -90,8 +90,10 @@ lower_function_body (void) /* The gimplifier should've left a body of exactly one statement, namely a GIMPLE_BIND. */ - gcc_assert (gimple_seq_first (body) == gimple_seq_last (body) - && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND); + /* FIXME : to parse gimple body without gimple bind */ + if (! (gimple_seq_first (body) == gimple_seq_last (body) + && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND)) + return 0; memset (&data, 0, sizeof (data)); data.block = DECL_INITIAL (current_function_decl); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8316bb8..dd6b04e 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -11678,7 +11678,10 @@ 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 + bind = NULL; /* The tree body of the function is no longer needed, replace it with the new GIMPLE body. */ diff --git a/gcc/passes.c b/gcc/passes.c index 0565cfa..117a25a 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -2294,6 +2294,7 @@ execute_one_pass (opt_pass *pass) gcc_assert (cfun && current_function_decl); current_pass = pass; + debug_pass (); /* Check whether gate check should be avoided. User controls the value of the gate through the parameter "gate_status". */