OSDN Git Service

2010-12-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / lower-subreg.c
index 3301a9d..3563cee 100644 (file)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "basic-block.h"
 #include "recog.h"
 #include "bitmap.h"
+#include "dce.h"
 #include "expr.h"
 #include "except.h"
 #include "regs.h"
@@ -63,6 +64,12 @@ static bitmap decomposable_context;
    which it can not be decomposed.  */
 static bitmap non_decomposable_context;
 
+/* Bit N in this bitmap is set if regno N is used in a subreg
+   which changes the mode but not the size.  This typically happens
+   when the register accessed as a floating-point value; we want to
+   avoid generating accesses to its subwords in integer modes.  */
+static bitmap subreg_context;
+
 /* Bit N in the bitmap in element M of this array is set if there is a
    copy from reg M to reg N.  */
 static VEC(bitmap,heap) *reg_copy_graph;
@@ -289,6 +296,7 @@ find_decomposable_subregs (rtx *px, void *data)
          && !MODES_TIEABLE_P (GET_MODE (x), GET_MODE (inner)))
        {
          bitmap_set_bit (non_decomposable_context, regno);
+         bitmap_set_bit (subreg_context, regno);
          return -1;
        }
     }
@@ -388,7 +396,7 @@ simplify_subreg_concatn (enum machine_mode outermode, rtx op,
                         unsigned int byte)
 {
   unsigned int inner_size;
-  enum machine_mode innermode;
+  enum machine_mode innermode, partmode;
   rtx part;
   unsigned int final_offset;
 
@@ -401,11 +409,24 @@ simplify_subreg_concatn (enum machine_mode outermode, rtx op,
 
   inner_size = GET_MODE_SIZE (innermode) / XVECLEN (op, 0);
   part = XVECEXP (op, 0, byte / inner_size);
+  partmode = GET_MODE (part);
+
+  /* VECTOR_CSTs in debug expressions are expanded into CONCATN instead of
+     regular CONST_VECTORs.  They have vector or integer modes, depending
+     on the capabilities of the target.  Cope with them.  */
+  if (partmode == VOIDmode && VECTOR_MODE_P (innermode))
+    partmode = GET_MODE_INNER (innermode);
+  else if (partmode == VOIDmode)
+    {
+      enum mode_class mclass = GET_MODE_CLASS (innermode);
+      partmode = mode_for_size (inner_size * BITS_PER_UNIT, mclass, 0);
+    }
+
   final_offset = byte % inner_size;
   if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
     return NULL_RTX;
 
-  return simplify_gen_subreg (outermode, part, GET_MODE (part), final_offset);
+  return simplify_gen_subreg (outermode, part, partmode, final_offset);
 }
 
 /* Wrapper around simplify_gen_subreg which handles CONCATN.  */
@@ -616,7 +637,7 @@ can_decompose_p (rtx x)
        return (validate_subreg (word_mode, GET_MODE (x), x, UNITS_PER_WORD)
                && HARD_REGNO_MODE_OK (regno, word_mode));
       else
-       return !bitmap_bit_p (non_decomposable_context, regno);
+       return !bitmap_bit_p (subreg_context, regno);
     }
 
   return true;
@@ -1000,13 +1021,6 @@ resolve_shift_zext (rtx insn)
   offset2 = UNITS_PER_WORD * (1 - dest_reg_num);
   src_offset = UNITS_PER_WORD * src_reg_num;
 
-  if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
-    {
-      offset1 += UNITS_PER_WORD - 1;
-      offset2 += UNITS_PER_WORD - 1;
-      src_offset += UNITS_PER_WORD - 1;
-    }
-
   start_sequence ();
 
   dest_reg = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
@@ -1084,6 +1098,9 @@ decompose_multiword_subregs (void)
       return;
   }
 
+  if (df)
+    run_word_dce ();
+
   /* FIXME: When the dataflow branch is merged, we can change this
      code to look for each multi-word pseudo-register and to find each
      insn which sets or uses that register.  That should be faster
@@ -1091,6 +1108,7 @@ decompose_multiword_subregs (void)
 
   decomposable_context = BITMAP_ALLOC (NULL);
   non_decomposable_context = BITMAP_ALLOC (NULL);
+  subreg_context = BITMAP_ALLOC (NULL);
 
   reg_copy_graph = VEC_alloc (bitmap, heap, max);
   VEC_safe_grow (bitmap, heap, reg_copy_graph, max);
@@ -1212,7 +1230,7 @@ decompose_multiword_subregs (void)
                         basic block and still produce the correct control
                         flow graph for it.  */
                      gcc_assert (!cfi
-                                 || (flag_non_call_exceptions
+                                 || (cfun->can_throw_non_call_exceptions
                                      && can_throw_internal (insn)));
 
                      insn = resolve_simple_move (set, insn);
@@ -1300,7 +1318,7 @@ decompose_multiword_subregs (void)
     unsigned int i;
     bitmap b;
 
-    for (i = 0; VEC_iterate (bitmap, reg_copy_graph, i, b); ++i)
+    FOR_EACH_VEC_ELT (bitmap, reg_copy_graph, i, b)
       if (b)
        BITMAP_FREE (b);
   }
@@ -1309,6 +1327,7 @@ decompose_multiword_subregs (void)
 
   BITMAP_FREE (decomposable_context);
   BITMAP_FREE (non_decomposable_context);
+  BITMAP_FREE (subreg_context);
 }
 \f
 /* Gate function for lower subreg pass.  */