mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-15 20:15:43 +08:00
defaults.h (CLZ_DEFINED_VALUE_AT_ZERO): New.
* defaults.h (CLZ_DEFINED_VALUE_AT_ZERO): New. (CTZ_DEFINED_VALUE_AT_ZERO): New. * doc/rtl.texi, doc/tm.texi: Document them. * combine.c (nonzero_bits) [CLZ, CTZ]: Handle the definedness of the value at zero properly. * fold-const.c (tree_expr_nonnegative_p): Likewise. * simplify-rtx.c (simplify_unary_operation): Likewise. * config/alpha/alpha.h (CLZ_DEFINED_VALUE_AT_ZERO): New. (CTZ_DEFINED_VALUE_AT_ZERO): New. * config/arm/arm.c (TARGET_INIT_BUILTINS): Remove. (TARGET_EXPAND_BUILTIN): Remove. (def_builtin, arm_init_builtins, arm_expand_builtin): Remove. * config/arm/arm.h (CLZ_DEFINED_VALUE_AT_ZERO): New. (enum arm_builtins): Remove. * config/arm/arm.md (UNSPEC_CLZ): Remove. (clzsi2): Rename from clz; use clz instead of unspec. (ctzsi2): New. * config/arm/arm-protos.h: Update. From-SVN: r62453
This commit is contained in:
parent
8d705469aa
commit
7dba8395e2
@ -1,3 +1,27 @@
|
||||
2003-02-05 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* defaults.h (CLZ_DEFINED_VALUE_AT_ZERO): New.
|
||||
(CTZ_DEFINED_VALUE_AT_ZERO): New.
|
||||
* doc/rtl.texi, doc/tm.texi: Document them.
|
||||
|
||||
* combine.c (nonzero_bits) [CLZ, CTZ]: Handle the definedness
|
||||
of the value at zero properly.
|
||||
* fold-const.c (tree_expr_nonnegative_p): Likewise.
|
||||
* simplify-rtx.c (simplify_unary_operation): Likewise.
|
||||
|
||||
* config/alpha/alpha.h (CLZ_DEFINED_VALUE_AT_ZERO): New.
|
||||
(CTZ_DEFINED_VALUE_AT_ZERO): New.
|
||||
|
||||
* config/arm/arm.c (TARGET_INIT_BUILTINS): Remove.
|
||||
(TARGET_EXPAND_BUILTIN): Remove.
|
||||
(def_builtin, arm_init_builtins, arm_expand_builtin): Remove.
|
||||
* config/arm/arm.h (CLZ_DEFINED_VALUE_AT_ZERO): New.
|
||||
(enum arm_builtins): Remove.
|
||||
* config/arm/arm.md (UNSPEC_CLZ): Remove.
|
||||
(clzsi2): Rename from clz; use clz instead of unspec.
|
||||
(ctzsi2): New.
|
||||
* config/arm/arm-protos.h: Update.
|
||||
|
||||
Wed Feb 5 23:12:57 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* i386-protos.h (x86_emit_floatuns): Declare.
|
||||
|
@ -8547,11 +8547,28 @@ nonzero_bits (x, mode)
|
||||
break;
|
||||
|
||||
case FFS:
|
||||
case CLZ:
|
||||
case CTZ:
|
||||
case POPCOUNT:
|
||||
/* This is at most the number of bits in the mode. */
|
||||
nonzero = ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width) + 1)) - 1;
|
||||
nonzero = ((HOST_WIDE_INT) 2 << (floor_log2 (mode_width))) - 1;
|
||||
break;
|
||||
|
||||
case CLZ:
|
||||
/* If CLZ has a known value at zero, then the nonzero bits are
|
||||
that value, plus the number of bits in the mode minus one. */
|
||||
if (CLZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
|
||||
nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
|
||||
else
|
||||
nonzero = -1;
|
||||
break;
|
||||
|
||||
case CTZ:
|
||||
/* If CTZ has a known value at zero, then the nonzero bits are
|
||||
that value, plus the number of bits in the mode minus one. */
|
||||
if (CTZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
|
||||
nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
|
||||
else
|
||||
nonzero = -1;
|
||||
break;
|
||||
break;
|
||||
|
||||
case PARITY:
|
||||
|
@ -1493,6 +1493,10 @@ do { \
|
||||
|
||||
#define STORE_FLAG_VALUE 1
|
||||
|
||||
/* The CIX ctlz and cttz instructions return 64 for zero. */
|
||||
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, TARGET_CIX)
|
||||
#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, TARGET_CIX)
|
||||
|
||||
/* Define the value returned by a floating-point comparison instruction. */
|
||||
|
||||
#define FLOAT_STORE_FLAG_VALUE(MODE) \
|
||||
|
@ -209,12 +209,6 @@ extern void arm_mark_dllexport PARAMS ((tree));
|
||||
extern void arm_mark_dllimport PARAMS ((tree));
|
||||
#endif
|
||||
|
||||
extern void arm_init_builtins PARAMS ((void));
|
||||
#if defined (TREE_CODE) && defined (RTX_CODE)
|
||||
extern rtx arm_expand_builtin PARAMS ((tree, rtx, rtx,
|
||||
enum machine_mode, int));
|
||||
#endif
|
||||
|
||||
extern void arm_pr_long_calls PARAMS ((struct cpp_reader *));
|
||||
extern void arm_pr_no_long_calls PARAMS ((struct cpp_reader *));
|
||||
extern void arm_pr_long_calls_off PARAMS ((struct cpp_reader *));
|
||||
|
@ -187,12 +187,6 @@ static int arm_address_cost PARAMS ((rtx));
|
||||
#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
|
||||
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes
|
||||
|
||||
#undef TARGET_INIT_BUILTINS
|
||||
#define TARGET_INIT_BUILTINS arm_init_builtins
|
||||
|
||||
#undef TARGET_EXPAND_BUILTIN
|
||||
#define TARGET_EXPAND_BUILTIN arm_expand_builtin
|
||||
|
||||
#undef TARGET_SCHED_ADJUST_COST
|
||||
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
|
||||
|
||||
@ -9981,82 +9975,6 @@ arm_debugger_arg_offset (value, addr)
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#define def_builtin(NAME, TYPE, CODE) \
|
||||
builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE)
|
||||
|
||||
void
|
||||
arm_init_builtins ()
|
||||
{
|
||||
tree endlink = void_list_node;
|
||||
tree int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
|
||||
tree pchar_type_node = build_pointer_type (char_type_node);
|
||||
|
||||
tree int_ftype_int, void_ftype_pchar;
|
||||
|
||||
/* void func (char *) */
|
||||
void_ftype_pchar
|
||||
= build_function_type_list (void_type_node, pchar_type_node, NULL_TREE);
|
||||
|
||||
/* int func (int) */
|
||||
int_ftype_int
|
||||
= build_function_type (integer_type_node, int_endlink);
|
||||
|
||||
/* Initialize arm V5 builtins. */
|
||||
if (arm_arch5)
|
||||
def_builtin ("__builtin_arm_clz", int_ftype_int, ARM_BUILTIN_CLZ);
|
||||
}
|
||||
|
||||
/* Expand an expression EXP that calls a built-in function,
|
||||
with result going to TARGET if that's convenient
|
||||
(and in mode MODE if that's convenient).
|
||||
SUBTARGET may be used as the target for computing one of EXP's operands.
|
||||
IGNORE is nonzero if the value is to be ignored. */
|
||||
|
||||
rtx
|
||||
arm_expand_builtin (exp, target, subtarget, mode, ignore)
|
||||
tree exp;
|
||||
rtx target;
|
||||
rtx subtarget ATTRIBUTE_UNUSED;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
int ignore ATTRIBUTE_UNUSED;
|
||||
{
|
||||
enum insn_code icode;
|
||||
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree arg0;
|
||||
rtx op0, pat;
|
||||
enum machine_mode tmode, mode0;
|
||||
int fcode = DECL_FUNCTION_CODE (fndecl);
|
||||
|
||||
switch (fcode)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case ARM_BUILTIN_CLZ:
|
||||
icode = CODE_FOR_clz;
|
||||
arg0 = TREE_VALUE (arglist);
|
||||
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
||||
tmode = insn_data[icode].operand[0].mode;
|
||||
mode0 = insn_data[icode].operand[1].mode;
|
||||
|
||||
if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
|
||||
op0 = copy_to_mode_reg (mode0, op0);
|
||||
if (target == 0
|
||||
|| GET_MODE (target) != tmode
|
||||
|| ! (*insn_data[icode].operand[0].predicate) (target, tmode))
|
||||
target = gen_reg_rtx (tmode);
|
||||
pat = GEN_FCN (icode) (target, op0);
|
||||
if (! pat)
|
||||
return 0;
|
||||
emit_insn (pat);
|
||||
return target;
|
||||
}
|
||||
|
||||
/* @@@ Should really do something sensible here. */
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Recursively search through all of the blocks in a function
|
||||
checking to see if any of the variables created in that
|
||||
|
@ -2146,6 +2146,8 @@ extern int making_const_table;
|
||||
|
||||
#define STORE_FLAG_VALUE 1
|
||||
|
||||
/* The arm5 clz instruction returns 32. */
|
||||
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
|
||||
|
||||
|
||||
/* Gcc puts the pool in the wrong place for ARM, since we can only
|
||||
@ -2456,9 +2458,4 @@ extern int making_const_table;
|
||||
#define SPECIAL_MODE_PREDICATES \
|
||||
"cc_register", "dominant_cc_register",
|
||||
|
||||
enum arm_builtins
|
||||
{
|
||||
ARM_BUILTIN_CLZ,
|
||||
ARM_BUILTIN_MAX
|
||||
};
|
||||
#endif /* ! GCC_ARM_H */
|
||||
|
@ -58,9 +58,6 @@
|
||||
; value to it before trying to dereference it.
|
||||
(UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
|
||||
; being scheduled before the stack adjustment insn.
|
||||
(UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
|
||||
; operand 0 is the result,
|
||||
; operand 1 is the parameter.
|
||||
(UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
|
||||
; this unspec is used to prevent the deletion of
|
||||
; instructions setting registers for EH handling
|
||||
@ -8851,10 +8848,9 @@
|
||||
|
||||
;; V5 Instructions,
|
||||
|
||||
(define_insn "clz"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=r")
|
||||
(unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
|
||||
UNSPEC_CLZ))]
|
||||
(define_insn "clzsi2"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=r")
|
||||
(clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
|
||||
"TARGET_ARM && arm_arch5"
|
||||
"clz\\t%0, %1")
|
||||
|
||||
@ -8872,12 +8868,32 @@
|
||||
|
||||
emit_insn (gen_negsi2 (t1, operands[1]));
|
||||
emit_insn (gen_andsi3 (t2, operands[1], t1));
|
||||
emit_insn (gen_clz (t3, t2));
|
||||
emit_insn (gen_clzsi2 (t3, t2));
|
||||
emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
|
||||
DONE;
|
||||
}"
|
||||
)
|
||||
|
||||
(define_expand "ctzsi2"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
|
||||
"TARGET_ARM && arm_arch5"
|
||||
"
|
||||
{
|
||||
rtx t1, t2, t3;
|
||||
|
||||
t1 = gen_reg_rtx (SImode);
|
||||
t2 = gen_reg_rtx (SImode);
|
||||
t3 = gen_reg_rtx (SImode);
|
||||
|
||||
emit_insn (gen_negsi2 (t1, operands[1]));
|
||||
emit_insn (gen_andsi3 (t2, operands[1], t1));
|
||||
emit_insn (gen_clzsi2 (t3, t2));
|
||||
emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
|
||||
DONE;
|
||||
}"
|
||||
)
|
||||
|
||||
;; V5E instructions.
|
||||
|
||||
(define_insn "prefetch"
|
||||
|
@ -644,4 +644,12 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
|
||||
#define TARGET_C99_FUNCTIONS 0
|
||||
#endif
|
||||
|
||||
/* Indicate that CLZ and CTZ are undefined at zero. */
|
||||
#ifndef CLZ_DEFINED_VALUE_AT_ZERO
|
||||
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) 0
|
||||
#endif
|
||||
#ifndef CTZ_DEFINED_VALUE_AT_ZERO
|
||||
#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) 0
|
||||
#endif
|
||||
|
||||
#endif /* ! GCC_DEFAULTS_H */
|
||||
|
@ -1850,7 +1850,8 @@ valid.
|
||||
@item (clz:@var{m} @var{x})
|
||||
Represents the number of leading 0-bits in @var{x}, represented as an
|
||||
integer of mode @var{m}, starting at the most significant bit position.
|
||||
If @var{x} is zero, the value is undefined. Note that this is one of
|
||||
If @var{x} is zero, the value is determined by
|
||||
@code{CLZ_DEFINED_VALUE_AT_ZERO}. Note that this is one of
|
||||
the few expressions that is not invariant under widening. The mode of
|
||||
@var{x} will usually be an integer mode.
|
||||
|
||||
@ -1858,7 +1859,8 @@ the few expressions that is not invariant under widening. The mode of
|
||||
@item (ctz:@var{m} @var{x})
|
||||
Represents the number of trailing 0-bits in @var{x}, represented as an
|
||||
integer of mode @var{m}, starting at the least significant bit position.
|
||||
If @var{x} is zero, the value is undefined. Except for this case,
|
||||
If @var{x} is zero, the value is determined by
|
||||
@code{CTZ_DEFINED_VALUE_AT_ZERO}. Except for this case,
|
||||
@code{ctz(x)} is equivalent to @code{ffs(@var{x}) - 1}. The mode of
|
||||
@var{x} will usually be an integer mode.
|
||||
|
||||
|
@ -8800,6 +8800,25 @@ Define this macro on machine that have comparison operations that return
|
||||
floating-point values. If there are no such operations, do not define
|
||||
this macro.
|
||||
|
||||
@findex CLZ_DEFINED_VALUE_AT_ZERO
|
||||
@findex CTZ_DEFINED_VALUE_AT_ZERO
|
||||
@item CLZ_DEFINED_VALUE_AT_ZERO (@var{mode}, @var{value})
|
||||
@itemx CTZ_DEFINED_VALUE_AT_ZERO (@var{mode}, @var{value})
|
||||
A C expression that evaluates to true if the architecture defines a value
|
||||
for @code{clz} or @code{ctz} with a zero operand. If so, @var{value}
|
||||
should be set to this value. If this macro is not defined, the value of
|
||||
@code{clz} or @code{ctz} is assumed to be undefined.
|
||||
|
||||
This macro must be defined if the target's expansion for @code{ffs}
|
||||
relies on a particular value to get correct results. Otherwise it
|
||||
is not necessary, though it may be used to optimize some corner cases.
|
||||
|
||||
Note that regardless of this macro the ``definedness'' of @code{clz}
|
||||
and @code{ctz} at zero do @emph{not} extend to the builtin functions
|
||||
visible to the user. Thus one may be free to adjust the value at will
|
||||
to match the target expansion of these operations without fear of
|
||||
breaking the API.
|
||||
|
||||
@findex Pmode
|
||||
@item Pmode
|
||||
An alias for the machine mode for pointers. On most machines, define
|
||||
|
@ -7436,11 +7436,17 @@ tree_expr_nonnegative_p (t)
|
||||
{
|
||||
case ABS_EXPR:
|
||||
case FFS_EXPR:
|
||||
case CLZ_EXPR:
|
||||
case CTZ_EXPR:
|
||||
case POPCOUNT_EXPR:
|
||||
case PARITY_EXPR:
|
||||
return 1;
|
||||
|
||||
case CLZ_EXPR:
|
||||
case CTZ_EXPR:
|
||||
/* These are undefined at zero. This is true even if
|
||||
C[LT]Z_DEFINED_VALUE_AT_ZERO is set, since what we're
|
||||
computing here is a user-visible property. */
|
||||
return 0;
|
||||
|
||||
case INTEGER_CST:
|
||||
return tree_int_cst_sgn (t) >= 0;
|
||||
case TRUNC_DIV_EXPR:
|
||||
|
@ -449,14 +449,23 @@ simplify_unary_operation (code, mode, op, op_mode)
|
||||
|
||||
case CLZ:
|
||||
arg0 &= GET_MODE_MASK (mode);
|
||||
val = GET_MODE_BITSIZE (mode) - floor_log2 (arg0) - 1;
|
||||
if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val))
|
||||
;
|
||||
else
|
||||
val = GET_MODE_BITSIZE (mode) - floor_log2 (arg0) - 1;
|
||||
break;
|
||||
|
||||
case CTZ:
|
||||
arg0 &= GET_MODE_MASK (mode);
|
||||
val = arg0 == 0
|
||||
? GET_MODE_BITSIZE (mode)
|
||||
: exact_log2 (arg0 & -arg0);
|
||||
if (arg0 == 0)
|
||||
{
|
||||
/* Even if the value at zero is undefined, we have to come
|
||||
up with some replacement. Seems good enough. */
|
||||
if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val))
|
||||
val = GET_MODE_BITSIZE (mode);
|
||||
}
|
||||
else
|
||||
val = exact_log2 (arg0 & -arg0);
|
||||
break;
|
||||
|
||||
case POPCOUNT:
|
||||
|
Loading…
Reference in New Issue
Block a user