Commit 8f4773ea by Richard Henderson Committed by Richard Henderson

longlong.h [__alpha] (count_leading_zeros): New.

        * longlong.h [__alpha] (count_leading_zeros): New.
        (count_trailing_zeros): New.
        (COUNT_LEADING_ZEROS_0): New.

        * config/alpha/alpha.c (alpha_zero_comparison_operator): New.
        (alpha_split_conditional_move): New.
        * config/alpha/alpha-protos.h: Prototype them.
        * config/alpha/alpha.h (PREDICATE_CODES): Update.
        (CPP_CPU_DEFAULT_SPEC): Fix typo for EV67.
        * config/alpha/alpha.md: Update ffs cix commentary.
        (*ze_and_ne): New.
        (*nabssf2, *nabsdf2): New.
        (*mov[qhsd]icc_internal): Use add_operand.
        (if_then_else constant splitters): New.
        (*cmp_sadd_di, *cmp_sadd_si, *cmp_sadd_sidi): New.
        (*cmp_ssub_di, *cmp_ssub_si, *cmp_ssub_sidi): New.

From-SVN: r34250
parent e2c7a29e
2000-05-29 Richard Henderson <rth@cygnus.com>
* longlong.h [__alpha] (count_leading_zeros): New.
(count_trailing_zeros): New.
(COUNT_LEADING_ZEROS_0): New.
* config/alpha/alpha.c (alpha_zero_comparison_operator): New.
(alpha_split_conditional_move): New.
* config/alpha/alpha-protos.h: Prototype them.
* config/alpha/alpha.h (PREDICATE_CODES): Update.
(CPP_CPU_DEFAULT_SPEC): Fix typo for EV67.
* config/alpha/alpha.md: Update ffs cix commentary.
(*ze_and_ne): New.
(*nabssf2, *nabsdf2): New.
(*mov[qhsd]icc_internal): Use add_operand.
(if_then_else constant splitters): New.
(*cmp_sadd_di, *cmp_sadd_si, *cmp_sadd_sidi): New.
(*cmp_ssub_di, *cmp_ssub_si, *cmp_ssub_sidi): New.
2000-05-29 Richard Henderson <rth@cygnus.com>
* combine.c (force_to_mode) [MINUS]: Convert subtraction from
a constant to NEG or NOT when conditions allow.
......@@ -57,6 +57,7 @@ extern int input_operand PARAMS ((rtx, enum machine_mode));
extern int current_file_function_operand PARAMS ((rtx, enum machine_mode));
extern int call_operand PARAMS ((rtx, enum machine_mode));
extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int alpha_zero_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int alpha_swapped_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int signed_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int alpha_fp_comparison_operator PARAMS ((rtx, enum machine_mode));
......@@ -83,6 +84,8 @@ extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT,
extern void alpha_emit_floatuns PARAMS ((rtx[]));
extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code));
extern rtx alpha_emit_conditional_move PARAMS ((rtx, enum machine_mode));
extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx,
rtx, rtx));
extern void alpha_emit_xfloating_arith PARAMS ((enum rtx_code, rtx[]));
extern void alpha_emit_xfloating_cvt PARAMS ((enum rtx_code, rtx[]));
extern void alpha_split_tfmode_pair PARAMS ((rtx[]));
......
......@@ -735,6 +735,23 @@ alpha_comparison_operator (op, mode)
|| code == LEU || code == LTU);
}
/* Return 1 if OP is a valid Alpha comparison operator against zero.
Here we know which comparisons are valid in which insn. */
int
alpha_zero_comparison_operator (op, mode)
register rtx op;
enum machine_mode mode;
{
enum rtx_code code = GET_CODE (op);
if (mode != GET_MODE (op) && mode != VOIDmode)
return 0;
return (code == EQ || code == NE || code == LE || code == LT
|| code == LEU || code == LTU);
}
/* Return 1 if OP is a valid Alpha swapped comparison operator. */
int
......@@ -1834,6 +1851,90 @@ alpha_emit_conditional_move (cmp, mode)
emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
}
/* Simplify a conditional move of two constants into a setcc with
arithmetic. This is done with a splitter since combine would
just undo the work if done during code generation. It also catches
cases we wouldn't have before cse. */
int
alpha_split_conditional_move (code, dest, cond, t_rtx, f_rtx)
enum rtx_code code;
rtx dest, cond, t_rtx, f_rtx;
{
HOST_WIDE_INT t, f, diff;
enum machine_mode mode;
rtx target, subtarget, tmp;
mode = GET_MODE (dest);
t = INTVAL (t_rtx);
f = INTVAL (f_rtx);
diff = t - f;
if (((code == NE || code == EQ) && diff < 0)
|| (code == GE || code == GT))
{
code = reverse_condition (code);
diff = t, t = f, f = diff;
diff = t - f;
}
subtarget = target = dest;
if (mode != DImode)
{
target = gen_lowpart (DImode, dest);
if (! no_new_pseudos)
subtarget = gen_reg_rtx (DImode);
else
subtarget = target;
}
if (f == 0 && exact_log2 (diff) > 0
/* On EV6, we've got enough shifters to make non-arithmatic shifts
viable over a longer latency cmove. On EV5, the E0 slot is a
scarce resource, and on EV4 shift has the same latency as a cmove. */
&& (diff <= 8 || alpha_cpu == PROCESSOR_EV6))
{
tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
emit_insn (gen_rtx_SET (VOIDmode, subtarget, tmp));
tmp = gen_rtx_ASHIFT (DImode, subtarget, GEN_INT (exact_log2 (t)));
emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
}
else if (f == 0 && t == -1)
{
tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
emit_insn (gen_rtx_SET (VOIDmode, subtarget, tmp));
emit_insn (gen_negdi2 (target, subtarget));
}
else if (diff == 1 || diff == 4 || diff == 8)
{
rtx add_op;
tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
emit_insn (gen_rtx_SET (VOIDmode, subtarget, tmp));
if (diff == 1)
emit_insn (gen_adddi3 (target, subtarget, GEN_INT (f)));
else
{
add_op = GEN_INT (f);
if (sext_add_operand (add_op, mode))
{
tmp = gen_rtx_MULT (DImode, subtarget, GEN_INT (diff));
tmp = gen_rtx_PLUS (DImode, tmp, add_op);
emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
}
else
return 0;
}
}
else
return 0;
return 1;
}
/* Look up the function X_floating library function name for the
given operation. */
......
......@@ -290,7 +290,7 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
#ifndef CPP_CPU_DEFAULT_SPEC
# if TARGET_CPU_DEFAULT & MASK_CPU_EV6
# if TARGET_CPU_DEFAULT & MAX_CIX
# if TARGET_CPU_DEFAULT & MASK_CIX
# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV67_SPEC
# else
# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV6_SPEC
......@@ -2333,6 +2333,7 @@ do { \
{"mode_width_operand", {CONST_INT}}, \
{"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \
{"alpha_zero_comparison_operator", {EQ, NE, LE, LT, LEU, LTU}}, \
{"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}}, \
{"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \
{"alpha_fp_comparison_operator", {EQ, LE, LT, UNORDERED}}, \
......
......@@ -169,6 +169,39 @@
extern UDItype __udiv_qrnnd PARAMS ((UDItype *, UDItype, UDItype, UDItype));
#define UDIV_TIME 220
#endif /* LONGLONG_STANDALONE */
#ifdef __alpha_cix__
#define count_leading_zeros(COUNT,X) \
__asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X))
#define count_trailing_zeros(COUNT,X) \
__asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X))
#define COUNT_LEADING_ZEROS_0 64
#else
extern const UQItype __clz_tab[];
#define count_leading_zeros(COUNT,X) \
do { \
UDItype __xr = (X), __t, __a; \
__asm__("cmpbge %1,%2,%0" : "=r"(__t) : "r"(~__xr), "r"(-1)); \
__a = __clz_tab[__t ^ 0xff] - 1; \
__asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \
(COUNT) = 64 - (__clz_tab[__t] + __a*8); \
} while (0)
#define count_trailing_zeros(COUNT,X) \
do { \
UDItype __xr = (X), __t, __a; \
__asm__("cmpbge %1,%2,%0" : "=r"(__t) : "r"(~__xr), "r"(-1)); \
__t = ~__t & -~__t; \
__a = ((__t & 0xCC) != 0) * 2; \
__a += ((__t & 0xF0) != 0) * 4; \
__a += ((__t & 0xAA) != 0); \
__asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \
__a <<= 3; \
__t &= -__t; \
__a += ((__t & 0xCC) != 0) * 2; \
__a += ((__t & 0xF0) != 0) * 4; \
__a += ((__t & 0xAA) != 0); \
(COUNT) = __a; \
} while (0)
#endif /* __alpha_cix__ */
#endif /* __alpha */
#if defined (__arc__) && W_TYPE_SIZE == 32
......
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