Hi,

This is mostly a small memory and pointer-chasing cleanup. We always
know exactly what form an assignment takes so there is no need to
record assignments as SET-rtxen.

Bootstrapped and tested on x86_64-unknown-linux-gnu. OK?

Ciao!
Steven
        * cprop.c (struct expr): Split 'expr' field in 'dest' and 'src'.
        (expr_equiv_p): Remove.
        (insert_set_in_table): Look at <dest, src> pair instead of expr.
        (hash_scan_set): Update call to insert_set_in_table.
        (dump_hash_table): Dump <dest, src> pair.
        (lookup_set): Simplify.  Lookup <dest, src> pair.
        (compute_transp): Remove, fold heavily simplified code into...
        (compute_local_properties): ...here.  Expect COMP and TRANSP
        unconditionally.
        (find_avail_set): Take set directly from struct expr.
        (find_bypass-set): Likewise.
        (bypass_block): Likewise.
        (cprop_insn): Likewise.  Remove redundant INSN_P test.

*** cprop.c.v5  2011-04-02 00:56:57.000000000 +0200
--- cprop.c.v6  2011-04-02 15:54:38.000000000 +0200
*************** static struct obstack cprop_obstack;
*** 55,77 ****
  
  struct reg_use {rtx reg_rtx; };
  
- /* Hash table of expressions.  */
- 
- struct expr
- {
-   /* The expression (SET_SRC for expressions, PATTERN for assignments).  */
-   rtx expr;
-   /* Index in the available expression bitmaps.  */
-   int bitmap_index;
-   /* Next entry with the same hash.  */
-   struct expr *next_same_hash;
-   /* List of available occurrence in basic blocks in the function.
-      An "available occurrence" is one that is the last occurrence in the
-      basic block and the operands are not modified by following statements in
-      the basic block [including this insn].  */
-   struct occr *avail_occr;
- };
- 
  /* Occurrence of an expression.
     There is one per basic block.  If a pattern appears more than once the
     last appearance is used.  */
--- 55,60 ----
*************** typedef struct occr *occr_t;
*** 88,94 ****
  DEF_VEC_P (occr_t);
  DEF_VEC_ALLOC_P (occr_t, heap);
  
! /* Expression and copy propagation hash tables.
     Each hash table is an array of buckets.
     ??? It is known that if it were an array of entries, structure elements
     `next_same_hash' and `bitmap_index' wouldn't be necessary.  However, it is
--- 71,96 ----
  DEF_VEC_P (occr_t);
  DEF_VEC_ALLOC_P (occr_t, heap);
  
! /* Hash table entry for an assignment expressions.  */
! 
! struct expr
! {
!   /* The expression (DEST := SRC).  */
!   rtx dest;
!   rtx src;
! 
!   /* Index in the available expression bitmaps.  */
!   int bitmap_index;
!   /* Next entry with the same hash.  */
!   struct expr *next_same_hash;
!   /* List of available occurrence in basic blocks in the function.
!      An "available occurrence" is one that is the last occurrence in the
!      basic block and the operands are not modified by following statements in
!      the basic block [including this insn].  */
!   struct occr *avail_occr;
! };
! 
! /* Hash table for copy propagation expressions.
     Each hash table is an array of buckets.
     ??? It is known that if it were an array of entries, structure elements
     `next_same_hash' and `bitmap_index' wouldn't be necessary.  However, it is
*************** hash_set (int regno, int hash_table_size
*** 175,214 ****
    return hash % hash_table_size;
  }
  
! /* Return nonzero if exp1 is equivalent to exp2.  */
! 
! static int
! expr_equiv_p (const_rtx x, const_rtx y)
! {
!   return exp_equiv_p (x, y, 0, true);
! }
! 
! /* Insert pattern X in INSN in the hash table.
!    X is a SET of a reg to either another reg or a constant.
!    If it is already present, record it as the last occurrence in INSN's
!    basic block.  */
  
  static void
! insert_set_in_table (rtx x, rtx insn, struct hash_table_d *table)
  {
!   int found;
    unsigned int hash;
    struct expr *cur_expr, *last_expr = NULL;
    struct occr *cur_occr;
  
!   gcc_assert (GET_CODE (x) == SET && REG_P (SET_DEST (x)));
! 
!   hash = hash_set (REGNO (SET_DEST (x)), table->size);
  
!   cur_expr = table->table[hash];
!   found = 0;
! 
!   while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
      {
!       /* If the expression isn't found, save a pointer to the end of
!        the list.  */
        last_expr = cur_expr;
-       cur_expr = cur_expr->next_same_hash;
      }
  
    if (! found)
--- 177,207 ----
    return hash % hash_table_size;
  }
  
! /* Insert assignment DEST:=SET from INSN in the hash table.
!    DEST is a register and SET is a register or a suitable constant.
!    If the assignment is already present in the table, record it as
!    the last occurrence in INSN's basic block.  */
  
  static void
! insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table)
  {
!   bool found = false;
    unsigned int hash;
    struct expr *cur_expr, *last_expr = NULL;
    struct occr *cur_occr;
  
!   hash = hash_set (REGNO (dest), table->size);
  
!   for (cur_expr = table->table[hash]; cur_expr;
!        cur_expr = cur_expr->next_same_hash)
      {
!       if (dest == cur_expr->dest
!         && src == cur_expr->src)
!       {
!         found = true;
!         break;
!       }
        last_expr = cur_expr;
      }
  
    if (! found)
*************** insert_set_in_table (rtx x, rtx insn, st
*** 225,231 ****
        /* Set the fields of the expr element.
         We must copy X because it can be modified when copy propagation is
         performed on its operands.  */
!       cur_expr->expr = copy_rtx (x);
        cur_expr->bitmap_index = table->n_elems++;
        cur_expr->next_same_hash = NULL;
        cur_expr->avail_occr = NULL;
--- 218,225 ----
        /* Set the fields of the expr element.
         We must copy X because it can be modified when copy propagation is
         performed on its operands.  */
!       cur_expr->dest = copy_rtx (dest);
!       cur_expr->src = copy_rtx (src);
        cur_expr->bitmap_index = table->n_elems++;
        cur_expr->next_same_hash = NULL;
        cur_expr->avail_occr = NULL;
*************** hash_scan_set (rtx pat, rtx insn, struct
*** 290,296 ****
         for INSN, we miss copy propagation opportunities.
  
         Note that this does not impede profitable constant propagations.  We
!        "look through" reg-reg sets in lookup_avail_set.  */
        rtx note = find_reg_equal_equiv_note (insn);
        if (note != 0
          && REG_NOTE_KIND (note) == REG_EQUAL
--- 284,290 ----
         for INSN, we miss copy propagation opportunities.
  
         Note that this does not impede profitable constant propagations.  We
!        "look through" reg-reg sets in lookup_set.  */
        rtx note = find_reg_equal_equiv_note (insn);
        if (note != 0
          && REG_NOTE_KIND (note) == REG_EQUAL
*************** hash_scan_set (rtx pat, rtx insn, struct
*** 304,310 ****
           && ! HARD_REGISTER_P (src)
           && reg_available_p (src, insn))
          || cprop_constant_p (src))
!       insert_set_in_table (pat, insn, table);
      }
  }
  
--- 298,304 ----
           && ! HARD_REGISTER_P (src)
           && reg_available_p (src, insn))
          || cprop_constant_p (src))
!       insert_set_in_table (dest, src, insn, table);
      }
  }
  
*************** dump_hash_table (FILE *file, const char 
*** 368,374 ****
        expr = flat_table[i];
        fprintf (file, "Index %d (hash value %d)\n  ",
                 expr->bitmap_index, hash_val[i]);
!       print_rtl (file, expr->expr);
        fprintf (file, "\n");
        }
  
--- 362,370 ----
        expr = flat_table[i];
        fprintf (file, "Index %d (hash value %d)\n  ",
                 expr->bitmap_index, hash_val[i]);
!       print_rtl (file, expr->dest);
!       fprintf (file, " := ");
!       print_rtl (file, expr->src);
        fprintf (file, "\n");
        }
  
*************** lookup_set (unsigned int regno, struct h
*** 497,503 ****
  
    expr = table->table[hash];
  
!   while (expr && REGNO (SET_DEST (expr->expr)) != regno)
      expr = expr->next_same_hash;
  
    return expr;
--- 493,499 ----
  
    expr = table->table[hash];
  
!   while (expr && REGNO (expr->dest) != regno)
      expr = expr->next_same_hash;
  
    return expr;
*************** next_set (unsigned int regno, struct exp
*** 510,516 ****
  {
    do
      expr = expr->next_same_hash;
!   while (expr && REGNO (SET_DEST (expr->expr)) != regno);
  
    return expr;
  }
--- 506,512 ----
  {
    do
      expr = expr->next_same_hash;
!   while (expr && REGNO (expr->dest) != regno);
  
    return expr;
  }
*************** free_cprop_mem (void)
*** 583,658 ****
    sbitmap_vector_free (cprop_avout);
  }
  
- /* For each block, compute whether X is transparent.  X is either an
-    expression or an assignment [though we don't care which, for this context
-    an assignment is treated as an expression].  For each block where an
-    element of X is modified, set the INDX bit in BMAP.  */
- 
- static void
- compute_transp (const_rtx x, int indx, sbitmap *bmap)
- {
-   int i, j;
-   enum rtx_code code;
-   const char *fmt;
- 
-   /* repeat is used to turn tail-recursion into iteration since GCC
-      can't do it when there's no return value.  */
-  repeat:
- 
-   if (x == 0)
-     return;
- 
-   code = GET_CODE (x);
-   switch (code)
-     {
-     case REG:
-       {
-         df_ref def;
-         for (def = DF_REG_DEF_CHAIN (REGNO (x));
-              def;
-              def = DF_REF_NEXT_REG (def))
-           SET_BIT (bmap[DF_REF_BB (def)->index], indx);
-       }
-       return;
- 
-     case PC:
-     case CC0: /*FIXME*/
-     case CONST:
-     case CONST_INT:
-     case CONST_DOUBLE:
-     case CONST_FIXED:
-     case CONST_VECTOR:
-     case SYMBOL_REF:
-     case LABEL_REF:
-     case ADDR_VEC:
-     case ADDR_DIFF_VEC:
-       return;
- 
-     default:
-       break;
-     }
- 
-   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; 
i--)
-     {
-       if (fmt[i] == 'e')
-       {
-         /* If we are about to do the last recursive call
-            needed at this level, change it into iteration.
-            This function is called enough to be worth it.  */
-         if (i == 0)
-           {
-             x = XEXP (x, i);
-             goto repeat;
-           }
- 
-         compute_transp (XEXP (x, i), indx, bmap);
-       }
-       else if (fmt[i] == 'E')
-       for (j = 0; j < XVECLEN (x, i); j++)
-         compute_transp (XVECEXP (x, i, j), indx, bmap);
-     }
- }
- 
  /* Compute the local properties of each recorded expression.
  
     Local properties are those that are defined by the block, irrespective of
--- 579,584 ----
*************** compute_transp (const_rtx x, int indx, s
*** 665,675 ****
     at least once and expression would contain the same value if the
     computation was moved to the end of the block.
  
!    TRANSP and COMP are destination sbitmaps for recording local properties.
!    If NULL, then it is not necessary to compute or record that particular
!    property.
! 
!    TRANSP is computed as ~TRANSP, since this is really cprop's ABSALTERED.  */
  
  static void
  compute_local_properties (sbitmap *transp, sbitmap *comp,
--- 591,597 ----
     at least once and expression would contain the same value if the
     computation was moved to the end of the block.
  
!    TRANSP and COMP are destination sbitmaps for recording local properties.  
*/
  
  static void
  compute_local_properties (sbitmap *transp, sbitmap *comp,
*************** compute_local_properties (sbitmap *trans
*** 677,690 ****
  {
    unsigned int i;
  
!   /* Initialize any bitmaps that were passed in.  */
!   if (transp)
!     {
!       sbitmap_vector_zero (transp, last_basic_block);
!     }
! 
!   if (comp)
!     sbitmap_vector_zero (comp, last_basic_block);
  
    for (i = 0; i < table->size; i++)
      {
--- 599,607 ----
  {
    unsigned int i;
  
!   /* Initialize the bitmaps that were passed in.  */
!   sbitmap_vector_zero (transp, last_basic_block);
!   sbitmap_vector_zero (comp, last_basic_block);
  
    for (i = 0; i < table->size; i++)
      {
*************** compute_local_properties (sbitmap *trans
*** 693,713 ****
        for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
        {
          int indx = expr->bitmap_index;
          struct occr *occr;
  
!         /* The expression is transparent in this block if it is not killed.
!            We start by assuming all are transparent [none are killed], and
!            then reset the bits for those that are.  */
!         if (transp)
!           compute_transp (expr->expr, indx, transp);
  
          /* The occurrences recorded in avail_occr are exactly those that
             we want to set to nonzero in COMP.  */
!         if (comp)
!           for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
!             {
!               SET_BIT (comp[BLOCK_FOR_INSN (occr->insn)->index], indx);
!             }
        }
      }
  }
--- 610,636 ----
        for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
        {
          int indx = expr->bitmap_index;
+         df_ref def;
          struct occr *occr;
  
!         /* The expression is transparent in a block if it is not killed,
!            i.e. DEST and SRC are not set or clobbered in the block.
!            We start by assuming all are transparent [none are killed],
!            and then set the bits for those that are.  */
!         for (def = DF_REG_DEF_CHAIN (REGNO (expr->dest));
!              def; def = DF_REF_NEXT_REG (def))
!           SET_BIT (transp[DF_REF_BB (def)->index], indx);
!         if (REG_P (expr->src))
!           for (def = DF_REG_DEF_CHAIN (REGNO (expr->src));
!                def; def = DF_REF_NEXT_REG (def))
!             SET_BIT (transp[DF_REF_BB (def)->index], indx);
  
          /* The occurrences recorded in avail_occr are exactly those that
             we want to set to nonzero in COMP.  */
!         for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
!           {
!             SET_BIT (comp[BLOCK_FOR_INSN (occr->insn)->index], indx);
!           }
        }
      }
  }
*************** find_avail_set (int regno, rtx insn)
*** 892,900 ****
        if (set == 0)
        break;
  
!       gcc_assert (GET_CODE (set->expr) == SET);
! 
!       src = SET_SRC (set->expr);
  
        /* We know the set is available.
         Now check that SRC is locally anticipatable (i.e. none of the
--- 815,821 ----
        if (set == 0)
        break;
  
!       src = set->src;
  
        /* We know the set is available.
         Now check that SRC is locally anticipatable (i.e. none of the
*************** cprop_insn (rtx insn)
*** 1080,1094 ****
    int changed = 0;
    rtx note;
  
-   if (!INSN_P (insn))
-     return 0;
- 
    reg_use_count = 0;
    note_uses (&PATTERN (insn), find_used_regs, NULL);
  
-   note = find_reg_equal_equiv_note (insn);
- 
    /* We may win even when propagating constants into notes.  */
    if (note)
      find_used_regs (&XEXP (note, 0), NULL);
  
--- 1001,1011 ----
    int changed = 0;
    rtx note;
  
    reg_use_count = 0;
    note_uses (&PATTERN (insn), find_used_regs, NULL);
  
    /* We may win even when propagating constants into notes.  */
+   note = find_reg_equal_equiv_note (insn);
    if (note)
      find_used_regs (&XEXP (note, 0), NULL);
  
*************** cprop_insn (rtx insn)
*** 1096,1102 ****
         reg_used++, reg_use_count--)
      {
        unsigned int regno = REGNO (reg_used->reg_rtx);
!       rtx pat, src;
        struct expr *set;
  
        /* If the register has already been set in this block, there's
--- 1013,1019 ----
         reg_used++, reg_use_count--)
      {
        unsigned int regno = REGNO (reg_used->reg_rtx);
!       rtx src;
        struct expr *set;
  
        /* If the register has already been set in this block, there's
*************** cprop_insn (rtx insn)
*** 1110,1120 ****
        if (! set)
        continue;
  
!       pat = set->expr;
!       /* ??? We might be able to handle PARALLELs.  Later.  */
!       gcc_assert (GET_CODE (pat) == SET);
! 
!       src = SET_SRC (pat);
  
        /* Constant propagation.  */
        if (cprop_constant_p (src))
--- 1027,1033 ----
        if (! set)
        continue;
  
!       src = set->src;
  
        /* Constant propagation.  */
        if (cprop_constant_p (src))
*************** cprop_insn (rtx insn)
*** 1150,1156 ****
                }
  
              /* The original insn setting reg_used may or may not now be
!                deletable.  We leave the deletion to flow.  */
              /* FIXME: If it turns out that the insn isn't deletable,
                 then we may have unnecessarily extended register lifetimes
                 and made things worse.  */
--- 1063,1069 ----
                }
  
              /* The original insn setting reg_used may or may not now be
!                deletable.  We leave the deletion to DCE.  */
              /* FIXME: If it turns out that the insn isn't deletable,
                 then we may have unnecessarily extended register lifetimes
                 and made things worse.  */
*************** find_bypass_set (int regno, int bb)
*** 1502,1510 ****
        if (set == 0)
        break;
  
!       gcc_assert (GET_CODE (set->expr) == SET);
! 
!       src = SET_SRC (set->expr);
        if (cprop_constant_p (src))
        result = set;
  
--- 1415,1421 ----
        if (set == 0)
        break;
  
!       src = set->src;
        if (cprop_constant_p (src))
        result = set;
  
*************** bypass_block (basic_block bb, rtx setcc,
*** 1625,1631 ****
                                        SET_SRC (PATTERN (setcc)));
  
          new_rtx = simplify_replace_rtx (src, reg_used->reg_rtx,
!                                         SET_SRC (set->expr));
  
          /* Jump bypassing may have already placed instructions on
             edges of the CFG.  We can't bypass an outgoing edge that
--- 1536,1542 ----
                                        SET_SRC (PATTERN (setcc)));
  
          new_rtx = simplify_replace_rtx (src, reg_used->reg_rtx,
!                                         set->src);
  
          /* Jump bypassing may have already placed instructions on
             edges of the CFG.  We can't bypass an outgoing edge that
*************** bypass_block (basic_block bb, rtx setcc,
*** 1677,1683 ****
                  fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
                                      "in jump_insn %d equals constant ",
                           regno, INSN_UID (jump));
!                 print_rtl (dump_file, SET_SRC (set->expr));
                  fprintf (dump_file, "\nBypass edge from %d->%d to %d\n",
                           e->src->index, old_dest->index, dest->index);
                }
--- 1588,1594 ----
                  fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
                                      "in jump_insn %d equals constant ",
                           regno, INSN_UID (jump));
!                 print_rtl (dump_file, set->src);
                  fprintf (dump_file, "\nBypass edge from %d->%d to %d\n",
                           e->src->index, old_dest->index, dest->index);
                }

Reply via email to