diff mbox

Fix PR 57662

Message ID 52EF873B.9090405@ispras.ru
State New
Headers show

Commit Message

Andrey Belevantsev Feb. 3, 2014, 12:10 p.m. UTC
Hello,

On 14.08.2013 17:12, Andrey Belevantsev wrote:
> Hello,
>
> As noted in Bugzilla, the problem is this PR is the rare case of removing
> the unconditional jump that is used for traversing CFG when simplifying
> control flow.  We rescan the remaining successors when we know the flow
> below the current point has changed, and when we have removed the jump we
> are currently on, we segfault.  The fix is just to break out of successor
> iterator loop as in the unconditional jump case we have already visited the
> only successor.

I've recently found another test case for this PR which exhibits the 
segfault in the other spot of the CFG traversal driver -- we try to mark 
the basic block as visited when it is already gone.  Fixed with the below 
patch, the test was reduced as much as multidelta could.  Bootstrapped and 
tested on ia64, committed to trunk.

Yours,
Andrey

gcc/
         PR rtl-optimization/57662
         * sel-sched.c (code_motion_path_driver): Do not mark already not
         existing blocks in the visiting bitmap.

testsuite/
         PR rtl-optimization/57662
         * g++.dg/pr57662.C: New test.


>
> Bootstrapped and tested on x86-64, ok for trunk?  If yes, Alexander, could
> you please commit this for me?
>
> Andrey
>
> 2013-08-14  Andrey Belevantsev  <abel@ispras.ru>
>
> PR rtl-optimization/57662
>
> gcc/
>      * sel-sched.c (code_motion_process_successors): When the current insn
>      is removed after the recursive traversal, break from the loop.
>      Add comments and debug printouts.
>
> testsuite/
>
>      * gcc.dg/pr57662.c: New test.
>
diff mbox

Patch

Index: gcc/ChangeLog
===================================================================
*** gcc/ChangeLog	(revision 207420)
--- gcc/ChangeLog	(revision 207422)
***************
*** 1,5 ****
--- 1,11 ----
  2014-02-03  Andrey Belevantsev  <abel@ispras.ru>
  
+ 	PR rtl-optimization/57662
+ 	* sel-sched.c (code_motion_path_driver): Do not mark already not
+ 	existing blocks in the visiting bitmap.
+ 
+ 2014-02-03  Andrey Belevantsev  <abel@ispras.ru>
+ 
  	* sel-sched-ir.c (sel_gen_insn_from_expr_after): Reset INSN_DELETED_P
  	on the insn being emitted.
  
Index: gcc/testsuite/ChangeLog
===================================================================
*** gcc/testsuite/ChangeLog	(revision 207420)
--- gcc/testsuite/ChangeLog	(revision 207422)
***************
*** 1,3 ****
--- 1,8 ----
+ 2014-02-03  Andrey Belevantsev  <abel@ispras.ru>
+ 
+ 	PR rtl-optimization/57662
+ 	* g++.dg/pr57662.C: New test.
+ 
  2014-02-02  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
  
  	* gcc.dg/vmx/3b-15.c: Remove special handling for little endian.
Index: gcc/testsuite/g++.dg/pr57662.C
===================================================================
*** gcc/testsuite/g++.dg/pr57662.C	(revision 0)
--- gcc/testsuite/g++.dg/pr57662.C	(revision 207422)
***************
*** 0 ****
--- 1,339 ----
+ /* { dg-do compile { target powerpc*-*-* ia64-*-* x86_64-*-* } } */
+ /* { dg-options "-O2 -fselective-scheduling2 -fsel-sched-pipelining" } */
+ 
+ extern "C" {
+ 	typedef struct _IO_FILE FILE;
+ 	extern int putc(int __c, FILE * __stream);
+ 	extern int strcmp(__const char *__s1, __const char *__s2) throw()
+ 	    __attribute__ ((__pure__)) __attribute__ ((__nonnull__(1, 2)));
+ } typedef union tree_node *tree;
+ struct gcc_options {
+ 	int x_flag_openmp;
+ };
+ extern struct gcc_options global_options;
+ struct ht_identifier {
+ 	const unsigned char *str;
+ };
+ enum cpp_ttype {
+ 	CPP_SEMICOLON, CPP_NAME
+ };
+ struct vl_embed {
+ };
+ struct va_heap {
+ };
+ struct va_gc {
+ 	typedef vl_embed default_layout;
+ };
+ template < typename T, typename A = va_heap, typename L =
+     typename A::default_layout > struct vec {
+ };
+ enum tree_code {
+ 	ERROR_MARK,
+ 	IDENTIFIER_NODE,
+ 	OMP_SIMD,
+ 	CILK_SIMD,
+ 	MAX_TREE_CODES
+ };
+ struct tree_identifier {
+ 	struct ht_identifier
+ 	 id;
+ };
+ union tree_node {
+ 	struct tree_identifier
+ 	 identifier;
+ };
+ inline tree
+ tree_check(tree __t, const char *__f, int __l, const char *__g, tree_code __c)
+ {
+ }
+ 
+ extern tree chainon(tree, tree);
+ extern vec < tree, va_gc > *make_tree_vector(void);
+ typedef unsigned long omp_clause_mask;
+ enum c_omp_clause_split {
+ 	C_OMP_CLAUSE_SPLIT_TARGET = 0, C_OMP_CLAUSE_SPLIT_COUNT
+ };
+ typedef struct cxx_saved_binding {
+ 	tree attributes;
+ } cp_decl_specifier_seq;
+ typedef enum pragma_kind {
+ 	PRAGMA_NONE = 0, PRAGMA_OMP_DECLARE_REDUCTION, PRAGMA_OMP_TARGET
+ } pragma_kind;
+ typedef enum pragma_omp_clause {
+ 	PRAGMA_OMP_CLAUSE_NONE =
+ 	    0, PRAGMA_OMP_CLAUSE_DEVICE, PRAGMA_OMP_CLAUSE_IF,
+ 	    PRAGMA_OMP_CLAUSE_MAP
+ } pragma_omp_clause;
+ typedef struct cp_token {
+ 	enum cpp_ttype type:8;
+ 	union cp_token_value {
+ 		tree value;
+ 	} u;
+ } cp_token;
+ typedef struct cp_token *cp_token_position;
+ typedef struct cp_lexer {
+ 	cp_token_position next_token;
+ 	bool debugging_p;
+ 	cp_lexer *lexer;
+ } cp_parser;
+ static FILE *cp_lexer_debug_stream;
+ static inline bool cp_lexer_debugging_p(cp_lexer * lexer)
+ {
+ 	return lexer->debugging_p;
+ }
+ 
+ static inline cp_token *cp_lexer_peek_token(cp_lexer * lexer)
+ {
+ 	if (cp_lexer_debugging_p(lexer)) {
+ 		putc('\n', cp_lexer_debug_stream);
+ 	}
+ 	return lexer->next_token;
+ }
+ 
+ static inline bool cp_lexer_next_token_is(cp_lexer * lexer, enum cpp_ttype type)
+ {
+ }
+ 
+ enum {
+ 	CP_PARSER_FLAGS_NONE = 0x0, CP_PARSER_FLAGS_OPTIONAL =
+ 	    0x1, CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES =
+ 	    0x2, CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS =
+ 	    0x4, CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8
+ };
+ typedef int cp_parser_flags;
+ extern tree
+ cp_parser_type_specifier(cp_parser *, cp_parser_flags,
+ 			 cp_decl_specifier_seq *, bool, int *, bool *);
+ static void
+ cp_parser_type_specifier_seq(cp_parser *, bool, bool, cp_decl_specifier_seq *);
+ extern bool cp_next_tokens_can_be_attribute_p(cp_parser *);
+ extern tree cp_parser_attributes_opt(cp_parser *);
+ enum pragma_context {
+ 	pragma_external,
+ 	pragma_member,
+ 	pragma_objc_icode,
+ 	pragma_stmt,
+ 	pragma_compound
+ };
+ static bool cp_parser_pragma(cp_parser *, enum pragma_context);
+ static bool cp_parser_translation_unit(cp_parser * parser)
+ {
+ 	while (true) {
+ 		cp_token *token;
+ 		if (token->type == CPP_SEMICOLON) {
+ 			cp_parser_pragma(parser, pragma_external);
+ 		}
+ 	}
+ }
+ 
+ static tree
+ cp_parser_type_id_1(cp_parser * parser, bool is_template_arg,
+ 		    bool is_trailing_return)
+ {
+ 	cp_decl_specifier_seq type_specifier_seq;
+ 	cp_parser_type_specifier_seq(parser, false, is_trailing_return,
+ 				     &type_specifier_seq);
+ }
+ 
+ static tree cp_parser_type_id(cp_parser * parser)
+ {
+ 	return cp_parser_type_id_1(parser, false, false);
+ }
+ 
+ static void
+ cp_parser_type_specifier_seq(cp_parser * parser, bool is_declaration,
+ 			     bool is_trailing_return,
+ 			     cp_decl_specifier_seq * type_specifier_seq)
+ {
+ 	cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
+ 	cp_token *start_token = __null;
+ 	while (true) {
+ 		tree type_specifier;
+ 		bool is_cv_qualifier;
+ 		if (cp_next_tokens_can_be_attribute_p(parser)) {
+ 			type_specifier_seq->attributes =
+ 			    chainon(type_specifier_seq->attributes,
+ 				    cp_parser_attributes_opt(parser));
+ 			continue;
+ 		}
+ 		if (!start_token)
+ 			start_token = cp_lexer_peek_token(parser->lexer);
+ 		type_specifier =
+ 		    cp_parser_type_specifier(parser, flags, type_specifier_seq,
+ 					     false, __null, &is_cv_qualifier);
+ 		if (!type_specifier) {
+ 			break;
+ 		}
+ 		if (is_declaration && !is_cv_qualifier)
+ 			flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
+ 	}
+ }
+ 
+ static bool
+ cp_parser_omp_for_loop_init(cp_parser * parser, bool parsing_openmp,
+ 			    tree & this_pre_body, vec < tree,
+ 			    va_gc > *for_block, tree & init, tree & decl,
+ 			    tree & real_decl)
+ {
+ 	cp_decl_specifier_seq type_specifiers;
+ 	cp_parser_type_specifier_seq(parser, true, false, &type_specifiers);
+ }
+ 
+ static tree
+ cp_parser_omp_for_loop(cp_parser * parser, enum tree_code code, tree clauses,
+ 		       tree * cclauses)
+ {
+ 	tree init, cond, incr, body, decl, pre_body = (tree) __null, ret;
+ 	tree real_decl, initv, condv, incrv, declv;
+ 	tree this_pre_body, cl;
+ 	int i, collapse = 1, nbraces = 0;
+ 	vec < tree, va_gc > *for_block = make_tree_vector();
+ 	for (i = 0; i < collapse; i++) {
+ 		bool add_private_clause = false;
+ 		add_private_clause |=
+ 		    cp_parser_omp_for_loop_init(parser, code != CILK_SIMD,
+ 						this_pre_body, for_block, init,
+ 						decl, real_decl);
+ 	}
+ }
+ 
+ static tree
+ cp_parser_omp_simd(cp_parser * parser, cp_token * pragma_tok, char *p_name,
+ 		   omp_clause_mask mask, tree * cclauses)
+ {
+ 	tree clauses, sb, ret;
+ 	ret = cp_parser_omp_for_loop(parser, OMP_SIMD, clauses, cclauses);
+ }
+ 
+ static tree
+ cp_parser_omp_distribute(cp_parser * parser, cp_token * pragma_tok,
+ 			 char *p_name, omp_clause_mask mask, tree * cclauses)
+ {
+ 	if (cp_lexer_next_token_is(parser->lexer, CPP_NAME)) {
+ 		tree id = cp_lexer_peek_token(parser->lexer)->u.value;
+ 		const char *p =
+ 		    ((const char
+ 		      *)(tree_check((id),
+ 				    "/home/bonzo/develop/trunk/gcc/cp/parser.c",
+ 				    29966, __FUNCTION__,
+ 				    (IDENTIFIER_NODE)))->identifier.id.str);
+ 		bool simd = false;
+ 		bool parallel = false;
+ 		if (strcmp(p, "simd") == 0)
+ 			simd = true;
+ 		if (parallel || simd) {
+ 			if (!global_options.x_flag_openmp) {
+ 				if (simd)
+ 					return cp_parser_omp_simd(parser,
+ 								  pragma_tok,
+ 								  p_name, mask,
+ 								  cclauses);
+ 			}
+ 		}
+ 	}
+ }
+ 
+ static tree
+ cp_parser_omp_teams(cp_parser * parser, cp_token * pragma_tok, char *p_name,
+ 		    omp_clause_mask mask, tree * cclauses)
+ {
+ 	if (cp_lexer_next_token_is(parser->lexer, CPP_NAME)) {
+ 		tree id = cp_lexer_peek_token(parser->lexer)->u.value;
+ 		const char *p =
+ 		    ((const char
+ 		      *)(tree_check((id),
+ 				    "/home/bonzo/develop/trunk/gcc/cp/parser.c",
+ 				    30062, __FUNCTION__,
+ 				    (IDENTIFIER_NODE)))->identifier.id.str);
+ 		if (strcmp(p, "distribute") == 0) {
+ 			if (!global_options.x_flag_openmp)
+ 				return cp_parser_omp_distribute(parser,
+ 								pragma_tok,
+ 								p_name, mask,
+ 								cclauses);
+ 		}
+ 	}
+ }
+ 
+ static bool
+ cp_parser_omp_target(cp_parser * parser, cp_token * pragma_tok,
+ 		     enum pragma_context context)
+ {
+ 	if (context != pragma_stmt && context != pragma_compound) {
+ 		tree id = cp_lexer_peek_token(parser->lexer)->u.value;
+ 		const char *p =
+ 		    ((const char
+ 		      *)(tree_check((id),
+ 				    "/home/bonzo/develop/trunk/gcc/cp/parser.c",
+ 				    30201, __FUNCTION__,
+ 				    (IDENTIFIER_NODE)))->identifier.id.str);
+ 		if (strcmp(p, "teams") == 0) {
+ 			tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
+ 			char p_name[sizeof
+ 				    ("#pragma omp target teams distribute "
+ 				     "parallel for simd")];
+ 			if (!global_options.x_flag_openmp)
+ 				return cp_parser_omp_teams(parser, pragma_tok,
+ 							   p_name,
+ 							   ((((omp_clause_mask)
+ 							      1) <<
+ 							     PRAGMA_OMP_CLAUSE_DEVICE)
+ 							    |
+ 							    (((omp_clause_mask)
+ 							      1) <<
+ 							     PRAGMA_OMP_CLAUSE_MAP)
+ 							    |
+ 							    (((omp_clause_mask)
+ 							      1) <<
+ 							     PRAGMA_OMP_CLAUSE_IF)),
+ 							   cclauses);
+ 		}
+ 	}
+ }
+ 
+ static void
+ cp_parser_omp_declare_reduction(cp_parser * parser, cp_token * pragma_tok,
+ 				enum pragma_context)
+ {
+ 	tree reduc_id = (tree) __null, orig_reduc_id = (tree) __null, type;
+ 	while (true) {
+ 		type = cp_parser_type_id(parser);
+ 	}
+ }
+ 
+ static void
+ cp_parser_omp_declare(cp_parser * parser, cp_token * pragma_tok,
+ 		      enum pragma_context context)
+ {
+ 	if (cp_lexer_next_token_is(parser->lexer, CPP_NAME)) {
+ 		tree id = cp_lexer_peek_token(parser->lexer)->u.value;
+ 		const char *p =
+ 		    ((const char
+ 		      *)(tree_check((id),
+ 				    "/home/bonzo/develop/trunk/gcc/cp/parser.c",
+ 				    30883, __FUNCTION__,
+ 				    (IDENTIFIER_NODE)))->identifier.id.str);
+ 		if (strcmp(p, "simd") == 0) {
+ 			cp_parser_omp_declare_reduction(parser, pragma_tok,
+ 							context);
+ 		}
+ 	}
+ }
+ 
+ static cp_parser *the_parser;
+ static bool cp_parser_pragma(cp_parser * parser, enum pragma_context context)
+ {
+ 	cp_token *pragma_tok;
+ 	unsigned int id;
+ 	switch (id) {
+ 	case PRAGMA_OMP_DECLARE_REDUCTION:
+ 		cp_parser_omp_declare(parser, pragma_tok, context);
+ 	case PRAGMA_OMP_TARGET:
+ 		return cp_parser_omp_target(parser, pragma_tok, context);
+ 	}
+ }
+ 
+ void c_parse_file(void)
+ {
+ 	cp_parser_translation_unit(the_parser);
+ }
Index: gcc/sel-sched.c
===================================================================
*** gcc/sel-sched.c	(revision 207420)
--- gcc/sel-sched.c	(revision 207422)
*************** code_motion_path_driver (insn_t insn, av
*** 6741,6747 ****
       the numbering by creating bookkeeping blocks.  */
    if (removed_last_insn)
      insn = PREV_INSN (insn);
!   bitmap_set_bit (code_motion_visited_blocks, BLOCK_FOR_INSN (insn)->index);
    return true;
  }
  
--- 6741,6751 ----
       the numbering by creating bookkeeping blocks.  */
    if (removed_last_insn)
      insn = PREV_INSN (insn);
! 
!   /* If we have simplified the control flow and removed the first jump insn,
!      there's no point in marking this block in the visited blocks bitmap.  */
!   if (BLOCK_FOR_INSN (insn))
!     bitmap_set_bit (code_motion_visited_blocks, BLOCK_FOR_INSN (insn)->index);
    return true;
  }