i386: Use bzhi for x & ((1 << y) - 1) or x & ((1U << y) - 1) [PR93346]

The bzhi patterns are quite complicated because they need to accurately
describe the behavior of the instruction for all input values.
The following patterns are simple and make bzhi recognizable even for
cases where not all input values are valid, because the user used
a shift, in which case the low 8 bit of the last operand need to be in
between 0 and precision-1.

2020-01-23  Jakub Jelinek  <jakub@redhat.com>

	PR target/93346
	* config/i386/i386.md (*bmi2_bzhi_<mode>3_2, *bmi2_bzhi_<mode>3_3):
	New define_insn patterns.

	* gcc.target/i386/pr93346.c: New test.
This commit is contained in:
Jakub Jelinek 2020-01-23 12:39:13 +01:00
parent 8a990ffafa
commit 9592f639ff
4 changed files with 116 additions and 0 deletions
gcc
ChangeLog
config/i386
testsuite
ChangeLog
gcc.target/i386

View file

@ -1,3 +1,9 @@
2020-01-23 Jakub Jelinek <jakub@redhat.com>
PR target/93346
* config/i386/i386.md (*bmi2_bzhi_<mode>3_2, *bmi2_bzhi_<mode>3_3):
New define_insn patterns.
2020-01-23 Richard Sandiford <richard.sandiford@arm.com>
* doc/sourcebuild.texi (check-function-bodies): Add an

View file

@ -14304,6 +14304,35 @@
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
(define_insn "*bmi2_bzhi_<mode>3_2"
[(set (match_operand:SWI48 0 "register_operand" "=r")
(and:SWI48
(plus:SWI48
(ashift:SWI48 (const_int 1)
(match_operand:QI 2 "register_operand" "r"))
(const_int -1))
(match_operand:SWI48 1 "nonimmediate_operand" "rm")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI2"
"bzhi\t{%<k>2, %1, %0|%0, %1, %<k>2}"
[(set_attr "type" "bitmanip")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
(define_insn "*bmi2_bzhi_<mode>3_3"
[(set (match_operand:SWI48 0 "register_operand" "=r")
(and:SWI48
(not:SWI48
(ashift:SWI48 (const_int -1)
(match_operand:QI 2 "register_operand" "r")))
(match_operand:SWI48 1 "nonimmediate_operand" "rm")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI2"
"bzhi\t{%<k>2, %1, %0|%0, %1, %<k>2}"
[(set_attr "type" "bitmanip")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
(define_insn "bmi2_pdep_<mode>3"
[(set (match_operand:SWI48 0 "register_operand" "=r")
(unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r")

View file

@ -1,3 +1,8 @@
2020-01-23 Jakub Jelinek <jakub@redhat.com>
PR target/93346
* gcc.target/i386/pr93346.c: New test.
2020-01-23 Martin Sebor <msebor@redhat.com>
PR c/84919

View file

@ -0,0 +1,76 @@
/* PR target/93346 */
/* { dg-do compile } */
/* { dg-options "-O2 -mbmi2" } */
/* { dg-final { scan-assembler-times "\tbzhi\t" 12 } } */
unsigned int
f1 (unsigned int x, unsigned int y)
{
return x & ((1 << y) - 1);
}
unsigned int
f2 (unsigned int x, unsigned int y)
{
return x & ((1U << y) - 1);
}
int
f3 (int x, unsigned int y)
{
return x & ((1 << y) - 1);
}
unsigned long
f4 (unsigned long x, unsigned int y)
{
return x & ((1L << y) - 1);
}
unsigned long
f5 (unsigned long x, unsigned int y)
{
return x & ((1UL << y) - 1);
}
long
f6 (long x, unsigned int y)
{
return x & ((1L << y) - 1);
}
unsigned int
f7 (unsigned int x, int y)
{
return x & ((1 << y) - 1);
}
unsigned int
f8 (unsigned int x, int y)
{
return x & ((1U << y) - 1);
}
int
f9 (int x, int y)
{
return x & ((1 << y) - 1);
}
unsigned long
f10 (unsigned long x, int y)
{
return x & ((1L << y) - 1);
}
unsigned long
f11 (unsigned long x, int y)
{
return x & ((1UL << y) - 1);
}
long
f12 (long x, int y)
{
return x & ((1L << y) - 1);
}