OSDN Git Service

Make print_scop output the scoplib format.
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index 3f3b863..585cce8 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -2237,7 +2237,7 @@ hash_rtx_string (const char *ps)
   return hash;
 }
 
-/* Same as hash_rtx, but call CB on each rtx if it is not NULL.  
+/* Same as hash_rtx, but call CB on each rtx if it is not NULL.
    When the callback returns true, we continue with the new rtx.  */
 
 unsigned
@@ -2260,7 +2260,7 @@ hash_rtx_cb (const_rtx x, enum machine_mode mode,
     return hash;
 
   /* Invoke the callback first.  */
-  if (cb != NULL 
+  if (cb != NULL
       && ((*cb) (x, mode, &newx, &newmode)))
     {
       hash += hash_rtx_cb (newx, newmode, do_not_record_p,
@@ -2370,7 +2370,7 @@ hash_rtx_cb (const_rtx x, enum machine_mode mode,
          {
            elt = CONST_VECTOR_ELT (x, i);
            hash += hash_rtx_cb (elt, GET_MODE (elt),
-                                 do_not_record_p, hash_arg_in_memory_p, 
+                                 do_not_record_p, hash_arg_in_memory_p,
                                  have_reg_qty, cb);
          }
 
@@ -2516,7 +2516,7 @@ hash_rtx_cb (const_rtx x, enum machine_mode mode,
              x = XEXP (x, i);
              goto repeat;
            }
-          
+
          hash += hash_rtx_cb (XEXP (x, i), VOIDmode, do_not_record_p,
                                hash_arg_in_memory_p,
                                have_reg_qty, cb);
@@ -2623,6 +2623,10 @@ exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse)
   if (GET_MODE (x) != GET_MODE (y))
     return 0;
 
+  /* MEMs refering to different address space are not equivalent.  */
+  if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
+    return 0;
+
   switch (code)
     {
     case PC:
@@ -2680,8 +2684,8 @@ exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse)
             They could e.g. be two different entities allocated into the
             same space on the stack (see e.g. PR25130).  In that case, the
             MEM addresses can be the same, even though the two MEMs are
-            absolutely not equivalent.  
-   
+            absolutely not equivalent.
+
             But because really all MEM attributes should be the same for
             equivalent MEMs, we just use the invariant that MEMs that have
             the same attributes share the same mem_attrs data structure.  */
@@ -3423,7 +3427,7 @@ fold_rtx (rtx x, rtx insn)
                     constant through simplifications.  */
                  p = lookup (folded_arg0, SAFE_HASH (folded_arg0, mode_arg0),
                              mode_arg0);
-                 
+
                  if (p != NULL)
                    {
                      cheapest_simplification = x;
@@ -4432,6 +4436,7 @@ cse_insn (rtx insn)
 
   for (i = 0; i < n_sets; i++)
     {
+      bool repeat = false;
       rtx src, dest;
       rtx src_folded;
       struct table_elt *elt = 0, *p;
@@ -5025,6 +5030,77 @@ cse_insn (rtx insn)
                break;
            }
 
+         /* Try to optimize
+            (set (reg:M N) (const_int A))
+            (set (reg:M2 O) (const_int B))
+            (set (zero_extract:M2 (reg:M N) (const_int C) (const_int D))
+                 (reg:M2 O)).  */
+         if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT
+             && CONST_INT_P (trial)
+             && CONST_INT_P (XEXP (SET_DEST (sets[i].rtl), 1))
+             && CONST_INT_P (XEXP (SET_DEST (sets[i].rtl), 2))
+             && REG_P (XEXP (SET_DEST (sets[i].rtl), 0))
+             && (GET_MODE_BITSIZE (GET_MODE (SET_DEST (sets[i].rtl)))
+                 >= INTVAL (XEXP (SET_DEST (sets[i].rtl), 1)))
+             && ((unsigned) INTVAL (XEXP (SET_DEST (sets[i].rtl), 1))
+                 + (unsigned) INTVAL (XEXP (SET_DEST (sets[i].rtl), 2))
+                 <= HOST_BITS_PER_WIDE_INT))
+           {
+             rtx dest_reg = XEXP (SET_DEST (sets[i].rtl), 0);
+             rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
+             rtx pos = XEXP (SET_DEST (sets[i].rtl), 2);
+             unsigned int dest_hash = HASH (dest_reg, GET_MODE (dest_reg));
+             struct table_elt *dest_elt
+               = lookup (dest_reg, dest_hash, GET_MODE (dest_reg));
+             rtx dest_cst = NULL;
+
+             if (dest_elt)
+               for (p = dest_elt->first_same_value; p; p = p->next_same_value)
+                 if (p->is_const && CONST_INT_P (p->exp))
+                   {
+                     dest_cst = p->exp;
+                     break;
+                   }
+             if (dest_cst)
+               {
+                 HOST_WIDE_INT val = INTVAL (dest_cst);
+                 HOST_WIDE_INT mask;
+                 unsigned int shift;
+                 if (BITS_BIG_ENDIAN)
+                   shift = GET_MODE_BITSIZE (GET_MODE (dest_reg))
+                           - INTVAL (pos) - INTVAL (width);
+                 else
+                   shift = INTVAL (pos);
+                 if (INTVAL (width) == HOST_BITS_PER_WIDE_INT)
+                   mask = ~(HOST_WIDE_INT) 0;
+                 else
+                   mask = ((HOST_WIDE_INT) 1 << INTVAL (width)) - 1;
+                 val &= ~(mask << shift);
+                 val |= (INTVAL (trial) & mask) << shift;
+                 val = trunc_int_for_mode (val, GET_MODE (dest_reg));
+                 validate_unshare_change (insn, &SET_DEST (sets[i].rtl),
+                                          dest_reg, 1);
+                 validate_unshare_change (insn, &SET_SRC (sets[i].rtl),
+                                          GEN_INT (val), 1);
+                 if (apply_change_group ())
+                   {
+                     rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+                     if (note)
+                       {
+                         remove_note (insn, note);
+                         df_notes_rescan (insn);
+                       }
+                     src_eqv = NULL_RTX;
+                     src_eqv_elt = NULL;
+                     src_eqv_volatile = 0;
+                     src_eqv_in_memory = 0;
+                     src_eqv_hash = 0;
+                     repeat = true;
+                     break;
+                   }
+               }
+           }
+
          /* We don't normally have an insn matching (set (pc) (pc)), so
             check for this separately here.  We will delete such an
             insn below.
@@ -5100,6 +5176,13 @@ cse_insn (rtx insn)
            }
        }
 
+      /* If we changed the insn too much, handle this set from scratch.  */
+      if (repeat)
+       {
+         i--;
+         continue;
+       }
+
       src = SET_SRC (sets[i].rtl);
 
       /* In general, it is good to have a SET with SET_SRC == SET_DEST.
@@ -5997,7 +6080,7 @@ cse_process_notes (rtx x, rtx object, bool *changed)
    describe the path.
    It is filled with a queue of basic blocks, starting with FIRST_BB
    and following a trace through the CFG.
-  
+
    If all paths starting at FIRST_BB have been followed, or no new path
    starting at FIRST_BB can be constructed, this function returns FALSE.
    Otherwise, DATA->path is filled and the function returns TRUE indicating
@@ -6013,7 +6096,7 @@ cse_find_path (basic_block first_bb, struct cse_basic_block_data *data,
   basic_block bb;
   edge e;
   int path_size;
+
   SET_BIT (cse_visited_basic_blocks, first_bb->index);
 
   /* See if there is a previous path.  */
@@ -6174,7 +6257,7 @@ cse_prescan_path (struct cse_basic_block_data *data)
   int path_entry;
 
   /* Scan to end of each basic block in the path.  */
-  for (path_entry = 0; path_entry < path_size; path_entry++) 
+  for (path_entry = 0; path_entry < path_size; path_entry++)
     {
       basic_block bb;
       rtx insn;
@@ -6544,9 +6627,9 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
     case CALL_INSN:
     case INSN:
     case JUMP_INSN:
-    /* We expect dest to be NULL_RTX here.  If the insn may trap, mark
-       this fact by setting DEST to pc_rtx.  */
-      if (flag_non_call_exceptions && may_trap_p (PATTERN (x)))
+      /* We expect dest to be NULL_RTX here.  If the insn may trap, mark
+         this fact by setting DEST to pc_rtx.  */
+      if (insn_could_throw_p (x))
        dest = pc_rtx;
       if (code == CALL_INSN)
        count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, dest, incr);
@@ -6658,7 +6741,7 @@ static bool
 insn_live_p (rtx insn, int *counts)
 {
   int i;
-  if (flag_non_call_exceptions && may_trap_p (PATTERN (insn)))
+  if (insn_could_throw_p (insn))
     return true;
   else if (GET_CODE (PATTERN (insn)) == SET)
     return set_live_p (PATTERN (insn), insn, counts);
@@ -6780,7 +6863,7 @@ cse_change_cc_mode (rtx *loc, void *data)
       && GET_MODE (*loc) != GET_MODE (args->newreg))
     {
       validate_change (args->insn, loc, args->newreg, 1);
-      
+
       return -1;
     }
   return 0;
@@ -6800,10 +6883,10 @@ cse_change_cc_mode_insn (rtx insn, rtx newreg)
 
   args.insn = insn;
   args.newreg = newreg;
-  
+
   for_each_rtx (&PATTERN (insn), cse_change_cc_mode, &args);
   for_each_rtx (&REG_NOTES (insn), cse_change_cc_mode, &args);
-  
+
   /* If the following assertion was triggered, there is most probably
      something wrong with the cc_modes_compatible back end function.
      CC modes only can be considered compatible if the insn - with the mode
@@ -6922,7 +7005,7 @@ cse_cc_succs (basic_block bb, basic_block orig_bb, rtx cc_reg, rtx cc_src,
                                       XEXP (SET_SRC (set), 0))
                       && rtx_equal_p (XEXP (cc_src, 1),
                                       XEXP (SET_SRC (set), 1)))
-                          
+
                {
                  comp_mode = targetm.cc_modes_compatible (mode, set_mode);
                  if (comp_mode != VOIDmode
@@ -7179,8 +7262,8 @@ struct rtl_opt_pass pass_cse =
  {
   RTL_PASS,
   "cse1",                               /* name */
-  gate_handle_cse,                      /* gate */   
-  rest_of_handle_cse,                  /* execute */       
+  gate_handle_cse,                      /* gate */
+  rest_of_handle_cse,                  /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
@@ -7242,8 +7325,8 @@ struct rtl_opt_pass pass_cse2 =
  {
   RTL_PASS,
   "cse2",                               /* name */
-  gate_handle_cse2,                     /* gate */   
-  rest_of_handle_cse2,                 /* execute */       
+  gate_handle_cse2,                     /* gate */
+  rest_of_handle_cse2,                 /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
@@ -7303,8 +7386,8 @@ struct rtl_opt_pass pass_cse_after_global_opts =
  {
   RTL_PASS,
   "cse_local",                          /* name */
-  gate_handle_cse_after_global_opts,    /* gate */   
-  rest_of_handle_cse_after_global_opts, /* execute */       
+  gate_handle_cse_after_global_opts,    /* gate */
+  rest_of_handle_cse_after_global_opts, /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */