This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Make reload CFG transparent


Hi,
this patch complettes my effort to get CFG from flow1 at bb_reorder and updates
reload to preserve CFG.  Reload had unfinished code to do so, so it purely adds
the missing bits.  I've also moved from BB indexes to pointers and removed few
other obsurities, that made the patch somewhat longish.

Bootstrapped/regtested i686; PPC/MIPS in progress.

Čt čec 26 00:31:33 CEST 2001  Jan Hubicka  <jh@suse.cz>

	* caller-save.c (insert_one_insn): Set block for chain properly;
	update for new CFG.
	* global.c (build_insn_chain): Use new CFG datastructure.
	* reload.h (struct insn_chain): block is basic_block instead of int.
	* reload1.c (delete_caller_save_insns): Update for new CFG datastructure.
	(emit_reload_insns): Likewise.
	* toplev.c (rest_of_compilation):  Avoid CFG rebuild after reload;
	call compute_bb_for_insn instead and verify_flow_info.

*** caller-save.c.nor	Thu Jul 26 00:22:03 2001
--- caller-save.c	Thu Jul 26 00:26:20 2001
*************** insert_one_insn (chain, before_p, code, 
*** 807,813 ****
  
        chain->prev = new;
        new->next = chain;
!       new->insn = emit_insn_before (pat, insn);
        /* ??? It would be nice if we could exclude the already / still saved
  	 registers from the live sets.  */
        COPY_REG_SET (&new->live_throughout, &chain->live_throughout);
--- 807,814 ----
  
        chain->prev = new;
        new->next = chain;
!       new->insn = emit_block_insn_before (pat, insn, chain->block);
!       new->block = chain->block;
        /* ??? It would be nice if we could exclude the already / still saved
  	 registers from the live sets.  */
        COPY_REG_SET (&new->live_throughout, &chain->live_throughout);
*************** insert_one_insn (chain, before_p, code, 
*** 833,840 ****
  	    }
  	}
        CLEAR_REG_SET (&new->dead_or_set);
!       if (chain->insn == BLOCK_HEAD (chain->block))
! 	BLOCK_HEAD (chain->block) = new->insn;
      }
    else
      {
--- 834,841 ----
  	    }
  	}
        CLEAR_REG_SET (&new->dead_or_set);
!       if (chain->insn == chain->block->head)
! 	chain->block->head = new->insn;
      }
    else
      {
*************** insert_one_insn (chain, before_p, code, 
*** 843,849 ****
  	new->next->prev = new;
        chain->next = new;
        new->prev = chain;
!       new->insn = emit_insn_after (pat, insn);
        /* ??? It would be nice if we could exclude the already / still saved
  	 registers from the live sets, and observe REG_UNUSED notes.  */
        COPY_REG_SET (&new->live_throughout, &chain->live_throughout);
--- 844,851 ----
  	new->next->prev = new;
        chain->next = new;
        new->prev = chain;
!       new->insn = emit_block_insn_after (pat, insn, chain->block);
!       new->block = chain->block;
        /* ??? It would be nice if we could exclude the already / still saved
  	 registers from the live sets, and observe REG_UNUSED notes.  */
        COPY_REG_SET (&new->live_throughout, &chain->live_throughout);
*************** insert_one_insn (chain, before_p, code, 
*** 853,860 ****
        note_stores (PATTERN (chain->insn), add_stored_regs,
  		   &new->live_throughout);
        CLEAR_REG_SET (&new->dead_or_set);
!       if (chain->insn == BLOCK_END (chain->block))
! 	BLOCK_END (chain->block) = new->insn;
      }
    new->block = chain->block;
    new->is_caller_save_insn = 1;
--- 855,862 ----
        note_stores (PATTERN (chain->insn), add_stored_regs,
  		   &new->live_throughout);
        CLEAR_REG_SET (&new->dead_or_set);
!       if (chain->insn == chain->block->end)
! 	chain->block->end = new->insn;
      }
    new->block = chain->block;
    new->is_caller_save_insn = 1;
*** global.c.nor	Thu Jul 26 00:21:46 2001
--- global.c	Thu Jul 26 00:21:58 2001
*************** build_insn_chain (first)
*** 1785,1805 ****
    struct insn_chain *prev = 0;
    int b = 0;
    regset_head live_relevant_regs_head;
  
    live_relevant_regs = INITIALIZE_REG_SET (live_relevant_regs_head);
  
!   for (; first; first = NEXT_INSN (first))
      {
        struct insn_chain *c;
  
!       if (first == BLOCK_HEAD (b))
  	{
  	  int i;
  
  	  CLEAR_REG_SET (live_relevant_regs);
  
  	  EXECUTE_IF_SET_IN_BITMAP
! 	    (BASIC_BLOCK (b)->global_live_at_start, 0, i,
  	     {
  	       if (i < FIRST_PSEUDO_REGISTER
  		   ? ! TEST_HARD_REG_BIT (eliminable_regset, i)
--- 1785,1809 ----
    struct insn_chain *prev = 0;
    int b = 0;
    regset_head live_relevant_regs_head;
+   int i;
  
    live_relevant_regs = INITIALIZE_REG_SET (live_relevant_regs_head);
  
!   for (i=0 ; i < n_basic_blocks; i++)
!   {
! 	  basic_block b = BASIC_BLOCK (i);
!   for (first = b->head; first!=NEXT_INSN (b->end); first = NEXT_INSN (first))
      {
        struct insn_chain *c;
  
!       if (first == b->head)
  	{
  	  int i;
  
  	  CLEAR_REG_SET (live_relevant_regs);
  
  	  EXECUTE_IF_SET_IN_BITMAP
! 	    (b->global_live_at_start, 0, i,
  	     {
  	       if (i < FIRST_PSEUDO_REGISTER
  		   ? ! TEST_HARD_REG_BIT (eliminable_regset, i)
*************** build_insn_chain (first)
*** 1853,1881 ****
  			    c);
  	    }
  	}
- 
-       if (first == BLOCK_END (b))
- 	b++;
- 
-       /* Stop after we pass the end of the last basic block.  Verify that
- 	 no real insns are after the end of the last basic block.
- 
- 	 We may want to reorganize the loop somewhat since this test should
- 	 always be the right exit test.  Allow an ADDR_VEC or ADDR_DIF_VEC if
- 	 the previous real insn is a JUMP_INSN.  */
-       if (b == n_basic_blocks)
- 	{
- 	  for (first = NEXT_INSN (first) ; first; first = NEXT_INSN (first))
- 	    if (INSN_P (first)
- 		&& GET_CODE (PATTERN (first)) != USE
- 		&& ! ((GET_CODE (PATTERN (first)) == ADDR_VEC
- 		       || GET_CODE (PATTERN (first)) == ADDR_DIFF_VEC)
- 		      && prev_real_insn (first) != 0
- 		      && GET_CODE (prev_real_insn (first)) == JUMP_INSN))
- 	      abort ();
- 	  break;
- 	}
      }
    FREE_REG_SET (live_relevant_regs);
    *p = 0;
  }
--- 1857,1864 ----
  			    c);
  	    }
  	}
      }
+   }
    FREE_REG_SET (live_relevant_regs);
    *p = 0;
  }
*** reload.h.nor	Thu Jul 26 00:20:52 2001
--- reload.h	Thu Jul 26 00:25:31 2001
*************** struct needs
*** 207,213 ****
    short groups[N_REG_CLASSES];
  };
  
! #if defined SET_HARD_REG_BIT && defined CLEAR_REG_SET
  /* This structure describes instructions which are relevant for reload.
     Apart from all regular insns, this also includes CODE_LABELs, since they
     must be examined for register elimination.  */
--- 207,213 ----
    short groups[N_REG_CLASSES];
  };
  
! #if defined SET_HARD_REG_BIT && defined CLEAR_REG_SET && defined EXIT_BLOCK_PTR
  /* This structure describes instructions which are relevant for reload.
     Apart from all regular insns, this also includes CODE_LABELs, since they
     must be examined for register elimination.  */
*************** struct insn_chain 
*** 221,227 ****
    struct insn_chain *next_need_reload;
  
    /* The basic block this insn is in.  */
!   int block;
    /* The rtx of the insn.  */
    rtx insn;
    /* Register life information: record all live hard registers, and all
--- 221,227 ----
    struct insn_chain *next_need_reload;
  
    /* The basic block this insn is in.  */
!   basic_block block;
    /* The rtx of the insn.  */
    rtx insn;
    /* Register life information: record all live hard registers, and all
*** reload1.c.nor	Thu Jul 26 00:22:34 2001
--- reload1.c	Thu Jul 26 00:24:49 2001
*************** delete_caller_save_insns ()
*** 1855,1864 ****
  	  struct insn_chain *next = c->next;
  	  rtx insn = c->insn;
  
! 	  if (insn == BLOCK_HEAD (c->block))
! 	    BLOCK_HEAD (c->block) = NEXT_INSN (insn);
! 	  if (insn == BLOCK_END (c->block))
! 	    BLOCK_END (c->block) = PREV_INSN (insn);
  	  if (c == reload_insn_chain)
  	    reload_insn_chain = next;
  
--- 1856,1865 ----
  	  struct insn_chain *next = c->next;
  	  rtx insn = c->insn;
  
! 	  if (insn == c->block->head)
! 	    c->block->head = NEXT_INSN (insn);
! 	  if (insn == c->block->end)
! 	    c->block->end = PREV_INSN (insn);
  	  if (c == reload_insn_chain)
  	    reload_insn_chain = next;
  
*************** emit_reload_insns (chain)
*** 7029,7041 ****
      }
  
    /* Keep basic block info up to date.  */
!   if (n_basic_blocks)
!     {
!       if (BLOCK_HEAD (chain->block) == insn)
! 	BLOCK_HEAD (chain->block) = NEXT_INSN (before_insn);
!       if (BLOCK_END (chain->block) == insn)
! 	BLOCK_END (chain->block) = PREV_INSN (following_insn);
!     }
  
    /* For all the spill regs newly reloaded in this instruction,
       record what they were reloaded from, so subsequent instructions
--- 7032,7041 ----
      }
  
    /* Keep basic block info up to date.  */
!   if (chain->block->head == insn)
!     chain->block->head = NEXT_INSN (before_insn);
!   if (chain->block->end == insn)
!     chain->block->end = PREV_INSN (following_insn);
  
    /* For all the spill regs newly reloaded in this instruction,
       record what they were reloaded from, so subsequent instructions
*** toplev.c.nor	Thu Jul 26 00:29:00 2001
--- toplev.c	Thu Jul 26 00:30:36 2001
*************** rest_of_compilation (decl)
*** 3462,3468 ****
    timevar_push (TV_FLOW2);
    open_dump_file (DFI_flow2, decl);
  
!   find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
  
    /* If optimizing, then go ahead and split insns now.  */
    if (optimize > 0)
--- 3462,3473 ----
    timevar_push (TV_FLOW2);
    open_dump_file (DFI_flow2, decl);
  
!   /* We've generated the reload insns; update bb_for_insn and check CFG
!      for consistency.  */
!   compute_bb_for_insn (get_max_uid ());
! #ifdef ENABLE_CHECKING
!   verify_flow_info ();
! #endif
  
    /* If optimizing, then go ahead and split insns now.  */
    if (optimize > 0)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]