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:
Richard Henderson 2003-02-05 14:37:54 -08:00 committed by Richard Henderson
parent 8d705469aa
commit 7dba8395e2
12 changed files with 126 additions and 112 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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) \

View File

@ -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 *));

View File

@ -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

View File

@ -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 */

View File

@ -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"

View File

@ -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 */

View File

@ -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.

View File

@ -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

View File

@ -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:

View File

@ -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: