Hi! Another broken define_insn, bzhi has the middle operand r/m, others are r. But, combine would usually not match memory loads, because the pattern had non-canonical order of AND operands, thus it would never match there, and only could result in broken code if the RA decided to use memory instead of register.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8? 2013-06-27 Jakub Jelinek <ja...@redhat.com> PR target/57623 * config/i386/i386.md (bmi2_bzhi_<mode>3): Swap AND arguments to match RTL canonicalization. Swap predicates and constraints of operand 1 and 2. * gcc.target/i386/bmi2-bzhi-1.c: New test. --- gcc/config/i386/i386.md.jj 2013-06-19 19:28:29.000000000 +0200 +++ gcc/config/i386/i386.md 2013-06-27 13:51:21.771071326 +0200 @@ -11733,9 +11733,9 @@ (define_insn "*bmi_blsr_<mode>" ;; BMI2 instructions. (define_insn "bmi2_bzhi_<mode>3" [(set (match_operand:SWI48 0 "register_operand" "=r") - (and:SWI48 (match_operand:SWI48 1 "register_operand" "r") - (lshiftrt:SWI48 (const_int -1) - (match_operand:SWI48 2 "nonimmediate_operand" "rm")))) + (and:SWI48 (lshiftrt:SWI48 (const_int -1) + (match_operand:SWI48 2 "register_operand" "r")) + (match_operand:SWI48 1 "nonimmediate_operand" "rm"))) (clobber (reg:CC FLAGS_REG))] "TARGET_BMI2" "bzhi\t{%2, %1, %0|%0, %1, %2}" --- gcc/testsuite/gcc.target/i386/bmi2-bzhi-1.c.jj 2013-06-27 13:43:03.858202104 +0200 +++ gcc/testsuite/gcc.target/i386/bmi2-bzhi-1.c 2013-06-27 13:43:22.026140832 +0200 @@ -0,0 +1,31 @@ +/* PR target/57623 */ +/* { dg-do assemble { target bmi2 } } */ +/* { dg-options "-O2 -mbmi2" } */ + +#include <x86intrin.h> + +unsigned int +f1 (unsigned int x, unsigned int *y) +{ + return _bzhi_u32 (x, *y); +} + +unsigned int +f2 (unsigned int *x, unsigned int y) +{ + return _bzhi_u32 (*x, y); +} + +#ifdef __x86_64__ +unsigned long long +f3 (unsigned long long x, unsigned long long *y) +{ + return _bzhi_u64 (x, *y); +} + +unsigned long long +f4 (unsigned long long *x, unsigned long long y) +{ + return _bzhi_u64 (*x, y); +} +#endif Jakub