target.h (struct gcc_target): Add mode_rep_extended.
* 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. From-SVN: r112998
This commit is contained in:
parent
ca8b30c8d1
commit
b12cbf2cc5
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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, \
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user