Commit 273a2526 by Richard Sandiford Committed by Richard Sandiford

md.texi (shift patterns): New anchor.

	* doc/md.texi (shift patterns): New anchor.  Add reference to
	TARGET_SHIFT_TRUNCATION_MASK.
	* doc/tm.texi (TARGET_SHIFT_TRUNCATION_MASK): Document.
	* target.h (shift_truncation_mask): New target hook.
	* targhook.h (default_shift_truncation_mask): Declare.
	* targhook.c (default_shift_truncation_mask): Define.
	* target-def.h (TARGET_SHIFT_TRUNCATION_MASK): Define.
	(TARGET_INITIALIZER): Include it.
	* simplify-rtx.c (simplify_binary_operation): Combine ASHIFT, ASHIFTRT
	and LSHIFTRT cases.  Truncate arg1 if SHIFT_COUNT_TRUNCATED, otherwise
	reject all out-of-range values.  Fix sign-extension code for modes
	whose width is smaller than HOST_BITS_PER_WIDE_INT.
	* optabs.c (simplify_expand_binop, force_expand_binop): New functions.
	(expand_superword_shift, expand_subword_shift): Likewise.
	(expand_doubleword_shift_condmove, expand_doubleword_shift): Likewise.
	(expand_binop): Use them to implement double-word shifts.
	* config/arm/arm.c (arm_shift_truncation_mask): New function.
	(TARGET_SHIFT_TRUNCATION_MASK): Define.

From-SVN: r87079
parent caf29de7
2004-09-04 Richard Sandiford <rsandifo@redhat.com>
* doc/md.texi (shift patterns): New anchor. Add reference to
TARGET_SHIFT_TRUNCATION_MASK.
* doc/tm.texi (TARGET_SHIFT_TRUNCATION_MASK): Document.
* target.h (shift_truncation_mask): New target hook.
* targhook.h (default_shift_truncation_mask): Declare.
* targhook.c (default_shift_truncation_mask): Define.
* target-def.h (TARGET_SHIFT_TRUNCATION_MASK): Define.
(TARGET_INITIALIZER): Include it.
* simplify-rtx.c (simplify_binary_operation): Combine ASHIFT, ASHIFTRT
and LSHIFTRT cases. Truncate arg1 if SHIFT_COUNT_TRUNCATED, otherwise
reject all out-of-range values. Fix sign-extension code for modes
whose width is smaller than HOST_BITS_PER_WIDE_INT.
* optabs.c (simplify_expand_binop, force_expand_binop): New functions.
(expand_superword_shift, expand_subword_shift): Likewise.
(expand_doubleword_shift_condmove, expand_doubleword_shift): Likewise.
(expand_binop): Use them to implement double-word shifts.
* config/arm/arm.c (arm_shift_truncation_mask): New function.
(TARGET_SHIFT_TRUNCATION_MASK): Define.
2004-09-04 Jan Hubicka <jh@suse.cz>
* tree.c (iterate_hash_expr): Optimize, avoid use of iterative_hash_object.
......
......@@ -175,7 +175,7 @@ static bool arm_cxx_cdtor_returns_this (void);
static bool arm_cxx_key_method_may_be_inline (void);
static bool arm_cxx_export_class_data (void);
static void arm_init_libfuncs (void);
static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
/* Initialize the GCC target structure. */
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
......@@ -248,6 +248,8 @@ static void arm_init_libfuncs (void);
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST arm_address_cost
#undef TARGET_SHIFT_TRUNCATION_MASK
#define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask
#undef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p
......@@ -14334,3 +14336,14 @@ arm_vector_mode_supported_p (enum machine_mode mode)
return false;
}
/* Implement TARGET_SHIFT_TRUNCATION_MASK. SImode shifts use normal
ARM insns and therefore guarantee that the shift count is modulo 256.
DImode shifts (those implemented by lib1funcs.asm or by optabs.c)
guarantee no particular behavior for out-of-range counts. */
static unsigned HOST_WIDE_INT
arm_shift_truncation_mask (enum machine_mode mode)
{
return mode == SImode ? 255 : 0;
}
......@@ -2884,13 +2884,16 @@ quotient or remainder and generate the appropriate instruction.
@item @samp{udivmod@var{m}4}
Similar, but does unsigned division.
@anchor{shift patterns}
@cindex @code{ashl@var{m}3} instruction pattern
@item @samp{ashl@var{m}3}
Arithmetic-shift operand 1 left by a number of bits specified by operand
2, and store the result in operand 0. Here @var{m} is the mode of
operand 0 and operand 1; operand 2's mode is specified by the
instruction pattern, and the compiler will convert the operand to that
mode before generating the instruction.
mode before generating the instruction. The meaning of out-of-range shift
counts can optionally be specified by @code{TARGET_SHIFT_TRUNCATION_MASK}.
@xref{TARGET_SHIFT_TRUNCATION_MASK}.
@cindex @code{ashr@var{m}3} instruction pattern
@cindex @code{lshr@var{m}3} instruction pattern
......
......@@ -8749,6 +8749,31 @@ the implied truncation of the shift instructions.
You need not define this macro if it would always have the value of zero.
@end defmac
@anchor{TARGET_SHIFT_TRUNCATION_MASK}
@deftypefn {Target Hook} int TARGET_SHIFT_TRUNCATION_MASK (enum machine_mode @var{mode})
This function describes how the standard shift patterns for @var{mode}
deal with shifts by negative amounts or by more than the width of the mode.
@xref{shift patterns}.
On many machines, the shift patterns will apply a mask @var{m} to the
shift count, meaning that a fixed-width shift of @var{x} by @var{y} is
equivalent to an arbitrary-width shift of @var{x} by @var{y & m}. If
this is true for mode @var{mode}, the function should return @var{m},
otherwise it should return 0. A return value of 0 indicates that no
particular behavior is guaranteed.
Note that, unlike @code{SHIFT_COUNT_TRUNCATED}, this function does
@emph{not} apply to general shift rtxes; it applies only to instructions
that are generated by the named shift patterns.
The default implementation of this function returns
@code{GET_MODE_BITSIZE (@var{mode}) - 1} if @code{SHIFT_COUNT_TRUNCATED}
and 0 otherwise. This definition is always safe, but if
@code{SHIFT_COUNT_TRUNCATED} is false, and some shift patterns
nevertheless truncate the shift count, you may get better code
by overriding it.
@end deftypefn
@defmac TRULY_NOOP_TRUNCATION (@var{outprec}, @var{inprec})
A C expression which is nonzero if on this machine it is safe to
``convert'' an integer of @var{inprec} bits to one of @var{outprec}
......
......@@ -2343,41 +2343,26 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
break;
case LSHIFTRT:
/* If shift count is undefined, don't fold it; let the machine do
what it wants. But truncate it if the machine will do that. */
if (arg1 < 0)
return 0;
if (SHIFT_COUNT_TRUNCATED)
arg1 %= width;
val = ((unsigned HOST_WIDE_INT) arg0) >> arg1;
break;
case ASHIFT:
if (arg1 < 0)
return 0;
if (SHIFT_COUNT_TRUNCATED)
arg1 %= width;
val = ((unsigned HOST_WIDE_INT) arg0) << arg1;
break;
case ASHIFTRT:
if (arg1 < 0)
return 0;
/* Truncate the shift if SHIFT_COUNT_TRUNCATED, otherwise make sure the
value is in range. We can't return any old value for out-of-range
arguments because either the middle-end (via shift_truncation_mask)
or the back-end might be relying on target-specific knowledge.
Nor can we rely on shift_truncation_mask, since the shift might
not be part of an ashlM3, lshrM3 or ashrM3 instruction. */
if (SHIFT_COUNT_TRUNCATED)
arg1 %= width;
val = arg0s >> arg1;
arg1 = (unsigned HOST_WIDE_INT) arg1 % width;
else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode))
return 0;
/* Bootstrap compiler may not have sign extended the right shift.
Manually extend the sign to insure bootstrap cc matches gcc. */
if (arg0s < 0 && arg1 > 0)
val |= ((HOST_WIDE_INT) -1) << (HOST_BITS_PER_WIDE_INT - arg1);
val = (code == ASHIFT
? ((unsigned HOST_WIDE_INT) arg0) << arg1
: ((unsigned HOST_WIDE_INT) arg0) >> arg1);
/* Sign-extend the result for arithmetic right shifts. */
if (code == ASHIFTRT && arg0s < 0 && arg1 > 0)
val |= ((HOST_WIDE_INT) -1) << (width - arg1);
break;
case ROTATERT:
......
......@@ -301,6 +301,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_BINDS_LOCAL_P default_binds_local_p
#endif
#ifndef TARGET_SHIFT_TRUNCATION_MASK
#define TARGET_SHIFT_TRUNCATION_MASK default_shift_truncation_mask
#endif
#ifndef TARGET_VALID_POINTER_MODE
#define TARGET_VALID_POINTER_MODE default_valid_pointer_mode
#endif
......@@ -488,6 +492,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_BINDS_LOCAL_P, \
TARGET_ENCODE_SECTION_INFO, \
TARGET_STRIP_NAME_ENCODING, \
TARGET_SHIFT_TRUNCATION_MASK, \
TARGET_VALID_POINTER_MODE, \
TARGET_SCALAR_MODE_SUPPORTED_P, \
TARGET_VECTOR_MODE_SUPPORTED_P, \
......
......@@ -378,6 +378,10 @@ struct gcc_target
/* Undo the effects of encode_section_info on the symbol string. */
const char * (* strip_name_encoding) (const char *);
/* If shift optabs for MODE are known to always truncate the shift count,
return the mask that they apply. Return 0 otherwise. */
unsigned HOST_WIDE_INT (* shift_truncation_mask) (enum machine_mode mode);
/* True if MODE is valid for a pointer in __attribute__((mode("MODE"))). */
bool (* valid_pointer_mode) (enum machine_mode mode);
......
......@@ -135,6 +135,14 @@ default_eh_return_filter_mode (void)
return word_mode;
}
/* The default implementation of TARGET_SHIFT_TRUNCATION_MASK. */
unsigned HOST_WIDE_INT
default_shift_truncation_mask (enum machine_mode mode)
{
return SHIFT_COUNT_TRUNCATED ? GET_MODE_BITSIZE (mode) - 1 : 0;
}
/* Generic hook that takes a CUMULATIVE_ARGS pointer and returns true. */
bool
......
......@@ -32,6 +32,8 @@ extern bool hook_bool_CUMULATIVE_ARGS_false (CUMULATIVE_ARGS *);
extern bool default_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *);
extern enum machine_mode default_eh_return_filter_mode (void);
extern unsigned HOST_WIDE_INT default_shift_truncation_mask
(enum machine_mode);
extern bool hook_bool_CUMULATIVE_ARGS_true (CUMULATIVE_ARGS *);
extern tree default_cxx_guard_type (void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment