mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-02 05:50:26 +08:00
rs6000.md (popcount<mode>2): Rewrite.
* config/rs6000/rs6000.md (popcount<mode>2): Rewrite. (parity<mode>2): New define_expand using rs6000_emit_parity. * config/rs6000/rs6000.c (rs6000_emit_popcount, rs6000_emit_parity): New functions. * config/rs6000/rs6000-protos.h (rs6000_emit_popcount, rs6000_emit_parity): Prototype here. * gcc.target/powerpc/popcount-1.c: New test case. * gcc.target/powerpc/parity-1.c: Likewise. From-SVN: r121653
This commit is contained in:
parent
7e0c3f57e0
commit
565ef4bafb
@ -1,3 +1,12 @@
|
||||
2007-02-06 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* config/rs6000/rs6000.md (popcount<mode>2): Rewrite.
|
||||
(parity<mode>2): New define_expand using rs6000_emit_parity.
|
||||
* config/rs6000/rs6000.c (rs6000_emit_popcount,
|
||||
rs6000_emit_parity): New functions.
|
||||
* config/rs6000/rs6000-protos.h (rs6000_emit_popcount,
|
||||
rs6000_emit_parity): Prototype here.
|
||||
|
||||
2007-02-06 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* lower-subreg.c (simple_move_operand): Reject CONST.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
|
||||
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
|
||||
|
||||
@ -106,6 +106,8 @@ extern bool rs6000_offsettable_memref_p (rtx);
|
||||
extern rtx rs6000_return_addr (int, rtx);
|
||||
extern void rs6000_output_symbol_ref (FILE*, rtx);
|
||||
extern HOST_WIDE_INT rs6000_initial_elimination_offset (int, int);
|
||||
extern void rs6000_emit_popcount (rtx, rtx);
|
||||
extern void rs6000_emit_parity (rtx, rtx);
|
||||
|
||||
extern rtx rs6000_machopic_legitimize_pic_address (rtx, enum machine_mode,
|
||||
rtx);
|
||||
|
@ -20239,6 +20239,102 @@ rs6000_emit_swdivdf (rtx res, rtx n, rtx d)
|
||||
gen_rtx_MULT (DFmode, v0, y3), u0)));
|
||||
}
|
||||
|
||||
|
||||
/* Emit popcount intrinsic on TARGET_POPCNTB targets. DST is the
|
||||
target, and SRC is the argument operand. */
|
||||
|
||||
void
|
||||
rs6000_emit_popcount (rtx dst, rtx src)
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (dst);
|
||||
rtx tmp1, tmp2;
|
||||
|
||||
tmp1 = gen_reg_rtx (mode);
|
||||
|
||||
if (mode == SImode)
|
||||
{
|
||||
emit_insn (gen_popcntbsi2 (tmp1, src));
|
||||
tmp2 = expand_mult (SImode, tmp1, GEN_INT (0x01010101),
|
||||
NULL_RTX, 0);
|
||||
tmp2 = force_reg (SImode, tmp2);
|
||||
emit_insn (gen_lshrsi3 (dst, tmp2, GEN_INT (24)));
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_insn (gen_popcntbdi2 (tmp1, src));
|
||||
tmp2 = expand_mult (DImode, tmp1,
|
||||
GEN_INT ((HOST_WIDE_INT)
|
||||
0x01010101 << 32 | 0x01010101),
|
||||
NULL_RTX, 0);
|
||||
tmp2 = force_reg (DImode, tmp2);
|
||||
emit_insn (gen_lshrdi3 (dst, tmp2, GEN_INT (56)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Emit parity intrinsic on TARGET_POPCNTB targets. DST is the
|
||||
target, and SRC is the argument operand. */
|
||||
|
||||
void
|
||||
rs6000_emit_parity (rtx dst, rtx src)
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (dst);
|
||||
rtx tmp;
|
||||
|
||||
tmp = gen_reg_rtx (mode);
|
||||
if (mode == SImode)
|
||||
{
|
||||
/* Is mult+shift >= shift+xor+shift+xor? */
|
||||
if (rs6000_cost->mulsi_const >= COSTS_N_INSNS (3))
|
||||
{
|
||||
rtx tmp1, tmp2, tmp3, tmp4;
|
||||
|
||||
tmp1 = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_popcntbsi2 (tmp1, src));
|
||||
|
||||
tmp2 = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_lshrsi3 (tmp2, tmp1, GEN_INT (16)));
|
||||
tmp3 = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_xorsi3 (tmp3, tmp1, tmp2));
|
||||
|
||||
tmp4 = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_lshrsi3 (tmp4, tmp3, GEN_INT (8)));
|
||||
emit_insn (gen_xorsi3 (tmp, tmp3, tmp4));
|
||||
}
|
||||
else
|
||||
rs6000_emit_popcount (tmp, src);
|
||||
emit_insn (gen_andsi3 (dst, tmp, const1_rtx));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Is mult+shift >= shift+xor+shift+xor+shift+xor? */
|
||||
if (rs6000_cost->muldi >= COSTS_N_INSNS (5))
|
||||
{
|
||||
rtx tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
|
||||
|
||||
tmp1 = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_popcntbdi2 (tmp1, src));
|
||||
|
||||
tmp2 = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_lshrdi3 (tmp2, tmp1, GEN_INT (32)));
|
||||
tmp3 = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_xordi3 (tmp3, tmp1, tmp2));
|
||||
|
||||
tmp4 = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_lshrdi3 (tmp4, tmp3, GEN_INT (16)));
|
||||
tmp5 = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_xordi3 (tmp5, tmp3, tmp4));
|
||||
|
||||
tmp6 = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_lshrdi3 (tmp6, tmp5, GEN_INT (8)));
|
||||
emit_insn (gen_xordi3 (tmp, tmp5, tmp6));
|
||||
}
|
||||
else
|
||||
rs6000_emit_popcount (tmp, src);
|
||||
emit_insn (gen_anddi3 (dst, tmp, const1_rtx));
|
||||
}
|
||||
}
|
||||
|
||||
/* Return an RTX representing where to find the function value of a
|
||||
function returning MODE. */
|
||||
static rtx
|
||||
|
@ -2161,26 +2161,6 @@
|
||||
operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));
|
||||
})
|
||||
|
||||
(define_expand "popcount<mode>2"
|
||||
[(set (match_dup 2)
|
||||
(unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
|
||||
UNSPEC_POPCNTB))
|
||||
(set (match_dup 3)
|
||||
(mult:GPR (match_dup 2) (match_dup 4)))
|
||||
(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
|
||||
(lshiftrt:GPR (match_dup 3) (match_dup 5)))]
|
||||
"TARGET_POPCNTB"
|
||||
{
|
||||
operands[2] = gen_reg_rtx (<MODE>mode);
|
||||
operands[3] = gen_reg_rtx (<MODE>mode);
|
||||
operands[4] = force_reg (<MODE>mode,
|
||||
<MODE>mode == SImode
|
||||
? GEN_INT (0x01010101)
|
||||
: GEN_INT ((HOST_WIDE_INT)
|
||||
0x01010101 << 32 | 0x01010101));
|
||||
operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 8);
|
||||
})
|
||||
|
||||
(define_insn "popcntb<mode>2"
|
||||
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
|
||||
(unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
|
||||
@ -2188,6 +2168,24 @@
|
||||
"TARGET_POPCNTB"
|
||||
"popcntb %0,%1")
|
||||
|
||||
(define_expand "popcount<mode>2"
|
||||
[(use (match_operand:GPR 0 "gpc_reg_operand" "=r"))
|
||||
(use (match_operand:GPR 1 "gpc_reg_operand" "r"))]
|
||||
"TARGET_POPCNTB"
|
||||
{
|
||||
rs6000_emit_popcount (operands[0], operands[1]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "parity<mode>2"
|
||||
[(use (match_operand:GPR 0 "gpc_reg_operand" "=r"))
|
||||
(use (match_operand:GPR 1 "gpc_reg_operand" "r"))]
|
||||
"TARGET_POPCNTB"
|
||||
{
|
||||
rs6000_emit_parity (operands[0], operands[1]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "mulsi3"
|
||||
[(use (match_operand:SI 0 "gpc_reg_operand" ""))
|
||||
(use (match_operand:SI 1 "gpc_reg_operand" ""))
|
||||
|
9
gcc/testsuite/gcc.target/powerpc/parity-1.c
Normal file
9
gcc/testsuite/gcc.target/powerpc/parity-1.c
Normal file
@ -0,0 +1,9 @@
|
||||
/* { dg-do compile { target { ilp32 } } } */
|
||||
/* { dg-options "-O2 -mcpu=power6" } */
|
||||
/* { dg-final { scan-assembler "popcntb" } } */
|
||||
/* { dg-final { scan-assembler-not "mullw" } } */
|
||||
|
||||
int foo(int x)
|
||||
{
|
||||
return __builtin_parity(x);
|
||||
}
|
9
gcc/testsuite/gcc.target/powerpc/popcount-1.c
Normal file
9
gcc/testsuite/gcc.target/powerpc/popcount-1.c
Normal file
@ -0,0 +1,9 @@
|
||||
/* { dg-do compile { target { ilp32 } } } */
|
||||
/* { dg-options "-O2 -mcpu=power6" } */
|
||||
/* { dg-final { scan-assembler "popcntb" } } */
|
||||
/* { dg-final { scan-assembler-not "mullw" } } */
|
||||
|
||||
int foo(int x)
|
||||
{
|
||||
return __builtin_popcount(x);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user