Commit 2e6834d3 by Richard Henderson Committed by Richard Henderson

i386.md (bswapsi_1): Rename from bswapsi2, remove flags clobber.

        * config/i386/i386.md (bswapsi_1): Rename from bswapsi2,
        remove flags clobber.
        (bswapsi2): New expander, emit code for !TARGET_BSWAP.
        (bswaphi_lowpart): New.
        (bswapdi2): Rename from bswapdi2_rex, remove flags clobber,
        remove TARGET_BSWAP test.  Delete expander of the same name.

        * optabs.c (widen_bswap, expand_doubleword_bswap): New.
        (expand_unop): Use them.

From-SVN: r121884
parent a23132e1
2007-02-13 Richard Henderson <rth@redhat.com>
* config/i386/i386.md (bswapsi_1): Rename from bswapsi2,
remove flags clobber.
(bswapsi2): New expander, emit code for !TARGET_BSWAP.
(bswaphi_lowpart): New.
(bswapdi2): Rename from bswapdi2_rex, remove flags clobber,
remove TARGET_BSWAP test. Delete expander of the same name.
* optabs.c (widen_bswap, expand_doubleword_bswap): New.
(expand_unop): Use them.
2007-02-13 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (cmpdi_ccno_1_rex64, *cmpsi_ccno_1,
......
......@@ -14994,43 +14994,50 @@
(set_attr "type" "bitmanip")
(set_attr "mode" "SI")])
(define_insn "bswapsi2"
(define_expand "bswapsi2"
[(set (match_operand:SI 0 "register_operand" "")
(bswap:SI (match_operand:SI 1 "register_operand" "")))]
""
{
if (!TARGET_BSWAP)
{
rtx x = operands[0];
emit_move_insn (x, operands[1]);
emit_insn (gen_bswaphi_lowpart (gen_lowpart (HImode, x)));
emit_insn (gen_rotlsi3 (x, x, GEN_INT (16)));
emit_insn (gen_bswaphi_lowpart (gen_lowpart (HImode, x)));
DONE;
}
})
(define_insn "*bswapsi_1"
[(set (match_operand:SI 0 "register_operand" "=r")
(bswap:SI (match_operand:SI 1 "register_operand" "0")))
(clobber (reg:CC FLAGS_REG))]
(bswap:SI (match_operand:SI 1 "register_operand" "0")))]
"TARGET_BSWAP"
"bswap\t%k0"
"bswap\t%0"
[(set_attr "prefix_0f" "1")
(set_attr "length" "2")])
(define_insn "*bswapdi2_rex"
(define_insn "bswaphi_lowpart"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+Q"))
(bswap:HI (match_dup 0)))]
""
"xchg{b}\t%h0, %b0"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "double")])
(define_insn "bswapdi2"
[(set (match_operand:DI 0 "register_operand" "=r")
(bswap:DI (match_operand:DI 1 "register_operand" "0")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && TARGET_BSWAP"
(bswap:DI (match_operand:DI 1 "register_operand" "0")))]
"TARGET_64BIT"
"bswap\t%0"
[(set_attr "prefix_0f" "1")
(set_attr "length" "3")])
(define_expand "bswapdi2"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(bswap:DI (match_operand:DI 1 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_BSWAP"
{
if (!TARGET_64BIT)
{
rtx tmp1, tmp2;
tmp1 = gen_reg_rtx (SImode);
tmp2 = gen_reg_rtx (SImode);
emit_insn (gen_bswapsi2 (tmp1, gen_lowpart (SImode, operands[1])));
emit_insn (gen_bswapsi2 (tmp2, gen_highpart (SImode, operands[1])));
emit_move_insn (gen_lowpart (SImode, operands[0]), tmp2);
emit_move_insn (gen_highpart (SImode, operands[0]), tmp1);
DONE;
}
})
(define_expand "clzdi2"
[(parallel
[(set (match_operand:DI 0 "register_operand" "")
......
......@@ -2401,6 +2401,73 @@ widen_clz (enum machine_mode mode, rtx op0, rtx target)
return 0;
}
/* Try calculating
(bswap:narrow x)
as
(lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */
static rtx
widen_bswap (enum machine_mode mode, rtx op0, rtx target)
{
enum mode_class class = GET_MODE_CLASS (mode);
enum machine_mode wider_mode;
rtx x, last;
if (!CLASS_HAS_WIDER_MODES_P (class))
return NULL_RTX;
for (wider_mode = GET_MODE_WIDER_MODE (mode);
wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
if (bswap_optab->handlers[wider_mode].insn_code != CODE_FOR_nothing)
goto found;
return NULL_RTX;
found:
last = get_last_insn ();
x = widen_operand (op0, wider_mode, mode, true, true);
x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
if (x != 0)
x = expand_shift (RSHIFT_EXPR, wider_mode, x,
size_int (GET_MODE_BITSIZE (wider_mode)
- GET_MODE_BITSIZE (mode)),
NULL_RTX, true);
if (x != 0)
{
if (target == 0)
target = gen_reg_rtx (mode);
emit_move_insn (target, gen_lowpart (mode, x));
}
else
delete_insns_since (last);
return target;
}
/* Try calculating bswap as two bswaps of two word-sized operands. */
static rtx
expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
{
rtx t0, t1;
t1 = expand_unop (word_mode, bswap_optab,
operand_subword_force (op, 0, mode), NULL_RTX, true);
t0 = expand_unop (word_mode, bswap_optab,
operand_subword_force (op, 1, mode), NULL_RTX, true);
if (target == 0)
target = gen_reg_rtx (mode);
if (REG_P (target))
emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
emit_move_insn (operand_subword (target, 0, 1, mode), t0);
emit_move_insn (operand_subword (target, 1, 1, mode), t1);
return target;
}
/* Try calculating (parity x) as (and (popcount x) 1), where
popcount can also be done in a wider mode. */
static rtx
......@@ -2639,9 +2706,23 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
goto try_libcall;
}
/* We can't widen a bswap. */
/* Widening (or narrowing) bswap needs special treatment. */
if (unoptab == bswap_optab)
goto try_libcall;
{
temp = widen_bswap (mode, op0, target);
if (temp)
return temp;
if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
&& unoptab->handlers[word_mode].insn_code != CODE_FOR_nothing)
{
temp = expand_doubleword_bswap (mode, op0, target);
if (temp)
return temp;
}
goto try_libcall;
}
if (CLASS_HAS_WIDER_MODES_P (class))
for (wider_mode = GET_MODE_WIDER_MODE (mode);
......
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