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]

Patch: don't global copy-prop into the middle of libcalls


This patch
http://gcc.gnu.org/ml/gcc-patches/2002-12/msg00136.html
fixed local copy-prop so it won't create references into the middle of
libcalls.  The same problem can occur with global copy-prop, although,
as with the patch referenced above, I can't demonstrate it on mainline.
(Possibly the Hammer guys can do so in their branch.)  This patch
is pretty much analogous to the one above.  Bootstrapped and tested on
Darwin, to the extent currently possible (no diffs before & after).

2003-09-11 Dale Johannesen <dalej@apple.com>

        * gcse.c (struct expr):  add is_libcall_result.
        (insert_set_in_table):  add is_libcall_result; store it.
        (hash_scan_set):  add is_libcall_result; pass it down.
        (hash_scan_insn):  redefine in_libcall_block; use accordingly.
        (compute_hash_table_work): adjust in_libcall_block usages.

Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.272
diff -u -d -b -w -c -3 -p -r1.272 gcse.c
*** gcse.c      6 Sep 2003 17:05:01 -0000       1.272
--- gcse.c      11 Sep 2003 19:48:20 -0000
*************** struct expr
*** 326,331 ****
--- 326,337 ----
       The value is the newly created pseudo-reg to record a copy of the
       expression in all the places that reach the redundant copy.  */
    rtx reaching_reg;
+   /* Non-null for SETs that are the result of a LIBCALL.  Such SETs
+      cannot be used for copy propagation; this results in references
+      from outside the LIBCALL to regs set inside it, which results in
+      bad code if the LIBCALL is deleted.  These SETs are OK for const
+      propagation, though. */
+   int is_libcall_result;
  };

/* Occurrence of an expression.
*************** static void replace_one_set (int, rtx, r
*** 563,569 ****
static void record_set_info (rtx, rtx, void *);
static void compute_sets (rtx);
static void hash_scan_insn (rtx, struct hash_table *, int);
! static void hash_scan_set (rtx, rtx, struct hash_table *);
static void hash_scan_clobber (rtx, rtx, struct hash_table *);
static void hash_scan_call (rtx, rtx, struct hash_table *);
static int want_to_gcse_p (rtx);
--- 569,575 ----
static void record_set_info (rtx, rtx, void *);
static void compute_sets (rtx);
static void hash_scan_insn (rtx, struct hash_table *, int);
! static void hash_scan_set (rtx, rtx, struct hash_table *, int);
static void hash_scan_clobber (rtx, rtx, struct hash_table *);
static void hash_scan_call (rtx, rtx, struct hash_table *);
static int want_to_gcse_p (rtx);
*************** static int oprs_anticipatable_p (rtx, rt
*** 573,579 ****
static int oprs_available_p (rtx, rtx);
static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int,
struct hash_table *);
! static void insert_set_in_table (rtx, rtx, struct hash_table *);
static unsigned int hash_expr (rtx, enum machine_mode, int *, int);
static unsigned int hash_expr_1 (rtx, enum machine_mode, int *);
static unsigned int hash_string_1 (const char *);
--- 579,585 ----
static int oprs_available_p (rtx, rtx);
static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int,
struct hash_table *);
! static void insert_set_in_table (rtx, rtx, struct hash_table *, int);
static unsigned int hash_expr (rtx, enum machine_mode, int *, int);
static unsigned int hash_expr_1 (rtx, enum machine_mode, int *);
static unsigned int hash_string_1 (const char *);
*************** insert_expr_in_table (rtx x, enum machin
*** 2021,2027 ****
basic block. */


  static void
! insert_set_in_table (rtx x, rtx insn, struct hash_table *table)
  {
    int found;
    unsigned int hash;
--- 2027,2034 ----
     basic block.  */

  static void
! insert_set_in_table (rtx x, rtx insn, struct hash_table *table,
!                    int is_libcall_result)
  {
    int found;
    unsigned int hash;
*************** insert_set_in_table (rtx x, rtx insn, st
*** 2064,2069 ****
--- 2071,2077 ----
        cur_expr->next_same_hash = NULL;
        cur_expr->antic_occr = NULL;
        cur_expr->avail_occr = NULL;
+       cur_expr->is_libcall_result = is_libcall_result;
      }

    /* Now record the occurrence.  */
*************** gcse_constant_p (rtx x)
*** 2133,2139 ****
     expression one).  */

  static void
! hash_scan_set (rtx pat, rtx insn, struct hash_table *table)
  {
    rtx src = SET_SRC (pat);
    rtx dest = SET_DEST (pat);
--- 2141,2148 ----
    expression one).  */

  static void
! hash_scan_set (rtx pat, rtx insn, struct hash_table *table,
!              int is_libcall_result)
  {
    rtx src = SET_SRC (pat);
    rtx dest = SET_DEST (pat);
*************** hash_scan_set (rtx pat, rtx insn, struct
*** 2202,2208 ****
               && (insn == BLOCK_END (BLOCK_NUM (insn))
                   || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
                       && oprs_available_p (pat, tmp))))
!       insert_set_in_table (pat, insn, table);
      }
  }

--- 2211,2217 ----
               && (insn == BLOCK_END (BLOCK_NUM (insn))
                   || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
                       && oprs_available_p (pat, tmp))))
!       insert_set_in_table (pat, insn, table, is_libcall_result);
      }
  }

*************** hash_scan_call (rtx x ATTRIBUTE_UNUSED,
*** 2230,2237 ****

     If SET_P is nonzero, this is for the assignment hash table,
     otherwise it is for the expression hash table.
!    If IN_LIBCALL_BLOCK nonzero, we are in a libcall block, and should
!    not record any expressions.  */

static void
hash_scan_insn (rtx insn, struct hash_table *table, int in_libcall_block)
--- 2239,2250 ----


If SET_P is nonzero, this is for the assignment hash table,
otherwise it is for the expression hash table.
!
! If IN_LIBCALL_BLOCK is 1, we are inside a libcall block, and should
! not record any expressions.
! If IN_LIBCALL_BLOCK is 2, this is the SET that ends a libcall block,
! and should be recorded but marked as the result of a libcall.
! If IN_LIBCALL_BLOCK is 0, we are outside a libcall block. */


static void
hash_scan_insn (rtx insn, struct hash_table *table, int in_libcall_block)
*************** hash_scan_insn (rtx insn, struct hash_ta
*** 2239,2259 ****
rtx pat = PATTERN (insn);
int i;


!   if (in_libcall_block)
      return;

/* Pick out the sets of INSN and for other forms of instructions record
what's been modified. */


    if (GET_CODE (pat) == SET)
!     hash_scan_set (pat, insn, table);
    else if (GET_CODE (pat) == PARALLEL)
      for (i = 0; i < XVECLEN (pat, 0); i++)
        {
        rtx x = XVECEXP (pat, 0, i);

        if (GET_CODE (x) == SET)
!         hash_scan_set (x, insn, table);
        else if (GET_CODE (x) == CLOBBER)
          hash_scan_clobber (x, insn, table);
        else if (GET_CODE (x) == CALL)
--- 2252,2272 ----
    rtx pat = PATTERN (insn);
    int i;

!   if (in_libcall_block == 1)
      return;

/* Pick out the sets of INSN and for other forms of instructions record
what's been modified. */


    if (GET_CODE (pat) == SET)
!     hash_scan_set (pat, insn, table, in_libcall_block == 2);
    else if (GET_CODE (pat) == PARALLEL)
      for (i = 0; i < XVECLEN (pat, 0); i++)
        {
        rtx x = XVECEXP (pat, 0, i);

        if (GET_CODE (x) == SET)
!         hash_scan_set (x, insn, table, in_libcall_block == 2);
        else if (GET_CODE (x) == CLOBBER)
          hash_scan_clobber (x, insn, table);
        else if (GET_CODE (x) == CALL)
*************** compute_hash_table_work (struct hash_tab
*** 2494,2500 ****
        if (table->set_p
          && implicit_sets[current_bb->index] != NULL_RTX)
        hash_scan_set (implicit_sets[current_bb->index],
!                      current_bb->head, table);

/* The next pass builds the hash table. */

--- 2507,2513 ----
        if (table->set_p
          && implicit_sets[current_bb->index] != NULL_RTX)
        hash_scan_set (implicit_sets[current_bb->index],
!                      current_bb->head, table, 0);

/* The next pass builds the hash table. */

*************** compute_hash_table_work (struct hash_tab
*** 2506,2513 ****
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
in_libcall_block = 1;
else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
! in_libcall_block = 0;
hash_scan_insn (insn, table, in_libcall_block);
if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
in_libcall_block = 0;
}
--- 2519,2528 ----
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
in_libcall_block = 1;
else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
! in_libcall_block = 2;
hash_scan_insn (insn, table, in_libcall_block);
+ if (in_libcall_block == 2)
+ in_libcall_block = 0;
if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
in_libcall_block = 0;
}



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