diff options
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 14 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 28 | ||||
-rw-r--r-- | gcc/rtlanal.c | 77 | ||||
-rw-r--r-- | gcc/target-def.h | 5 | ||||
-rw-r--r-- | gcc/target.h | 8 | ||||
-rw-r--r-- | gcc/targhooks.c | 9 | ||||
-rw-r--r-- | gcc/targhooks.h | 1 |
8 files changed, 157 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53e1029..2afcfc1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index ffe047e..f66cdc2 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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; +} #include "gt-mips.h" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 9ee6a83..639e9e9 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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 diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 9292a4b..6a7a696 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -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]; /* 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; +} /* 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 (); } /* Check whether this is a constant pool constant. */ diff --git a/gcc/target-def.h b/gcc/target-def.h index 7500151..3fd22f4 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -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, \ diff --git a/gcc/target.h b/gcc/target.h index b9d3578..f028754 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -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); diff --git a/gcc/targhooks.c b/gcc/targhooks.c index f33704b..a12d6b5 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -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 diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 7c99b08..f6d50dd 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -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); |