* target.h (struct gcc_target): Add mode_rep_extended.
authornemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 17 Apr 2006 01:59:41 +0000 (01:59 +0000)
committernemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 17 Apr 2006 01:59:41 +0000 (01:59 +0000)
* rtlanal.c (num_sign_bit_copies_in_rep): New global.
(init_num_sign_bit_copies_in_rep): Initialize it using
mode_rep_extended.
(truncate_to_mode): Use it.
(init_rtlanal): Call init_num_sign_bit_copies_in_rep.
* targhooks.h (default_mode_rep_extended): Declare it.
* targhooks.c (default_mode_rep_extended): Define it.
* target-def.h (TARGET_MODE_REP_EXTENDED): New macro.  Default to
default_mode_rep_extended.
(TARGET_INITIALIZER): Include it.
* doc/tm.texi (Misc): Document it.
* config/mips/mips.c (TARGET_TRUNCATED_TO_MODE): Override it.
(mips_truncated_to_mode): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112998 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/doc/tm.texi
gcc/rtlanal.c
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h

index 53e1029..2afcfc1 100644 (file)
@@ -1,3 +1,20 @@
+2006-04-16  Adam Nemet  <anemet@caviumnetworks.com>
+
+       * target.h (struct gcc_target): Add mode_rep_extended.
+       * rtlanal.c (num_sign_bit_copies_in_rep): New global.
+       (init_num_sign_bit_copies_in_rep): Initialize it using
+       mode_rep_extended.
+       (truncate_to_mode): Use it.
+       (init_rtlanal): Call init_num_sign_bit_copies_in_rep.
+       * targhooks.h (default_mode_rep_extended): Declare it.
+       * targhooks.c (default_mode_rep_extended): Define it.
+       * target-def.h (TARGET_MODE_REP_EXTENDED): New macro.  Default to
+       default_mode_rep_extended.
+       (TARGET_INITIALIZER): Include it.
+       * doc/tm.texi (Misc): Document it.
+       * config/mips/mips.c (TARGET_TRUNCATED_TO_MODE): Override it.
+       (mips_truncated_to_mode): New function.
+
 2006-04-16  Roger Sayle  <roger@eyesopen.com>
 
        PR middle-end/25474
index ffe047e..f66cdc2 100644 (file)
@@ -409,6 +409,7 @@ static rtx mips_expand_builtin_compare (enum mips_builtin_type,
 static rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx);
 static void mips_encode_section_info (tree, rtx, int);
 static void mips_extra_live_on_entry (bitmap);
+static int mips_mode_rep_extended (enum machine_mode, enum machine_mode);
 
 /* Structure to be filled in by compute_frame_size with register
    save masks, and offsets for the current function.  */
@@ -1139,6 +1140,9 @@ static struct mips_rtx_cost_data const mips_rtx_cost_data[PROCESSOR_MAX] =
 #undef TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES mips_arg_partial_bytes
 
+#undef TARGET_MODE_REP_EXTENDED
+#define TARGET_MODE_REP_EXTENDED mips_mode_rep_extended
+
 #undef TARGET_VECTOR_MODE_SUPPORTED_P
 #define TARGET_VECTOR_MODE_SUPPORTED_P mips_vector_mode_supported_p
 
@@ -10725,5 +10729,15 @@ mips_extra_live_on_entry (bitmap regs)
     bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM);
 }
 
+/* SImode values are represented as sign-extended to DImode.  */
+
+int
+mips_mode_rep_extended (enum machine_mode mode, enum machine_mode mode_rep)
+{
+  if (TARGET_64BIT && mode == SImode && mode_rep == DImode)
+    return SIGN_EXTEND;
+
+  return UNKNOWN;
+}
 \f
 #include "gt-mips.h"
index 9ee6a83..639e9e9 100644 (file)
@@ -9143,6 +9143,34 @@ If this is the case, making @code{TRULY_NOOP_TRUNCATION} return 0 in
 such cases may improve things.
 @end defmac
 
+@deftypefn {Target Hook} int TARGET_MODE_REP_EXTENDED (enum machine_mode @var{mode}, enum machine_mode @var{rep_mode})
+The representation of an intergral mode can be such that the values
+are always extended to a wider integral mode.  Return
+@code{SIGN_EXTEND} if values of @var{mode} are represented in
+sign-extended form to @var{rep_mode}.  Return @code{UNKNOWN}
+otherwise.  (Currently, none of the targets use zero-extended
+representation this way so unlike @code{LOAD_EXTEND_OP},
+@code{TARGET_MODE_REP_EXTENDED} is expected to return either
+@code{SIGN_EXTEND} or @code{UNKNOWN}.  Also no target extends
+@var{mode} to @var{mode_rep} so that @var{mode_rep} is not the next
+widest integral mode and currently we take advantage of this fact.)
+
+Similarly to @code{LOAD_EXTEND_OP} you may return a non-@code{UNKNOWN}
+value even if the extension is not performed on certain hard registers
+as long as for the @code{REGNO_REG_CLASS} of these hard registers
+@code{CANNOT_CHANGE_MODE_CLASS} returns nonzero.
+
+Note that @code{TARGET_MODE_REP_EXTENDED} and @code{LOAD_EXTEND_OP}
+describe two related properties.  If you define
+@code{TARGET_MODE_REP_EXTENDED (mode, word_mode)} you probably also want
+to define @code{LOAD_EXTEND_OP (mode)} to return the same type of
+extension.
+
+In order to enforce the representation of @code{mode},
+@code{TRULY_NOOP_TRUNCATION} should return false when truncating to
+@code{mode}.
+@end deftypefn
+
 @defmac STORE_FLAG_VALUE
 A C expression describing the value returned by a comparison operator
 with an integral mode and stored by a store-flag instruction
index 9292a4b..6a7a696 100644 (file)
@@ -67,6 +67,22 @@ static int non_rtx_starting_operands[NUM_RTX_CODE];
    and set by `-m...' switches.  Must be defined in rtlanal.c.  */
 
 int target_flags;
+
+/* Truncation narrows the mode from SOURCE mode to DESTINATION mode.
+   If TARGET_MODE_REP_EXTENDED (DESTINATION, DESTINATION_REP) is
+   SIGN_EXTEND then while narrowing we also have to enforce the
+   representation and sign-extend the value to mode DESTINATION_REP.
+
+   If the value is already sign-extended to DESTINATION_REP mode we
+   can just switch to DESTINATION mode on it.  For each pair of
+   integral modes SOURCE and DESTINATION, when truncating from SOURCE
+   to DESTINATION, NUM_SIGN_BIT_COPIES_IN_REP[SOURCE][DESTINATION]
+   contains the number of high-order bits in SOURCE that have to be
+   copies of the sign-bit so that we can do this mode-switch to
+   DESTINATION.  */
+
+static unsigned int
+num_sign_bit_copies_in_rep[MAX_MODE_INT + 1][MAX_MODE_INT + 1];
 \f
 /* Return 1 if the value of X is unstable
    (would be different at a different point in the program).
@@ -4632,6 +4648,50 @@ get_condition (rtx jump, rtx *earliest, int allow_cc_mode, int valid_at_insn_p)
                                 allow_cc_mode, valid_at_insn_p);
 }
 
+/* Initialize the table NUM_SIGN_BIT_COPIES_IN_REP based on
+   TARGET_MODE_REP_EXTENDED.
+
+   Note that we assume that the property of
+   TARGET_MODE_REP_EXTENDED(B, C) is sticky to the integral modes
+   narrower than mode B.  I.e., if A is a mode narrower than B then in
+   order to be able to operate on it in mode B, mode A needs to
+   satisfy the requirements set by the representation of mode B.  */
+
+static void
+init_num_sign_bit_copies_in_rep (void)
+{
+  enum machine_mode mode, in_mode;
+
+  for (in_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); in_mode != VOIDmode;
+       in_mode = GET_MODE_WIDER_MODE (mode))
+    for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != in_mode;
+        mode = GET_MODE_WIDER_MODE (mode))
+      {
+       enum machine_mode i;
+
+       /* Currently, it is assumed that TARGET_MODE_REP_EXTENDED
+          extends to the next widest mode.  */
+       gcc_assert (targetm.mode_rep_extended (mode, in_mode) == UNKNOWN
+                   || GET_MODE_WIDER_MODE (mode) == in_mode);
+
+       /* We are in in_mode.  Count how many bits outside of mode
+          have to be copies of the sign-bit.  */
+       for (i = mode; i != in_mode; i = GET_MODE_WIDER_MODE (i))
+         {
+           enum machine_mode wider = GET_MODE_WIDER_MODE (i);
+
+           if (targetm.mode_rep_extended (i, wider) == SIGN_EXTEND
+               /* We can only check sign-bit copies starting from the
+                  top-bit.  In order to be able to check the bits we
+                  have already seen we pretend that subsequent bits
+                  have to be sign-bit copies too.  */
+               || num_sign_bit_copies_in_rep [in_mode][mode])
+             num_sign_bit_copies_in_rep [in_mode][mode]
+               += GET_MODE_BITSIZE (wider) - GET_MODE_BITSIZE (i);
+         }
+      }
+}
+
 /* Suppose that truncation from the machine mode of X to MODE is not a
    no-op.  See if there is anything special about X so that we can
    assume it already contains a truncated value of MODE.  */
@@ -4639,9 +4699,20 @@ get_condition (rtx jump, rtx *earliest, int allow_cc_mode, int valid_at_insn_p)
 bool
 truncated_to_mode (enum machine_mode mode, rtx x)
 {
-  return REG_P (x) && rtl_hooks.reg_truncated_to_mode (mode, x);
-}
+  /* This register has already been used in MODE without explicit
+     truncation.  */
+  if (REG_P (x) && rtl_hooks.reg_truncated_to_mode (mode, x))
+    return true;
+
+  /* See if we already satisfy the requirements of MODE.  If yes we
+     can just switch to MODE.  */
+  if (num_sign_bit_copies_in_rep[GET_MODE (x)][mode]
+      && (num_sign_bit_copies (x, GET_MODE (x))
+         >= num_sign_bit_copies_in_rep[GET_MODE (x)][mode] + 1))
+    return true;
 
+  return false;
+}
 \f
 /* Initialize non_rtx_starting_operands, which is used to speed up
    for_each_rtx.  */
@@ -4655,6 +4726,8 @@ init_rtlanal (void)
       const char *first = strpbrk (format, "eEV");
       non_rtx_starting_operands[i] = first ? first - format : -1;
     }
+
+  init_num_sign_bit_copies_in_rep ();
 }
 \f
 /* Check whether this is a constant pool constant.  */
index 7500151..3fd22f4 100644 (file)
@@ -373,6 +373,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #define TARGET_MIN_DIVISIONS_FOR_RECIP_MUL default_min_divisions_for_recip_mul
 #endif
 
+#ifndef TARGET_MODE_REP_EXTENDED
+#define TARGET_MODE_REP_EXTENDED default_mode_rep_extended
+#endif
+
 #ifndef TARGET_VALID_POINTER_MODE
 #define TARGET_VALID_POINTER_MODE default_valid_pointer_mode
 #endif
@@ -637,6 +641,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   TARGET_STRIP_NAME_ENCODING,                  \
   TARGET_SHIFT_TRUNCATION_MASK,                        \
   TARGET_MIN_DIVISIONS_FOR_RECIP_MUL,          \
+  TARGET_MODE_REP_EXTENDED,                    \
   TARGET_VALID_POINTER_MODE,                    \
   TARGET_SCALAR_MODE_SUPPORTED_P,              \
   TARGET_VECTOR_MODE_SUPPORTED_P,               \
index b9d3578..f028754 100644 (file)
@@ -520,6 +520,14 @@ struct gcc_target
      the reciprocal.  */
   unsigned int (* min_divisions_for_recip_mul) (enum machine_mode mode);
 
+  /* If the representation of integral MODE is such that values are
+     always sign-extended to a wider mode MODE_REP then return
+     SIGN_EXTEND.  Return UNKNOWN otherwise.  */
+  /* Note that the return type ought to be RTX_CODE, but that's not
+     necessarily defined at this point.  */
+  int (* mode_rep_extended) (enum machine_mode mode,
+                            enum machine_mode mode_rep);
+
   /* True if MODE is valid for a pointer in __attribute__((mode("MODE"))).  */
   bool (* valid_pointer_mode) (enum machine_mode mode);
 
index f33704b..a12d6b5 100644 (file)
@@ -156,6 +156,15 @@ default_min_divisions_for_recip_mul (enum machine_mode mode ATTRIBUTE_UNUSED)
   return have_insn_for (DIV, mode) ? 3 : 2;
 }
 
+/* The default implementation of TARGET_MODE_REP_EXTENDED.  */
+
+int
+default_mode_rep_extended (enum machine_mode mode ATTRIBUTE_UNUSED,
+                          enum machine_mode mode_rep ATTRIBUTE_UNUSED)
+{
+  return UNKNOWN;
+}
+
 /* Generic hook that takes a CUMULATIVE_ARGS pointer and returns true.  */
 
 bool
index 7c99b08..f6d50dd 100644 (file)
@@ -34,6 +34,7 @@ extern enum machine_mode default_eh_return_filter_mode (void);
 extern unsigned HOST_WIDE_INT default_shift_truncation_mask
   (enum machine_mode);
 extern unsigned int default_min_divisions_for_recip_mul (enum machine_mode);
+extern int default_mode_rep_extended (enum machine_mode, enum machine_mode);
 
 extern tree default_stack_protect_guard (void);
 extern tree default_external_stack_protect_fail (void);