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]
Other format: [Raw text]

[hammer] Preprocess RTL in VRP


Hi,

this patch preprocesses RTL not to analyze RTL each time basic block is
scanned.

Bootstrapped/regtested x86-64 hammer branch.

OK?

Josef

2003-07-07  Josef Zlomek  <zlomekj@suse.cz>

	* vrp.c (enum oper_type): New type.
	(struct operation_def): New struct.
	(struct bb_info_def): Added element 'operation_list'.
	(operation_pool): New alloc pool.
	(compute_ranges_for_insn): Deleted.
	(find_operations_1): New function.
	(find_operations): New function.
	(compute_ranges_for_bb): Update ranges according to preprocessed RTL. 
	(value_range_propagation): Alloc operation_pool, preprocess RTL.

diff -c -3 -p -r1.1.2.2 vrp.c
*** vrp.c	19 Jun 2003 17:13:43 -0000	1.1.2.2
--- vrp.c	2 Jul 2003 14:54:17 -0000
*************** typedef struct range_def
*** 101,106 ****
--- 101,124 ----
  #define RANGE_SIGNED_INT	1	/* Signed integer.  */
  #define RANGE_UNSIGNED_INT	2	/* Unsigned integer.  */
  
+ /* Type of operation.  */
+ enum oper_type
+ {
+   CONST_INT_TO_REG,			/* REG <- CONST_INT.  */
+   REG_TO_REG,				/* REG <- REG.  */
+   UNKNOWN_TO_REG,			/* REG <- anything else.  */
+   CLOBBER_CALL_USED_REGS		/* CALL_INSN.  */
+ };
+ 
+ /* Information about operation.  */
+ typedef struct operation_def
+ {
+   enum oper_type type;
+   rtx dst;
+   rtx src;
+   struct operation_def *next;
+ } *operation;
+ 
  /* Data for each edge.  */
  typedef struct edge_info_def
  {
*************** typedef struct bb_info_def
*** 114,119 ****
--- 132,139 ----
    /* Normalized condition (if any) for the branch in the end of BB.  */
    rtx cond;
  
+   operation operation_list;
+ 
    /* The IN list of ranges of registers for BB.  */
    htab_t in;
  
*************** typedef struct bb_info_def
*** 130,135 ****
--- 150,158 ----
  /* Alloc pool for range_t.  */
  alloc_pool range_pool;
  
+ /* Alloc pool for operation.  */
+ alloc_pool operation_pool;
+ 
  /* Local function prototypes.  */
  static hashval_t range_hash		PARAMS ((const void *));
  static int range_eq			PARAMS ((const void *, const void *));
*************** static void process_ranges_eq		PARAMS ((
*** 147,153 ****
  static void process_ranges_lt		PARAMS ((rtx, rtx, edge, edge));
  static void process_ranges_ltu		PARAMS ((rtx, rtx, edge, edge));
  static bool update_outgoing_edges	PARAMS ((basic_block, int));
! static void compute_ranges_for_insn	PARAMS ((rtx, rtx, void *));
  static int delete_call_used_regs	PARAMS ((void **, void *));
  static bool compute_ranges_for_bb	PARAMS ((basic_block));
  static void compute_ranges_for_pending	PARAMS ((basic_block, sbitmap,
--- 170,177 ----
  static void process_ranges_lt		PARAMS ((rtx, rtx, edge, edge));
  static void process_ranges_ltu		PARAMS ((rtx, rtx, edge, edge));
  static bool update_outgoing_edges	PARAMS ((basic_block, int));
! static void find_operations_1		PARAMS ((rtx, rtx, void *));
! static void find_operations		PARAMS ((basic_block));
  static int delete_call_used_regs	PARAMS ((void **, void *));
  static bool compute_ranges_for_bb	PARAMS ((basic_block));
  static void compute_ranges_for_pending	PARAMS ((basic_block, sbitmap,
*************** update_outgoing_edges (bb, changed)
*** 1180,1289 ****
    return changed;
  }
  
! /* Compute the effect of set to STORE in insn PATTERN and update the ranges
!    in table DATA.  */
  
  static void
! compute_ranges_for_insn (store, pattern, data)
       rtx store;
       rtx pattern;
       void *data;
  {
!   htab_t htab = (htab_t) data;
    rtx set_src, set_dst;
!   void **slot;
!   range_t *dst_r, *src_r;
!   unsigned HOST_WIDE_INT mask;
  
    set_dst = SET_DEST (pattern);
    if (GET_CODE (store) == REG)
      {
        if (set_dst != store || GET_CODE (pattern) == CLOBBER)
  	{
! 	  /* SET_DST is a SUBREG, ZERO_EXTRACT, etc.
! 	     or we are clobbering the register.
! 	     We do not know the resulting range so delete the range
! 	     (i.e. make it to be a full range).  */
! 
! 	  slot = htab_find_slot_with_hash (htab, store, HASH_REG (store),
! 					   NO_INSERT);
! 	  if (slot)
! 	    htab_clear_slot (htab, slot);
  	  return;
  	}
  
-       mask = (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (set_dst));
        set_src = SET_SRC (pattern);
        switch (GET_CODE (set_src))
  	{
  	  case REG:
! 	    src_r = htab_find_with_hash (htab, set_src, HASH_REG (set_src));
! 	    if (src_r)
! 	      {
! 		/* Copy the range from SET_SRC to SET_DST.  */
! 		slot = htab_find_slot_with_hash (htab, set_dst,
! 						 HASH_REG (set_dst), NO_INSERT);
! 
! 		if (slot)
! 		  dst_r = *slot;
! 		else
! 		  {
! 		    dst_r = pool_alloc (range_pool);
! 		    slot = htab_find_slot_with_hash (htab, set_dst,
! 						     HASH_REG (set_dst),
! 						     INSERT);
! 		    *slot = dst_r;
! 		  }
! 
! 		*dst_r = *src_r;
! 		dst_r->reg = set_dst;
! 	      }
! 	    else
! 	      {
! 		/* SET_SRC has a full range.  */
! 		slot = htab_find_slot_with_hash (htab, set_dst,
! 						 HASH_REG (set_dst),
! 						 NO_INSERT);
! 		if (slot)
! 		  htab_clear_slot (htab, slot);
! 	      }
  	    return;
  
  	  case CONST_INT:
! 	    /* Set the range of SET_DST to be a single value.  */
! 	    slot = htab_find_slot_with_hash (htab, set_dst,
! 					     HASH_REG (set_dst), NO_INSERT);
! 	    if (slot)
! 	      dst_r = *slot;
! 	    else
! 	      {
! 		dst_r = pool_alloc (range_pool);
! 		slot = htab_find_slot_with_hash (htab, set_dst,
! 						 HASH_REG (set_dst), INSERT);
! 		*slot = dst_r;
! 	      }
! 
! 	    /* We do not know whether the constant is signed or unsigned.  */
! 	    dst_r->type = RANGE_SIGNED_INT | RANGE_UNSIGNED_INT;
! 	    dst_r->reg = set_dst;
! 	    dst_r->from.si = INTVAL (set_src);
! 	    dst_r->to.si = INTVAL (set_src);
! 	    dst_r->from.ui = (unsigned HOST_WIDE_INT) INTVAL (set_src) & mask;
! 	    dst_r->to.ui = (unsigned HOST_WIDE_INT) INTVAL (set_src) & mask;
  	    return;
  
  	  default:
! 	    /* We do not know how the range changes so make it to be
! 	       a full range.  */
! 	    slot = htab_find_slot_with_hash (htab, set_dst,
! 					     HASH_REG (set_dst), NO_INSERT);
! 	    if (slot)
! 	      htab_clear_slot (htab, slot);
  	    return;
  	}
      }
  }
  
  /* Set the range of register *SLOT to be a full range
     if the register is in CALL_USED_REG_SET (i.e. delete such a register from
     hash table DATA.  */
--- 1205,1300 ----
    return changed;
  }
  
! /* Find operations in a single insn pattern PATTERN and insert them to the link
!    list DATA->OPERATION_LIST.  STORE is the destination of the store.  */
  
  static void
! find_operations_1 (store, pattern, data)
       rtx store;
       rtx pattern;
       void *data;
  {
!   bb_info *bbi = data;
    rtx set_src, set_dst;
!   operation oper;
  
    set_dst = SET_DEST (pattern);
    if (GET_CODE (store) == REG)
      {
        if (set_dst != store || GET_CODE (pattern) == CLOBBER)
  	{
! 	  oper = pool_alloc (operation_pool);
! 	  oper->next = bbi->operation_list;
! 	  oper->type = UNKNOWN_TO_REG;
! 	  oper->dst = set_dst;
! 	  bbi->operation_list = oper;
  	  return;
  	}
  
        set_src = SET_SRC (pattern);
        switch (GET_CODE (set_src))
  	{
  	  case REG:
! 	    oper = pool_alloc (operation_pool);
! 	    oper->next = bbi->operation_list;
! 	    oper->type = REG_TO_REG;
! 	    oper->dst = set_dst;
! 	    oper->src = set_src;
! 	    bbi->operation_list = oper;
  	    return;
  
  	  case CONST_INT:
! 	    oper = pool_alloc (operation_pool);
! 	    oper->next = bbi->operation_list;
! 	    oper->type = CONST_INT_TO_REG;
! 	    oper->dst = set_dst;
! 	    oper->src = set_src;
! 	    bbi->operation_list = oper;
  	    return;
  
  	  default:
! 	    oper = pool_alloc (operation_pool);
! 	    oper->next = bbi->operation_list;
! 	    oper->type = UNKNOWN_TO_REG;
! 	    oper->dst = set_dst;
! 	    bbi->operation_list = oper;
  	    return;
  	}
      }
  }
  
+ /* Find operations in basic block BB and store it to the link list of
+    operations.  */
+ 
+ static void
+ find_operations (bb)
+      basic_block bb;
+ {
+   rtx insn;
+   operation oper;
+ 
+   /* Scan the insns from the end of BB to the beginning of BB because we are
+      adding the opeations to the head of the chain.  */
+   for (insn = bb->end; insn != PREV_INSN (bb->head); insn = PREV_INSN (insn))
+     {
+       if (INSN_P (insn))
+ 	{
+ 	  note_stores (PATTERN (insn), find_operations_1, BBI (bb));
+ 	}
+ 
+       if (GET_CODE (insn) == CALL_INSN)
+ 	{
+ 	  /* Set the range to be a full range for the registers
+ 	     which do not survive during the call.  */
+ 
+ 	  oper = pool_alloc (operation_pool);
+ 	  oper->next = BBI (bb)->operation_list;
+ 	  oper->type = CLOBBER_CALL_USED_REGS;
+ 	  BBI (bb)->operation_list = oper;
+ 	}
+     }
+ }
+ 
  /* Set the range of register *SLOT to be a full range
     if the register is in CALL_USED_REG_SET (i.e. delete such a register from
     hash table DATA.  */
*************** compute_ranges_for_bb (bb)
*** 1317,1339 ****
  {
    bool changed;
    htab_t new_out;
!   rtx insn;
  
    new_out = htab_create (BBI (bb)->in->n_elements, range_hash, range_eq,
  			 range_del);
    copy_register_table (new_out, BBI (bb)->in);
  
!   for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
      {
!       if (GET_CODE (insn) == CALL_INSN)
  	{
! 	  /* Set the range to be a full range for the registers
! 	     which do not survive during the call.  */
! 	  htab_traverse (new_out, delete_call_used_regs, new_out);
! 	}
!       if (INSN_P (insn))
! 	{
! 	  note_stores (PATTERN (insn), compute_ranges_for_insn, new_out);
  	}
      }
  
--- 1328,1417 ----
  {
    bool changed;
    htab_t new_out;
!   operation oper;
!   range_t *dst_r, *src_r;
!   unsigned HOST_WIDE_INT mask;
!   void **slot;
  
    new_out = htab_create (BBI (bb)->in->n_elements, range_hash, range_eq,
  			 range_del);
    copy_register_table (new_out, BBI (bb)->in);
  
!   for (oper = BBI (bb)->operation_list; oper; oper = oper->next)
      {
!       switch (oper->type)
  	{
! 
! 	  case CLOBBER_CALL_USED_REGS:
! 	    htab_traverse (new_out, delete_call_used_regs, new_out);
! 	    break;
! 
! 	  case UNKNOWN_TO_REG:
! 	    slot = htab_find_slot_with_hash (new_out, oper->dst,
! 					     HASH_REG (oper->dst), NO_INSERT);
! 	    if (slot)
! 	      htab_clear_slot (new_out, slot);
! 	    break;
! 
! 	  case REG_TO_REG:
! 	    src_r = htab_find_with_hash (new_out, oper->src,
! 					 HASH_REG (oper->src));
! 	    if (src_r)
! 	      {
! 		/* Copy the range from SET_SRC to SET_DST.  */
! 		slot = htab_find_slot_with_hash (new_out, oper->dst,
! 						 HASH_REG (oper->dst),
! 						 NO_INSERT);
! 
! 		if (slot)
! 		  dst_r = *slot;
! 		else
! 		  {
! 		    dst_r = pool_alloc (range_pool);
! 		    slot = htab_find_slot_with_hash (new_out, oper->dst,
! 						     HASH_REG (oper->dst),
! 						     INSERT);
! 		    *slot = dst_r;
! 		  }
! 
! 		*dst_r = *src_r;
! 		dst_r->reg = oper->dst;
! 	      }
! 	    else
! 	      {
! 		/* SET_SRC has a full range.  */
! 		slot = htab_find_slot_with_hash (new_out, oper->dst,
! 						 HASH_REG (oper->dst),
! 						 NO_INSERT);
! 		if (slot)
! 		  htab_clear_slot (new_out, slot);
! 	      }
! 	    break;
! 
! 	  case CONST_INT_TO_REG:
! 	    mask
! 	      = (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (oper->dst));
! 	    /* Set the range of SET_DST to be a single value.  */
! 	    slot = htab_find_slot_with_hash (new_out, oper->dst,
! 					     HASH_REG (oper->dst), NO_INSERT);
! 	    if (slot)
! 	      dst_r = *slot;
! 	    else
! 	      {
! 		dst_r = pool_alloc (range_pool);
! 		slot = htab_find_slot_with_hash (new_out, oper->dst,
! 						 HASH_REG (oper->dst), INSERT);
! 		*slot = dst_r;
! 	      }
! 
! 	    /* We do not know whether the constant is signed or unsigned.  */
! 	    dst_r->type = RANGE_SIGNED_INT | RANGE_UNSIGNED_INT;
! 	    dst_r->reg = oper->dst;
! 	    dst_r->from.si = INTVAL (oper->src);
! 	    dst_r->to.si = INTVAL (oper->src);
! 	    dst_r->from.ui = (unsigned HOST_WIDE_INT) INTVAL (oper->src) & mask;
! 	    dst_r->to.ui = (unsigned HOST_WIDE_INT) INTVAL (oper->src) & mask;
! 	    break;
  	}
      }
  
*************** value_range_propagation ()
*** 1622,1643 ****
    int i;
  
    /* Initialization.  */
    range_pool = create_alloc_pool ("range_t", sizeof (range_t), 250);
    alloc_aux_for_blocks (sizeof (bb_info));
    alloc_aux_for_edges (sizeof (edge_info));
  
    FOR_ALL_BB (bb)
      {
!       if (bb != ENTRY_BLOCK_PTR && bb != EXIT_BLOCK_PTR)
! 	BBI (bb)->cond = get_condition (bb->end, NULL);
!       else
! 	BBI (bb)->cond = NULL;
! 
        BBI (bb)->in = htab_create (5, range_hash, range_eq, range_del);
        BBI (bb)->out = htab_create (5, range_hash, range_eq, range_del);
        for (e = bb->succ; e; e = e->succ_next)
  	EI (e)->htab = htab_create (5, range_hash, range_eq, range_del);
      }
  
    /* Compute reverse completion order of depth first search of the CFG
       so that the data-flow could possibly run faster.  */
--- 1700,1726 ----
    int i;
  
    /* Initialization.  */
+   operation_pool = create_alloc_pool ("operation",
+ 				      sizeof (struct operation_def), 1000);
    range_pool = create_alloc_pool ("range_t", sizeof (range_t), 250);
    alloc_aux_for_blocks (sizeof (bb_info));
    alloc_aux_for_edges (sizeof (edge_info));
  
    FOR_ALL_BB (bb)
      {
!       BBI (bb)->operation_list = NULL;
        BBI (bb)->in = htab_create (5, range_hash, range_eq, range_del);
        BBI (bb)->out = htab_create (5, range_hash, range_eq, range_del);
        for (e = bb->succ; e; e = e->succ_next)
  	EI (e)->htab = htab_create (5, range_hash, range_eq, range_del);
      }
+   BBI (ENTRY_BLOCK_PTR)->cond = NULL;
+   BBI (EXIT_BLOCK_PTR)->cond = NULL;
+   FOR_EACH_BB (bb)
+     {
+       BBI (bb)->cond = get_condition (bb->end, NULL);
+       find_operations (bb);
+     }
  
    /* Compute reverse completion order of depth first search of the CFG
       so that the data-flow could possibly run faster.  */
*************** value_range_propagation ()
*** 1689,1694 ****
--- 1772,1778 ----
    free_aux_for_edges ();
    free_aux_for_blocks ();
    free_alloc_pool (range_pool);
+   free_alloc_pool (operation_pool);
  
    return modified;
  }


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