Commit 565ef4ba by Roger Sayle Committed by Roger Sayle

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
parent 7e0c3f57
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> 2007-02-06 Ian Lance Taylor <iant@google.com>
* lower-subreg.c (simple_move_operand): Reject CONST. * lower-subreg.c (simple_move_operand): Reject CONST.
......
/* Definitions of target machine for GNU compiler, for IBM RS/6000. /* 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. Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
...@@ -106,6 +106,8 @@ extern bool rs6000_offsettable_memref_p (rtx); ...@@ -106,6 +106,8 @@ extern bool rs6000_offsettable_memref_p (rtx);
extern rtx rs6000_return_addr (int, rtx); extern rtx rs6000_return_addr (int, rtx);
extern void rs6000_output_symbol_ref (FILE*, rtx); extern void rs6000_output_symbol_ref (FILE*, rtx);
extern HOST_WIDE_INT rs6000_initial_elimination_offset (int, int); 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, extern rtx rs6000_machopic_legitimize_pic_address (rtx, enum machine_mode,
rtx); rtx);
......
...@@ -20239,6 +20239,102 @@ rs6000_emit_swdivdf (rtx res, rtx n, rtx d) ...@@ -20239,6 +20239,102 @@ rs6000_emit_swdivdf (rtx res, rtx n, rtx d)
gen_rtx_MULT (DFmode, v0, y3), u0))); 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 /* Return an RTX representing where to find the function value of a
function returning MODE. */ function returning MODE. */
static rtx static rtx
......
...@@ -2161,26 +2161,6 @@ ...@@ -2161,26 +2161,6 @@
operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)); 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" (define_insn "popcntb<mode>2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r") [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")] (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
...@@ -2188,6 +2168,24 @@ ...@@ -2188,6 +2168,24 @@
"TARGET_POPCNTB" "TARGET_POPCNTB"
"popcntb %0,%1") "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" (define_expand "mulsi3"
[(use (match_operand:SI 0 "gpc_reg_operand" "")) [(use (match_operand:SI 0 "gpc_reg_operand" ""))
(use (match_operand:SI 1 "gpc_reg_operand" "")) (use (match_operand:SI 1 "gpc_reg_operand" ""))
......
/* { 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);
}
/* { 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);
}
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