From 1ee62b926411dda2bffbca8019b494481183ee15 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Mon, 14 Nov 2016 13:51:48 +0000 Subject: [PATCH] Make-lang.in (C_AND_OBJC_OBJS): Add gimple-parser.o. 2016-11-14 Prasad Ghangal Richard Biener c/ * Make-lang.in (C_AND_OBJC_OBJS): Add gimple-parser.o. * config-lang.in (gtfiles): Add c/c-parser.h. * c-tree.h (enum c_declspec_word): Add cdw_gimple. (struct c_declspecs): Add gimple_pass member and gimple_p flag. * c-parser.c (enum c_id_kind, struct c_token, c_parser_next_token_is, c_parser_next_token_is_not, c_parser_next_token_is_keyword, enum c_lookahead_kind, enum c_dtr_syn, enum c_parser_prec): Split out to ... * c-parser.h: ... new header. * c-parser.c: Include c-parser.h and gimple-parser.h. (c_parser_peek_token, c_parser_peek_2nd_token, c_token_starts_typename, c_parser_next_token_starts_declspecs, c_parser_next_tokens_start_declaration, c_parser_consume_token, c_parser_error, c_parser_require, c_parser_skip_until_found, c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token, c_parser_type_name): Export. (c_parser_tokens_buf): New function. (c_parser_error): Likewise. (c_parser_set_error): Likewise. (c_parser_declspecs): Handle RID_GIMPLE. (c_parser_declaration_or_fndef): Parse __GIMPLE marked body via c_parser_parse_gimple_body. * c-parser.h (c_parser_peek_token, c_parser_peek_2nd_token, c_token_starts_typename, c_parser_next_token_starts_declspecs, c_parser_next_tokens_start_declaration, c_parser_consume_token, c_parser_error, c_parser_require, c_parser_skip_until_found, c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token, c_parser_type_name): Declare. (struct c_parser): Declare forward. (c_parser_tokens_buf): Declare. (c_parser_error): Likewise. (c_parser_set_error): Likewise. * gimple-parser.c: New file. * gimple-parser.h: Likewise. obj-c/ * config-lang.in (gtfiles): Add c/c-parser.h. c-family/ * 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. * doc/invoke.texi (fgimple): Document. * dumpfile.h (TDF_GIMPLE): Add. * dumpfile.c (dump_options): Add gimple. * gimple-pretty-print.c (dump_gimple_switch): Adjust dump for TDF_GIMPLE. (dump_gimple_label): Likewise. (dump_gimple_phi): Likewise. (dump_gimple_bb_header): Likewise. (dump_phi_nodes): Likewise. (pp_cfg_jump): Likewise. Pass in dump flags. (dump_implicit_edges): Adjust. * passes.c (pass_init_dump_file): Do not dump function header for TDF_GIMPLE. * tree-cfg.c (dump_function_to_file): Dump function return type and __GIMPLE keyword for TDF_GIMPLE. Change guard for dumping GIMPLE stmts. * tree-pretty-print.c (dump_decl_name): Adjust dump for TDF_GIMPLE. (dump_generic_node): Likewise. * function.h (struct function): Add pass_startwith member. * passes.c (execute_one_pass): Implement startwith. * 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. * internal-fn.c (expand_PHI): New function. * internal-fn.h (expand_PHI): Declared here. * internal-fn.def: New defination for PHI. * tree-cfg.c (lower_phi_internal_fn): New function. (build_gimple_cfg): Call it. (verify_gimple_call): Condition for passing label as arg in internal function PHI. * tree-into-ssa.c (rewrite_add_phi_arguments): Handle already present PHIs with arguments. testsuite/ * 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. * gcc.dg/gimplefe-14.c: Likewise. * gcc.dg/gimplefe-15.c: Likewise. * gcc.dg/gimplefe-16.c: Likewise. * gcc.dg/gimplefe-17.c: Likewise. * gcc.dg/gimplefe-18.c: Likewise. Co-Authored-By: Richard Biener From-SVN: r242387 --- gcc/ChangeLog | 36 ++++++ gcc/c-family/ChangeLog | 7 ++ gcc/c-family/c-common.c | 2 + gcc/c-family/c-common.h | 6 + gcc/c-family/c.opt | 4 + gcc/c/ChangeLog | 39 +++++++ gcc/c/Make-lang.in | 3 +- gcc/c/c-parser.c | 235 +++++++++++++------------------------- gcc/c/c-tree.h | 5 + gcc/c/config-lang.in | 2 +- gcc/doc/invoke.texi | 9 +- gcc/dumpfile.c | 4 +- gcc/dumpfile.h | 7 +- gcc/function.h | 3 + gcc/gimple-pretty-print.c | 106 ++++++++++++----- gcc/internal-fn.c | 6 + gcc/internal-fn.def | 1 + gcc/internal-fn.h | 1 + gcc/objc/ChangeLog | 5 + gcc/objc/config-lang.in | 2 +- gcc/passes.c | 33 +++++- gcc/testsuite/ChangeLog | 22 ++++ gcc/tree-cfg.c | 61 +++++++++- gcc/tree-into-ssa.c | 12 +- gcc/tree-pretty-print.c | 22 +++- gcc/tree-ssanames.c | 19 ++- gcc/tree-ssanames.h | 3 +- 27 files changed, 447 insertions(+), 208 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f8dc1bd2bf8..4fea3461b76 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2016-11-14 Prasad Ghangal + Richard Biener + + * doc/invoke.texi (fgimple): Document. + * dumpfile.h (TDF_GIMPLE): Add. + * dumpfile.c (dump_options): Add gimple. + * gimple-pretty-print.c (dump_gimple_switch): Adjust dump + for TDF_GIMPLE. + (dump_gimple_label): Likewise. + (dump_gimple_phi): Likewise. + (dump_gimple_bb_header): Likewise. + (dump_phi_nodes): Likewise. + (pp_cfg_jump): Likewise. Pass in dump flags. + (dump_implicit_edges): Adjust. + * passes.c (pass_init_dump_file): Do not dump function header + for TDF_GIMPLE. + * tree-cfg.c (dump_function_to_file): Dump function return type + and __GIMPLE keyword for TDF_GIMPLE. Change guard for dumping + GIMPLE stmts. + * tree-pretty-print.c (dump_decl_name): Adjust dump for TDF_GIMPLE. + (dump_generic_node): Likewise. + * function.h (struct function): Add pass_startwith member. + * passes.c (execute_one_pass): Implement startwith. + * 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. + * internal-fn.c (expand_PHI): New function. + * internal-fn.h (expand_PHI): Declared here. + * internal-fn.def: New defination for PHI. + * tree-cfg.c (lower_phi_internal_fn): New function. + (build_gimple_cfg): Call it. + (verify_gimple_call): Condition for passing label as arg in internal + function PHI. + * tree-into-ssa.c (rewrite_add_phi_arguments): Handle already + present PHIs with arguments. + 2016-11-14 Martin Liska PR bootstrap/78069 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 8c99b75aa56..2360d9ed17c 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2016-11-14 Prasad Ghangal + Richard Biener + + * 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-11-13 Eric Botcazou * c-ada-spec.c (print_ada_declaration): For typedef declarations, look diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 307862b9c7c..2997c83925f 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -435,6 +435,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 4f27f81b5b3..241b3454e06 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 cf946e7b86e..722d3800cf0 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 Add 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/ChangeLog b/gcc/c/ChangeLog index ee50c304b5f..75f39d7ed8b 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,42 @@ +2016-11-14 Prasad Ghangal + Richard Biener + + * Make-lang.in (C_AND_OBJC_OBJS): Add gimple-parser.o. + * config-lang.in (gtfiles): Add c/c-parser.h. + * c-tree.h (enum c_declspec_word): Add cdw_gimple. + (struct c_declspecs): Add gimple_pass member and gimple_p flag. + * c-parser.c (enum c_id_kind, struct c_token, + c_parser_next_token_is, c_parser_next_token_is_not, + c_parser_next_token_is_keyword, + enum c_lookahead_kind, enum c_dtr_syn, enum c_parser_prec): + Split out to ... + * c-parser.h: ... new header. + * c-parser.c: Include c-parser.h and gimple-parser.h. + (c_parser_peek_token, c_parser_peek_2nd_token, + c_token_starts_typename, c_parser_next_token_starts_declspecs, + c_parser_next_tokens_start_declaration, c_parser_consume_token, + c_parser_error, c_parser_require, c_parser_skip_until_found, + c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token, + c_parser_type_name): Export. + (c_parser_tokens_buf): New function. + (c_parser_error): Likewise. + (c_parser_set_error): Likewise. + (c_parser_declspecs): Handle RID_GIMPLE. + (c_parser_declaration_or_fndef): Parse __GIMPLE marked body + via c_parser_parse_gimple_body. + * c-parser.h (c_parser_peek_token, c_parser_peek_2nd_token, + c_token_starts_typename, c_parser_next_token_starts_declspecs, + c_parser_next_tokens_start_declaration, c_parser_consume_token, + c_parser_error, c_parser_require, c_parser_skip_until_found, + c_parser_declspecs, c_parser_declarator, c_parser_peek_nth_token, + c_parser_type_name): Declare. + (struct c_parser): Declare forward. + (c_parser_tokens_buf): Declare. + (c_parser_error): Likewise. + (c_parser_set_error): Likewise. + * gimple-parser.c: New file. + * gimple-parser.h: Likewise. + 2016-09-11 Le-Chun Wu Mark Wielaard diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in index 72c9ae74f87..cd7108b8afa 100644 --- a/gcc/c/Make-lang.in +++ b/gcc/c/Make-lang.in @@ -51,7 +51,8 @@ CFLAGS-c/gccspec.o += $(DRIVER_DEFINES) # Language-specific object files for C and Objective C. C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \ c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \ - c/c-array-notation.o c/c-fold.o $(C_COMMON_OBJS) $(C_TARGET_OBJS) + c/c-array-notation.o c/c-fold.o c/gimple-parser.o \ + $(C_COMMON_OBJS) $(C_TARGET_OBJS) # Language-specific object files for C. C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS) diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 52a5eddff7b..00fe7312c4c 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -59,6 +59,8 @@ along with GCC; see the file COPYING3. If not see #include "gimple-expr.h" #include "context.h" #include "gcc-rich-location.h" +#include "c-parser.h" +#include "gimple-parser.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -150,63 +152,6 @@ c_parse_init (void) } } -/* The C lexer intermediates between the lexer in cpplib and c-lex.c - and the C parser. Unlike the C++ lexer, the parser structure - stores the lexer information instead of using a separate structure. - Identifiers are separated into ordinary identifiers, type names, - keywords and some other Objective-C types of identifiers, and some - look-ahead is maintained. - - ??? It might be a good idea to lex the whole file up front (as for - C++). It would then be possible to share more of the C and C++ - lexer code, if desired. */ - -/* More information about the type of a CPP_NAME token. */ -enum c_id_kind { - /* An ordinary identifier. */ - C_ID_ID, - /* An identifier declared as a typedef name. */ - C_ID_TYPENAME, - /* An identifier declared as an Objective-C class name. */ - C_ID_CLASSNAME, - /* An address space identifier. */ - C_ID_ADDRSPACE, - /* Not an identifier. */ - C_ID_NONE -}; - -/* A single C token after string literal concatenation and conversion - of preprocessing tokens to tokens. */ -struct GTY (()) c_token { - /* The kind of token. */ - ENUM_BITFIELD (cpp_ttype) type : 8; - /* If this token is a CPP_NAME, this value indicates whether also - declared as some kind of type. Otherwise, it is C_ID_NONE. */ - ENUM_BITFIELD (c_id_kind) id_kind : 8; - /* If this token is a keyword, this value indicates which keyword. - Otherwise, this value is RID_MAX. */ - ENUM_BITFIELD (rid) keyword : 8; - /* If this token is a CPP_PRAGMA, this indicates the pragma that - was seen. Otherwise it is PRAGMA_NONE. */ - ENUM_BITFIELD (pragma_kind) pragma_kind : 8; - /* The location at which this token was found. */ - location_t location; - /* The value associated with this token, if any. */ - tree value; - /* Token flags. */ - unsigned char flags; - - source_range get_range () const - { - return get_range_from_loc (line_table, location); - } - - location_t get_finish () const - { - return get_range ().m_finish; - } -}; - /* A parser structure recording information about the state and context of parsing. Includes lexer information with up to two tokens of look-ahead; more are not needed for C. */ @@ -259,6 +204,30 @@ struct GTY(()) c_parser { vec *cilk_simd_fn_tokens; }; +/* Return a pointer to the Nth token in PARSERs tokens_buf. */ + +c_token * +c_parser_tokens_buf (c_parser *parser, unsigned n) +{ + return &parser->tokens_buf[n]; +} + +/* Return the error state of PARSER. */ + +bool +c_parser_error (c_parser *parser) +{ + return parser->error; +} + +/* Set the error state of PARSER to ERR. */ + +void +c_parser_set_error (c_parser *parser, bool err) +{ + parser->error = err; +} + /* The actual parser and external interface. ??? Does this need to be garbage-collected? */ @@ -454,7 +423,7 @@ c_lex_one_token (c_parser *parser, c_token *token) /* Return a pointer to the next token from PARSER, reading it in if necessary. */ -static inline c_token * +c_token * c_parser_peek_token (c_parser *parser) { if (parser->tokens_avail == 0) @@ -465,37 +434,10 @@ c_parser_peek_token (c_parser *parser) return &parser->tokens[0]; } -/* Return true if the next token from PARSER has the indicated - TYPE. */ - -static inline bool -c_parser_next_token_is (c_parser *parser, enum cpp_ttype type) -{ - return c_parser_peek_token (parser)->type == type; -} - -/* Return true if the next token from PARSER does not have the - indicated TYPE. */ - -static inline bool -c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type) -{ - return !c_parser_next_token_is (parser, type); -} - -/* Return true if the next token from PARSER is the indicated - KEYWORD. */ - -static inline bool -c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword) -{ - return c_parser_peek_token (parser)->keyword == keyword; -} - /* Return a pointer to the next-but-one token from PARSER, reading it in if necessary. The next token is already read in. */ -static c_token * +c_token * c_parser_peek_2nd_token (c_parser *parser) { if (parser->tokens_avail >= 2) @@ -511,7 +453,7 @@ c_parser_peek_2nd_token (c_parser *parser) /* Return a pointer to the Nth token from PARSER, reading it in if necessary. The N-1th token is already read in. */ -static c_token * +c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n) { /* N is 1-based, not zero-based. */ @@ -570,7 +512,7 @@ c_keyword_starts_typename (enum rid keyword) /* Return true if TOKEN can start a type name, false otherwise. */ -static bool +bool c_token_starts_typename (c_token *token) { switch (token->type) @@ -601,18 +543,6 @@ c_token_starts_typename (c_token *token) } } -enum c_lookahead_kind { - /* Always treat unknown identifiers as typenames. */ - cla_prefer_type, - - /* Could be parsing a nonabstract declarator. Only treat an identifier - as a typename if followed by another identifier or a star. */ - cla_nonabstract_decl, - - /* Never treat identifiers as typenames. */ - cla_prefer_id -}; - /* Return true if the next token from PARSER can start a type name, false otherwise. LA specifies how to do lookahead in order to detect unknown type names. If unsure, pick CLA_PREFER_ID. */ @@ -779,7 +709,7 @@ c_token_starts_declaration (c_token *token) /* Return true if the next token from PARSER can start declaration specifiers, false otherwise. */ -static inline bool +bool c_parser_next_token_starts_declspecs (c_parser *parser) { c_token *token = c_parser_peek_token (parser); @@ -801,7 +731,7 @@ c_parser_next_token_starts_declspecs (c_parser *parser) /* Return true if the next tokens from PARSER can start declaration specifiers or a static assertion, false otherwise. */ -static inline bool +bool c_parser_next_tokens_start_declaration (c_parser *parser) { c_token *token = c_parser_peek_token (parser); @@ -829,7 +759,7 @@ c_parser_next_tokens_start_declaration (c_parser *parser) /* Consume the next token from PARSER. */ -static void +void c_parser_consume_token (c_parser *parser) { gcc_assert (parser->tokens_avail >= 1); @@ -922,7 +852,7 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind, this way is not i18n-friendly and some other approach should be used. */ -static void +void c_parser_error (c_parser *parser, const char *gmsgid) { c_token *token = c_parser_peek_token (parser); @@ -965,7 +895,7 @@ c_parser_error (c_parser *parser, const char *gmsgid) been produced and no message will be produced this time. Returns true if found, false otherwise. */ -static bool +bool c_parser_require (c_parser *parser, enum cpp_ttype type, const char *msgid) @@ -1008,7 +938,7 @@ c_parser_require_keyword (c_parser *parser, already been produced and no message will be produced this time. */ -static void +void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type, const char *msgid) @@ -1243,42 +1173,6 @@ restore_extension_diagnostics (int flags) warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0); } -/* Possibly kinds of declarator to parse. */ -enum c_dtr_syn { - /* A normal declarator with an identifier. */ - C_DTR_NORMAL, - /* An abstract declarator (maybe empty). */ - C_DTR_ABSTRACT, - /* A parameter declarator: may be either, but after a type name does - not redeclare a typedef name as an identifier if it can - alternatively be interpreted as a typedef name; see DR#009, - applied in C90 TC1, omitted from C99 and reapplied in C99 TC2 - following DR#249. For example, given a typedef T, "int T" and - "int *T" are valid parameter declarations redeclaring T, while - "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are - abstract declarators rather than involving redundant parentheses; - the same applies with attributes inside the parentheses before - "T". */ - C_DTR_PARM -}; - -/* The binary operation precedence levels, where 0 is a dummy lowest level - used for the bottom of the stack. */ -enum c_parser_prec { - PREC_NONE, - PREC_LOGOR, - PREC_LOGAND, - PREC_BITOR, - PREC_BITXOR, - PREC_BITAND, - PREC_EQ, - PREC_REL, - PREC_SHIFT, - PREC_ADD, - PREC_MULT, - NUM_PRECS -}; - /* Helper data structure for parsing #pragma acc routine. */ struct oacc_routine_data { bool error_seen; /* Set if error has been reported. */ @@ -1295,15 +1189,11 @@ static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool * = NULL); static void c_parser_static_assert_declaration_no_semi (c_parser *); static void c_parser_static_assert_declaration (c_parser *); -static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, - bool, bool, bool, enum c_lookahead_kind); static struct c_typespec c_parser_enum_specifier (c_parser *); static struct c_typespec c_parser_struct_or_union_specifier (c_parser *); static tree c_parser_struct_declaration (c_parser *); static struct c_typespec c_parser_typeof_specifier (c_parser *); static tree c_parser_alignas_specifier (c_parser *); -static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn, - bool *); static struct c_declarator *c_parser_direct_declarator (c_parser *, bool, c_dtr_syn, bool *); static struct c_declarator *c_parser_direct_declarator_inner (c_parser *, @@ -1315,7 +1205,6 @@ static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree, static struct c_parm *c_parser_parameter_declaration (c_parser *, tree); static tree c_parser_simple_asm_expr (c_parser *); static tree c_parser_attributes (c_parser *); -static struct c_type_name *c_parser_type_name (c_parser *); static struct c_expr c_parser_initializer (c_parser *); static struct c_expr c_parser_braced_init (c_parser *, tree, bool, struct obstack *); @@ -1652,7 +1541,13 @@ static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool); OpenMP: declaration: - threadprivate-directive */ + threadprivate-directive + + GIMPLE: + + gimple-function-definition: + declaration-specifiers[opt] __GIMPLE (gimple-pass-list) declarator + declaration-list[opt] compound-statement */ static void c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, @@ -1752,6 +1647,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, c_parser_skip_to_end_of_block_or_statement (parser); return; } + finish_declspecs (specs); bool auto_type_p = specs->typespec_word == cts_auto_type; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) @@ -1882,7 +1778,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, struct c_declarator *declarator; bool dummy = false; timevar_id_t tv; - tree fnbody; + tree fnbody = NULL_TREE; /* Declaring either one or more declarators (in which case we should diagnose if there were no declaration specifiers) or a function definition (in which case the diagnostic for @@ -2173,9 +2069,24 @@ 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; - fnbody = c_parser_compound_statement (parser); - if (flag_cilkplus && contains_array_notation_expr (fnbody)) - fnbody = expand_array_notation_exprs (fnbody); + + /* If the definition was marked with __GIMPLE then parse the + function body as GIMPLE. */ + if (specs->gimple_p) + { + cfun->pass_startwith = specs->gimple_pass; + bool saved = in_late_binary_op; + in_late_binary_op = true; + c_parser_parse_gimple_body (parser); + in_late_binary_op = saved; + } + else + { + fnbody = c_parser_compound_statement (parser); + if (flag_cilkplus && contains_array_notation_expr (fnbody)) + fnbody = expand_array_notation_exprs (fnbody); + } + tree fndecl = current_function_decl; if (nested) { tree decl = current_function_decl; @@ -2191,9 +2102,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, } else { - add_stmt (fnbody); + if (fnbody) + add_stmt (fnbody); finish_function (); } + /* Get rid of the empty stmt list for GIMPLE. */ + if (specs->gimple_p) + DECL_SAVED_TREE (fndecl) = NULL_TREE; timevar_pop (tv); break; @@ -2416,7 +2331,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) objc-protocol-refs */ -static void +void c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, bool scspec_ok, bool typespec_ok, bool start_attr_ok, bool alignspec_ok, bool auto_type_ok, @@ -2681,6 +2596,14 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, align = c_parser_alignas_specifier (parser); declspecs_add_alignas (loc, specs, align); break; + case RID_GIMPLE: + if (! flag_gimple) + error_at (loc, "%<__GIMPLE%> only valid with -fgimple"); + c_parser_consume_token (parser); + specs->gimple_p = true; + specs->locations[cdw_gimple] = loc; + specs->gimple_pass = c_parser_gimple_pass_list (parser); + break; default: goto out; } @@ -3415,7 +3338,7 @@ c_parser_alignas_specifier (c_parser * parser) This function also accepts an omitted abstract declarator as being an abstract declarator, although not part of the formal syntax. */ -static struct c_declarator * +struct c_declarator * c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, bool *seen_id) { @@ -4311,7 +4234,7 @@ c_parser_attributes (c_parser *parser) specifier-qualifier-list abstract-declarator[opt] */ -static struct c_type_name * +struct c_type_name * c_parser_type_name (c_parser *parser) { struct c_declspecs *specs = build_null_declspecs (); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index e8060f8b197..a8cf353eb4d 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -267,6 +267,7 @@ enum c_declspec_word { cdw_saturating, cdw_alignas, cdw_address_space, + cdw_gimple, cdw_number_of_elements /* This one must always be the last enumerator. */ }; @@ -290,6 +291,8 @@ struct c_declspecs { NULL; attributes (possibly from multiple lists) will be passed separately. */ tree attrs; + /* The pass to start compiling a __GIMPLE function with. */ + char *gimple_pass; /* The base-2 log of the greatest alignment required by an _Alignas specifier, in bytes, or -1 if no such specifiers with nonzero alignment. */ @@ -362,6 +365,8 @@ struct c_declspecs { /* Whether any alignment specifier (even with zero alignment) was specified. */ BOOL_BITFIELD alignas_p : 1; + /* Whether any __GIMPLE specifier was specified. */ + BOOL_BITFIELD gimple_p : 1; /* The address space that the declaration belongs to. */ addr_space_t address_space; }; diff --git a/gcc/c/config-lang.in b/gcc/c/config-lang.in index b9cdc8e66ce..51fbb5366d3 100644 --- a/gcc/c/config-lang.in +++ b/gcc/c/config-lang.in @@ -29,4 +29,4 @@ compilers="cc1\$(exeext)" target_libs= -gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h" +gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h" diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 0668d2bb9ee..8e2f46617b8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -179,7 +179,7 @@ in the following sections. @xref{C Dialect Options,,Options Controlling C Dialect}. @gccoptlist{-ansi -std=@var{standard} -fgnu89-inline @gol -aux-info @var{filename} -fallow-parameterless-variadic-functions @gol --fno-asm -fno-builtin -fno-builtin-@var{function} @gol +-fno-asm -fno-builtin -fno-builtin-@var{function} -fgimple@gol -fhosted -ffreestanding -fopenacc -fopenmp -fopenmp-simd @gol -fms-extensions -fplan9-extensions -fsso-struct=@var{endianness} -fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol @@ -1951,6 +1951,13 @@ built-in functions selectively when using @option{-fno-builtin} or #define strcpy(d, s) __builtin_strcpy ((d), (s)) @end smallexample +@item -fgimple +@opindex fgimple + +Enable parsing of function definitions marked with @code{__GIMPLE}. +This is an experimental feature that allows unit testing of GIMPLE +passes. + @item -fhosted @opindex fhosted @cindex hosted environment diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c index 74522a66fc0..e9483bc8d4d 100644 --- a/gcc/dumpfile.c +++ b/gcc/dumpfile.c @@ -108,13 +108,15 @@ static const struct dump_option_value_info dump_options[] = {"nouid", TDF_NOUID}, {"enumerate_locals", TDF_ENUMERATE_LOCALS}, {"scev", TDF_SCEV}, + {"gimple", TDF_GIMPLE}, {"optimized", MSG_OPTIMIZED_LOCATIONS}, {"missed", MSG_MISSED_OPTIMIZATION}, {"note", MSG_NOTE}, {"optall", MSG_ALL}, {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE - | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)}, + | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV + | TDF_GIMPLE)}, {NULL, 0} }; diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h index 3f08b162458..b7d70f2804b 100644 --- a/gcc/dumpfile.h +++ b/gcc/dumpfile.h @@ -82,9 +82,10 @@ enum tree_dump_index #define TDF_CSELIB (1 << 23) /* Dump cselib details. */ #define TDF_SCEV (1 << 24) /* Dump SCEV details. */ #define TDF_COMMENT (1 << 25) /* Dump lines with prefix ";;" */ -#define MSG_OPTIMIZED_LOCATIONS (1 << 26) /* -fopt-info optimized sources */ -#define MSG_MISSED_OPTIMIZATION (1 << 27) /* missed opportunities */ -#define MSG_NOTE (1 << 28) /* general optimization info */ +#define TDF_GIMPLE (1 << 26) /* Dump in GIMPLE FE syntax */ +#define MSG_OPTIMIZED_LOCATIONS (1 << 27) /* -fopt-info optimized sources */ +#define MSG_MISSED_OPTIMIZATION (1 << 28) /* missed opportunities */ +#define MSG_NOTE (1 << 29) /* general optimization info */ #define MSG_ALL (MSG_OPTIMIZED_LOCATIONS | MSG_MISSED_OPTIMIZATION \ | MSG_NOTE) diff --git a/gcc/function.h b/gcc/function.h index e854c7f1c99..b564f4533f2 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -234,6 +234,9 @@ struct GTY(()) function { /* The loops in this function. */ struct loops *x_current_loops; + /* Filled by the GIMPLE FE, pass to start compilation with. */ + char *pass_startwith; + /* The stack usage of this function. */ struct stack_usage *su; diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index f588f5e445e..82863260ac3 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -893,7 +893,10 @@ 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, ") <"); + if (flags & TDF_GIMPLE) + pp_string (buffer, ") {"); + else + pp_string (buffer, ") <"); } for (i = 0; i < gimple_switch_num_labels (gs); i++) @@ -904,9 +907,17 @@ 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, ", "); + { + if (flags & TDF_GIMPLE) + pp_string (buffer, "; "); + else + pp_string (buffer, ", "); + } } - pp_greater (buffer); + if (flags & TDF_GIMPLE) + pp_string (buffer, "; }"); + else + pp_greater (buffer); } @@ -962,12 +973,14 @@ 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, "%G <%T>", gs, label); else { dump_generic_node (buffer, label, spc, flags, false); pp_colon (buffer); } + if (flags & TDF_GIMPLE) + return; if (DECL_NONLOCAL (label)) pp_string (buffer, " [non-local]"); if ((flags & TDF_EH) && EH_LANDING_PAD_NR (label)) @@ -2039,21 +2052,44 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment, else { dump_generic_node (buffer, lhs, spc, flags, false); - pp_string (buffer, " = PHI <"); + if (flags & TDF_GIMPLE) + pp_string (buffer, " = __PHI ("); + else + 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)); + if (flags & TDF_GIMPLE) + { + basic_block src = gimple_phi_arg_edge (phi, i)->src; + gimple *stmt = first_stmt (src); + if (!stmt || gimple_code (stmt) != GIMPLE_LABEL) + { + pp_string (buffer, "bb_"); + pp_decimal_int (buffer, src->index); + } + else + dump_generic_node (buffer, gimple_label_label (as_a (stmt)), 0, flags, + false); + 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 (! (flags & TDF_GIMPLE)) + { + 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); + if (flags & TDF_GIMPLE) + pp_string (buffer, ");"); + else + pp_greater (buffer); } @@ -2502,7 +2538,12 @@ 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:\n", indent, "", bb->index); + { + if (flags & TDF_GIMPLE) + fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index); + else + fprintf (outf, "%*s:\n", indent, "", bb->index); + } } } @@ -2535,7 +2576,8 @@ 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 & TDF_GIMPLE) ? false : true, flags); pp_newline (buffer); } } @@ -2546,26 +2588,32 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags) to BUFFER. */ static void -pp_cfg_jump (pretty_printer *buffer, basic_block bb) +pp_cfg_jump (pretty_printer *buffer, basic_block bb, int flags) { - gimple *stmt; - - stmt = first_stmt (bb); - - pp_string (buffer, "goto index); - pp_greater (buffer); - if (stmt && gimple_code (stmt) == GIMPLE_LABEL) + if (flags & TDF_GIMPLE) { - pp_string (buffer, " ("); - dump_generic_node (buffer, - gimple_label_label (as_a (stmt)), - 0, 0, false); - pp_right_paren (buffer); + pp_string (buffer, "goto bb_"); + pp_decimal_int (buffer, bb->index); pp_semicolon (buffer); } else - pp_semicolon (buffer); + { + gimple *stmt = first_stmt (bb); + pp_string (buffer, "goto index); + pp_greater (buffer); + if (stmt && gimple_code (stmt) == GIMPLE_LABEL) + { + pp_string (buffer, " ("); + dump_generic_node (buffer, + gimple_label_label (as_a (stmt)), + 0, 0, false); + pp_right_paren (buffer); + pp_semicolon (buffer); + } + else + pp_semicolon (buffer); + } } @@ -2593,11 +2641,11 @@ dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent, extract_true_false_edges_from_block (bb, &true_edge, &false_edge); INDENT (indent + 2); - pp_cfg_jump (buffer, true_edge->dest); + pp_cfg_jump (buffer, true_edge->dest, flags); newline_and_indent (buffer, indent); pp_string (buffer, "else"); newline_and_indent (buffer, indent + 2); - pp_cfg_jump (buffer, false_edge->dest); + pp_cfg_jump (buffer, false_edge->dest, flags); pp_newline (buffer); return; } @@ -2614,7 +2662,7 @@ dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent, && e->goto_locus != UNKNOWN_LOCATION) dump_location (buffer, e->goto_locus); - pp_cfg_jump (buffer, e->dest); + pp_cfg_jump (buffer, e->dest, flags); pp_newline (buffer); } } diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index cbee97ea82c..08755594db1 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -2505,3 +2505,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 0869b2fd52d..d1cd1a55b8f 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -170,6 +170,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 4e5dbaa79d4..672a60f0619 100644 --- a/gcc/internal-fn.h +++ b/gcc/internal-fn.h @@ -178,5 +178,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/objc/ChangeLog b/gcc/objc/ChangeLog index 74dda97e39c..4963e812fe4 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2016-11-14 Prasad Ghangal + Richard Biener + + * config-lang.in (gtfiles): Add c/c-parser.h. + 2016-09-27 Jakub Jelinek * objc-act.c (continue_class): Remove break after return. diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in index f5a74a7d173..912af224b00 100644 --- a/gcc/objc/config-lang.in +++ b/gcc/objc/config-lang.in @@ -35,4 +35,4 @@ lang_requires="c" # Order is important. If you change this list, make sure you test # building without C++ as well; that is, remove the gcc/cp directory, # and build with --enable-languages=c,objc. -gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c" +gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c" diff --git a/gcc/passes.c b/gcc/passes.c index e78f9ed79af..51d0d84b74d 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -2099,7 +2099,7 @@ pass_init_dump_file (opt_pass *pass) release_dump_file_name (); dump_file_name = dumps->get_dump_file_name (pass->static_pass_number); dumps->dump_start (pass->static_pass_number, &dump_flags); - if (dump_file && current_function_decl) + if (dump_file && current_function_decl && ! (dump_flags & TDF_GIMPLE)) dump_function_header (dump_file, current_function_decl, dump_flags); if (initializing_dump && dump_file && (dump_flags & TDF_GRAPH) @@ -2313,6 +2313,35 @@ execute_one_pass (opt_pass *pass) return false; } + /* For skipping passes until startwith pass */ + if (cfun + && cfun->pass_startwith + /* But we can't skip the lowering phase yet -- ideally we'd + drive that phase fully via properties. */ + && (cfun->curr_properties & PROP_ssa)) + { + size_t namelen = strlen (pass->name); + if (! strncmp (pass->name, cfun->pass_startwith, namelen)) + { + /* The following supports starting with the Nth invocation + of a pass (where N does not necessarily is equal to the + dump file suffix). */ + if (cfun->pass_startwith[namelen] == '\0' + || (cfun->pass_startwith[namelen] == '1' + && cfun->pass_startwith[namelen + 1] == '\0')) + cfun->pass_startwith = NULL; + else + { + if (cfun->pass_startwith[namelen + 1] != '\0') + return true; + --cfun->pass_startwith[namelen]; + return true; + } + } + else + return true; + } + /* Pass execution event trigger: useful to identify passes being executed. */ invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass); @@ -2428,7 +2457,7 @@ execute_pass_list_1 (opt_pass *pass) if (cfun == NULL) return; if (execute_one_pass (pass) && pass->sub) - execute_pass_list_1 (pass->sub); + execute_pass_list_1 (pass->sub); pass = pass->next; } while (pass); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c47c8b2af5c..e9485591659 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,25 @@ +2016-11-14 Prasad Ghangal + Richard Biener + + * 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. + * gcc.dg/gimplefe-14.c: Likewise. + * gcc.dg/gimplefe-15.c: Likewise. + * gcc.dg/gimplefe-16.c: Likewise. + * gcc.dg/gimplefe-17.c: Likewise. + * gcc.dg/gimplefe-18.c: Likewise. + 2016-11-14 Martin Liska PR bootstrap/78069 diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index dfa82aaef73..e99e1022b6c 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 (13); make_edges (); assign_discriminators (); + lower_phi_internal_fn (); cleanup_dead_labels (); delete discriminator_per_locus; discriminator_per_locus = NULL; @@ -345,6 +347,49 @@ 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);) + { + stmt = gsi_stmt (gsi); + if (! gimple_call_internal_p (stmt, IFN_PHI)) + { + gsi_next (&gsi); + continue; + } + + lhs = gimple_call_lhs (stmt); + phi_node = create_phi_node (lhs, bb); + + /* Add arguments to the PHI node. */ + for (unsigned 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); + } + } + + gsi_remove (&gsi, true); + } + } +} static unsigned int execute_build_cfg (void) @@ -3337,6 +3382,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 { @@ -7497,7 +7547,14 @@ dump_function_to_file (tree fndecl, FILE *file, int flags) } current_function_decl = fndecl; - fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : ""); + if (flags & TDF_GIMPLE) + { + print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), + dump_flags | TDF_SLIM); + fprintf (file, " __GIMPLE ()\n%s (", function_name (fun)); + } + else + fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : ""); arg = DECL_ARGUMENTS (fndecl); while (arg) @@ -7609,7 +7666,7 @@ dump_function_to_file (tree fndecl, FILE *file, int flags) fprintf (file, "}\n"); } - else if (DECL_SAVED_TREE (fndecl) == NULL) + else if (fun->curr_properties & PROP_gimple_any) { /* The function is now in GIMPLE form but the CFG has not been built yet. Emit the single sequence of GIMPLE statements diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c index e5b59a7a29f..0e7884519d6 100644 --- a/gcc/tree-into-ssa.c +++ b/gcc/tree-into-ssa.c @@ -1378,12 +1378,20 @@ 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 (via the GIMPLE FE) its args may + be different vars than existing vars and they may be constants + as well. Note the following supports partial SSA for PHI args. */ + argvar = gimple_phi_arg_def (phi, e->dest_idx); + if (argvar && ! DECL_P (argvar)) + 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-pretty-print.c b/gcc/tree-pretty-print.c index ebbf606ff8b..096eefdd4f6 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -257,10 +257,11 @@ dump_decl_name (pretty_printer *pp, tree node, int flags) else pp_tree_identifier (pp, DECL_NAME (node)); } + char uid_sep = (flags & TDF_GIMPLE) ? '_' : '.'; 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%c%d", uid_sep, (int) LABEL_DECL_UID (node)); else if (TREE_CODE (node) == DEBUG_EXPR_DECL) { if (flags & TDF_NOUID) @@ -274,7 +275,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%c%u", c, uid_sep, DECL_UID (node)); } } if ((flags & TDF_ALIAS) && DECL_PT_UID (node) != DECL_UID (node)) @@ -1762,13 +1763,23 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, int flags, if (DECL_NAME (node)) dump_decl_name (pp, node, flags); else if (LABEL_DECL_UID (node) != -1) - pp_printf (pp, "", (int) LABEL_DECL_UID (node)); + { + if (flags & TDF_GIMPLE) + pp_printf (pp, "L%d", (int) LABEL_DECL_UID (node)); + else + pp_printf (pp, "", (int) LABEL_DECL_UID (node)); + } else { if (flags & TDF_NOUID) pp_string (pp, ""); else - pp_printf (pp, "", DECL_UID (node)); + { + if (flags & TDF_GIMPLE) + pp_printf (pp, "", DECL_UID (node)); + else + pp_printf (pp, "", DECL_UID (node)); + } } break; @@ -2695,7 +2706,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, int flags, && SSA_NAME_VAR (node) && DECL_NAMELESS (SSA_NAME_VAR (node))) dump_fancy_name (pp, SSA_NAME_IDENTIFIER (node)); - else + else if (! (flags & TDF_GIMPLE) + || SSA_NAME_VAR (node)) dump_generic_node (pp, SSA_NAME_IDENTIFIER (node), spc, flags, false); } diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 913d142f046..bd5d10ab28b 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -252,10 +252,12 @@ flush_ssaname_freelist (void) /* Return an SSA_NAME node for variable VAR defined in statement STMT in function FN. STMT may be an empty statement for artificial references (e.g., default definitions created when a variable is - used without a preceding definition). */ + used without a preceding definition). If VERISON is not zero then + allocate the SSA name with that version. */ 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 +267,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))); + /* Get the specified SSA name version. */ + 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 d39cc9d4e27..57e887ec7ae 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -78,7 +78,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 *); -- 2.30.2