This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] New target-hook: mode_rep_extended (take 2)
- From: Adam Nemet <anemet at caviumnetworks dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 17 Mar 2006 11:06:42 -0800
- Subject: [PATCH] New target-hook: mode_rep_extended (take 2)
- References: <17435.1999.812437.395189@localhost.localdomain>
[Same contents, corrected Subject line]
This new version of the patch incorporates the ideas from Richard
Sandiford's review yesterday
(http://gcc.gnu.org/ml/gcc-patches/2006-03/msg01009.html).
I addressed all the issues except for the suggestion to remove
cubicness from init_num_sign_bit_copies_in_rep. I think since the
body of the most inner loop is run 10 times at start-up time
readability should be a higher priority than performance. However, I
did change the code to iterate through modes in size-order. While
doing this I swapped the order of indexes to num_sign_bit_copies to
match how the two loops are nested.
I also added more documentation mentioning that
TARGET_MODE_REP_EXTENDED is only supposed to return non-UNKNOWN for
neighboring modes. Actually, I think it would have been cleaner to
incorporate this limitation into the interface such that the hook
would only take one mode and assume the representation-mode to be the
next widest mode. I can follow up with a patch adjusting this if
there is interest to do this. Or alternatively I can add a gcc_assert
check as suggested by Giovanni.
Bootstrapped and tested on i686-pc-linux-gnu and tested on
mipsisa64-elf. tm.texi change was tested with make dvi.
OK to apply?
Adam
* 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.
Index: doc/tm.texi
===================================================================
--- doc/tm.texi (revision 111596)
+++ doc/tm.texi (working copy)
@@ -9063,6 +9063,34 @@ If this is the case, making @code{TRULY_
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: targhooks.c
===================================================================
--- targhooks.c (revision 111596)
+++ targhooks.c (working copy)
@@ -156,6 +156,15 @@ default_min_divisions_for_recip_mul (enu
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: targhooks.h
===================================================================
--- targhooks.h (revision 111596)
+++ targhooks.h (working copy)
@@ -34,6 +34,7 @@ extern enum machine_mode default_eh_retu
extern unsigned HOST_WIDE_INT default_shift_truncation_mask
(enum machine_mode);
extern unsigned int default_min_divisions_for_recip_mul (enum machine_mode);
+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);
Index: target.h
===================================================================
--- target.h (revision 111596)
+++ target.h (working copy)
@@ -462,6 +462,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: rtlanal.c
===================================================================
--- rtlanal.c (revision 111596)
+++ rtlanal.c (working copy)
@@ -67,6 +67,22 @@ static int non_rtx_starting_operands[NUM
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 simply 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];
/* Return 1 if the value of X is unstable
(would be different at a different point in the program).
@@ -4808,6 +4824,45 @@ get_condition (rtx jump, rtx *earliest,
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;
+
+ /* 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. */
@@ -4815,9 +4870,20 @@ get_condition (rtx jump, rtx *earliest,
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;
+}
/* Initialize non_rtx_starting_operands, which is used to speed up
for_each_rtx. */
@@ -4831,6 +4897,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 ();
}
/* Check whether this is a constant pool constant. */
Index: target-def.h
===================================================================
--- target-def.h (revision 111596)
+++ target-def.h (working copy)
@@ -354,6 +354,10 @@ Foundation, 51 Franklin Street, Fifth Fl
#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
@@ -616,6 +620,7 @@ Foundation, 51 Franklin Street, Fifth Fl
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: config/mips/mips.c
===================================================================
--- config/mips/mips.c (revision 111596)
+++ config/mips/mips.c (working copy)
@@ -409,6 +409,7 @@ static rtx mips_expand_builtin_compare (
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. */
@@ -1142,6 +1143,9 @@ static struct mips_rtx_cost_data const m
#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
@@ -10783,5 +10787,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;
+}
#include "gt-mips.h"