re PR target/68647 (__builtin_popcountll doesn't generate popcnt instructions when targeting -mpopcnt on x86_32)
PR target/68647 * optabs.c (expand_doubleword_popcount, expand_doubleword_parity): New functions. (expand_unop): Use them. * gcc.target/i386/pr68647.c: New test. From-SVN: r231201
This commit is contained in:
parent
d6221ad458
commit
8923e02ee4
|
@ -1,3 +1,10 @@
|
||||||
|
2015-12-02 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR target/68647
|
||||||
|
* optabs.c (expand_doubleword_popcount, expand_doubleword_parity):
|
||||||
|
New functions.
|
||||||
|
(expand_unop): Use them.
|
||||||
|
|
||||||
2015-12-02 Marek Polacek <polacek@redhat.com>
|
2015-12-02 Marek Polacek <polacek@redhat.com>
|
||||||
|
|
||||||
PR c++/68653
|
PR c++/68653
|
||||||
|
|
73
gcc/optabs.c
73
gcc/optabs.c
|
@ -2223,6 +2223,58 @@ expand_doubleword_clz (machine_mode mode, rtx op0, rtx target)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try calculating popcount of a double-word quantity as two popcount's of
|
||||||
|
word-sized quantities and summing up the results. */
|
||||||
|
static rtx
|
||||||
|
expand_doubleword_popcount (machine_mode mode, rtx op0, rtx target)
|
||||||
|
{
|
||||||
|
rtx t0, t1, t;
|
||||||
|
rtx_insn *seq;
|
||||||
|
|
||||||
|
start_sequence ();
|
||||||
|
|
||||||
|
t0 = expand_unop_direct (word_mode, popcount_optab,
|
||||||
|
operand_subword_force (op0, 0, mode), NULL_RTX,
|
||||||
|
true);
|
||||||
|
t1 = expand_unop_direct (word_mode, popcount_optab,
|
||||||
|
operand_subword_force (op0, 1, mode), NULL_RTX,
|
||||||
|
true);
|
||||||
|
if (!t0 || !t1)
|
||||||
|
{
|
||||||
|
end_sequence ();
|
||||||
|
return NULL_RTX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we were not given a target, use a word_mode register, not a
|
||||||
|
'mode' register. The result will fit, and nobody is expecting
|
||||||
|
anything bigger (the return type of __builtin_popcount* is int). */
|
||||||
|
if (!target)
|
||||||
|
target = gen_reg_rtx (word_mode);
|
||||||
|
|
||||||
|
t = expand_binop (word_mode, add_optab, t0, t1, target, 0, OPTAB_DIRECT);
|
||||||
|
|
||||||
|
seq = get_insns ();
|
||||||
|
end_sequence ();
|
||||||
|
|
||||||
|
add_equal_note (seq, t, POPCOUNT, op0, 0);
|
||||||
|
emit_insn (seq);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try calculating
|
||||||
|
(parity:wide x)
|
||||||
|
as
|
||||||
|
(parity:narrow (low (x) ^ high (x))) */
|
||||||
|
static rtx
|
||||||
|
expand_doubleword_parity (machine_mode mode, rtx op0, rtx target)
|
||||||
|
{
|
||||||
|
rtx t = expand_binop (word_mode, xor_optab,
|
||||||
|
operand_subword_force (op0, 0, mode),
|
||||||
|
operand_subword_force (op0, 1, mode),
|
||||||
|
NULL_RTX, 0, OPTAB_DIRECT);
|
||||||
|
return expand_unop (word_mode, parity_optab, t, target, true);
|
||||||
|
}
|
||||||
|
|
||||||
/* Try calculating
|
/* Try calculating
|
||||||
(bswap:narrow x)
|
(bswap:narrow x)
|
||||||
as
|
as
|
||||||
|
@ -2665,6 +2717,27 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
|
||||||
goto try_libcall;
|
goto try_libcall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unoptab == popcount_optab
|
||||||
|
&& GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
|
||||||
|
&& optab_handler (unoptab, word_mode) != CODE_FOR_nothing
|
||||||
|
&& optimize_insn_for_speed_p ())
|
||||||
|
{
|
||||||
|
temp = expand_doubleword_popcount (mode, op0, target);
|
||||||
|
if (temp)
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unoptab == parity_optab
|
||||||
|
&& GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
|
||||||
|
&& (optab_handler (unoptab, word_mode) != CODE_FOR_nothing
|
||||||
|
|| optab_handler (popcount_optab, word_mode) != CODE_FOR_nothing)
|
||||||
|
&& optimize_insn_for_speed_p ())
|
||||||
|
{
|
||||||
|
temp = expand_doubleword_parity (mode, op0, target);
|
||||||
|
if (temp)
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
/* Widening (or narrowing) bswap needs special treatment. */
|
/* Widening (or narrowing) bswap needs special treatment. */
|
||||||
if (unoptab == bswap_optab)
|
if (unoptab == bswap_optab)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2015-12-02 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR target/68647
|
||||||
|
* gcc.target/i386/pr68647.c: New test.
|
||||||
|
|
||||||
2015-12-02 Marek Polacek <polacek@redhat.com>
|
2015-12-02 Marek Polacek <polacek@redhat.com>
|
||||||
|
|
||||||
PR c++/68653
|
PR c++/68653
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* PR target/68647 */
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O2 -mpopcnt" } */
|
||||||
|
|
||||||
|
int
|
||||||
|
f1 (unsigned long long a)
|
||||||
|
{
|
||||||
|
return __builtin_popcountll (a);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
f2 (unsigned long long a)
|
||||||
|
{
|
||||||
|
return __builtin_parityll (a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* { dg-final { scan-assembler-not "__popcountdi2" } } */
|
||||||
|
/* { dg-final { scan-assembler-not "__paritydi2" } } */
|
Loading…
Reference in New Issue