OSDN Git Service

2009-04-08 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index f4bd77e..04f52fb 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -1364,17 +1364,6 @@ lookup_as_function (rtx x, enum rtx_code code)
   struct table_elt *p
     = lookup (x, SAFE_HASH (x, VOIDmode), GET_MODE (x));
 
-  /* If we are looking for a CONST_INT, the mode doesn't really matter, as
-     long as we are narrowing.  So if we looked in vain for a mode narrower
-     than word_mode before, look for word_mode now.  */
-  if (p == 0 && code == CONST_INT
-      && GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (word_mode))
-    {
-      x = copy_rtx (x);
-      PUT_MODE (x, word_mode);
-      p = lookup (x, SAFE_HASH (x, VOIDmode), word_mode);
-    }
-
   if (p == 0)
     return 0;
 
@@ -3171,33 +3160,15 @@ fold_rtx (rtx x, rtx insn)
     {
     case RTX_UNARY:
       {
-       int is_const = 0;
-
        /* We can't simplify extension ops unless we know the
           original mode.  */
        if ((code == ZERO_EXTEND || code == SIGN_EXTEND)
            && mode_arg0 == VOIDmode)
          break;
 
-       /* If we had a CONST, strip it off and put it back later if we
-          fold.  */
-       if (const_arg0 != 0 && GET_CODE (const_arg0) == CONST)
-         is_const = 1, const_arg0 = XEXP (const_arg0, 0);
-
        new_rtx = simplify_unary_operation (code, mode,
                                        const_arg0 ? const_arg0 : folded_arg0,
                                        mode_arg0);
-       /* NEG of PLUS could be converted into MINUS, but that causes
-          expressions of the form
-          (CONST (MINUS (CONST_INT) (SYMBOL_REF)))
-          which many ports mistakenly treat as LEGITIMATE_CONSTANT_P.
-          FIXME: those ports should be fixed.  */
-       if (new_rtx != 0 && is_const
-           && GET_CODE (new_rtx) == PLUS
-           && (GET_CODE (XEXP (new_rtx, 0)) == SYMBOL_REF
-               || GET_CODE (XEXP (new_rtx, 0)) == LABEL_REF)
-           && GET_CODE (XEXP (new_rtx, 1)) == CONST_INT)
-         new_rtx = gen_rtx_CONST (mode, new_rtx);
       }
       break;
 
@@ -3493,6 +3464,7 @@ fold_rtx (rtx x, rtx insn)
              int is_shift
                = (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
              rtx y, inner_const, new_const;
+             rtx canon_const_arg1 = const_arg1;
              enum rtx_code associate_code;
 
              if (is_shift
@@ -3500,8 +3472,9 @@ fold_rtx (rtx x, rtx insn)
                      || INTVAL (const_arg1) < 0))
                {
                  if (SHIFT_COUNT_TRUNCATED)
-                   const_arg1 = GEN_INT (INTVAL (const_arg1)
-                                         & (GET_MODE_BITSIZE (mode) - 1));
+                   canon_const_arg1 = GEN_INT (INTVAL (const_arg1)
+                                               & (GET_MODE_BITSIZE (mode)
+                                                  - 1));
                  else
                    break;
                }
@@ -3560,7 +3533,8 @@ fold_rtx (rtx x, rtx insn)
              associate_code = (is_shift || code == MINUS ? PLUS : code);
 
              new_const = simplify_binary_operation (associate_code, mode,
-                                                    const_arg1, inner_const);
+                                                    canon_const_arg1,
+                                                    inner_const);
 
              if (new_const == 0)
                break;
@@ -3659,6 +3633,8 @@ equiv_constant (rtx x)
 
   if (GET_CODE (x) == SUBREG)
     {
+      enum machine_mode mode = GET_MODE (x);
+      enum machine_mode imode = GET_MODE (SUBREG_REG (x));
       rtx new_rtx;
 
       /* See if we previously assigned a constant value to this SUBREG.  */
@@ -3667,10 +3643,25 @@ equiv_constant (rtx x)
           || (new_rtx = lookup_as_function (x, CONST_FIXED)) != 0)
         return new_rtx;
 
+      /* If we didn't and if doing so makes sense, see if we previously
+        assigned a constant value to the enclosing word mode SUBREG.  */
+      if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode)
+         && GET_MODE_SIZE (word_mode) < GET_MODE_SIZE (imode))
+       {
+         int byte = SUBREG_BYTE (x) - subreg_lowpart_offset (mode, word_mode);
+         if (byte >= 0 && (byte % UNITS_PER_WORD) == 0)
+           {
+             rtx y = gen_rtx_SUBREG (word_mode, SUBREG_REG (x), byte);
+             new_rtx = lookup_as_function (y, CONST_INT);
+             if (new_rtx)
+               return gen_lowpart (mode, new_rtx);
+           }
+       }
+
+      /* Otherwise see if we already have a constant for the inner REG.  */
       if (REG_P (SUBREG_REG (x))
          && (new_rtx = equiv_constant (SUBREG_REG (x))) != 0)
-        return simplify_subreg (GET_MODE (x), SUBREG_REG (x),
-                               GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
+        return simplify_subreg (mode, new_rtx, imode, SUBREG_BYTE (x));
 
       return 0;
     }
@@ -4495,7 +4486,8 @@ cse_insn (rtx insn)
          enum machine_mode wider_mode;
 
          for (wider_mode = GET_MODE_WIDER_MODE (mode);
-              GET_MODE_BITSIZE (wider_mode) <= BITS_PER_WORD
+              wider_mode != VOIDmode
+              && GET_MODE_BITSIZE (wider_mode) <= BITS_PER_WORD
               && src_related == 0;
               wider_mode = GET_MODE_WIDER_MODE (wider_mode))
            {
@@ -6008,11 +6000,11 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
         edge pointing to that bb.  */
       if (bb_has_eh_pred (bb))
        {
-         struct df_ref **def_rec;
+         df_ref *def_rec;
 
          for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
            {
-             struct df_ref *def = *def_rec;
+             df_ref def = *def_rec;
              if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
                invalidate (DF_REF_REG (def), GET_MODE (DF_REF_REG (def)));
            }