Message ID | ZrXFZe3BfMXUF8mF@tucnak |
---|---|
State | New |
Headers | show |
Series | i386: Fix up __builtin_ia32_b{extr{,i}_u{32,64},zhi_{s,d}i} folding [PR116287] | expand |
On Fri, Aug 9, 2024 at 9:29 AM Jakub Jelinek <jakub@redhat.com> wrote: > > Hi! > > The GENERIC folding of these builtins have cases where it folds to a > constant regardless of the value of the first operand. If so, we need > to use omit_one_operand to avoid throwing away side-effects in the first > operand if any. The cases which verify the first argument is INTEGER_CST > don't need that, INTEGER_CST doesn't have side-effects. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2024-08-09 Jakub Jelinek <jakub@redhat.com> > > PR target/116287 > * config/i386/i386.cc (ix86_fold_builtin) <case IX86_BUILTIN_BEXTR32>: > When folding into zero without checking whether first argument is > constant, use omit_one_operand. > (ix86_fold_builtin) <case IX86_BUILTIN_BZHI32>: Likewise. > > * gcc.target/i386/bmi-pr116287.c: New test. > * gcc.target/i386/bmi2-pr116287.c: New test. > * gcc.target/i386/tbm-pr116287.c: New test. Rubberstamp OK. Thanks, Uros. > > --- gcc/config/i386/i386.cc.jj 2024-08-01 14:33:28.172801480 +0200 > +++ gcc/config/i386/i386.cc 2024-08-08 12:55:12.780696418 +0200 > @@ -18549,9 +18549,11 @@ ix86_fold_builtin (tree fndecl, int n_ar > unsigned int prec = TYPE_PRECISION (TREE_TYPE (args[0])); > unsigned int start = tree_to_uhwi (args[1]); > unsigned int len = (start & 0xff00) >> 8; > + tree lhs_type = TREE_TYPE (TREE_TYPE (fndecl)); > start &= 0xff; > if (start >= prec || len == 0) > - res = 0; > + return omit_one_operand (lhs_type, build_zero_cst (lhs_type), > + args[0]); > else if (!tree_fits_uhwi_p (args[0])) > break; > else > @@ -18560,7 +18562,7 @@ ix86_fold_builtin (tree fndecl, int n_ar > len = prec; > if (len < HOST_BITS_PER_WIDE_INT) > res &= (HOST_WIDE_INT_1U << len) - 1; > - return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), res); > + return build_int_cstu (lhs_type, res); > } > break; > > @@ -18570,15 +18572,17 @@ ix86_fold_builtin (tree fndecl, int n_ar > if (tree_fits_uhwi_p (args[1])) > { > unsigned int idx = tree_to_uhwi (args[1]) & 0xff; > + tree lhs_type = TREE_TYPE (TREE_TYPE (fndecl)); > if (idx >= TYPE_PRECISION (TREE_TYPE (args[0]))) > return args[0]; > if (idx == 0) > - return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0); > + return omit_one_operand (lhs_type, build_zero_cst (lhs_type), > + args[0]); > if (!tree_fits_uhwi_p (args[0])) > break; > unsigned HOST_WIDE_INT res = tree_to_uhwi (args[0]); > res &= ~(HOST_WIDE_INT_M1U << idx); > - return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), res); > + return build_int_cstu (lhs_type, res); > } > break; > > --- gcc/testsuite/gcc.target/i386/bmi-pr116287.c.jj 2024-08-08 13:14:25.566827913 +0200 > +++ gcc/testsuite/gcc.target/i386/bmi-pr116287.c 2024-08-08 13:21:32.718312216 +0200 > @@ -0,0 +1,28 @@ > +/* PR target/116287 */ > +/* { dg-do run { target bmi } } */ > +/* { dg-options "-O2 -mbmi" } */ > + > +#include <x86intrin.h> > + > +#include "bmi-check.h" > + > +static void > +bmi_test () > +{ > + unsigned int a = 0; > + if (__builtin_ia32_bextr_u32 (a++, 0) != 0) > + abort (); > + if (__builtin_ia32_bextr_u32 (a++, 0x120) != 0) > + abort (); > + if (a != 2) > + abort (); > +#ifdef __x86_64__ > + unsigned long long b = 0; > + if (__builtin_ia32_bextr_u64 (b++, 0) != 0) > + abort (); > + if (__builtin_ia32_bextr_u64 (b++, 0x140) != 0) > + abort (); > + if (b != 2) > + abort (); > +#endif > +} > --- gcc/testsuite/gcc.target/i386/bmi2-pr116287.c.jj 2024-08-08 13:22:55.263246127 +0200 > +++ gcc/testsuite/gcc.target/i386/bmi2-pr116287.c 2024-08-08 13:30:44.851181267 +0200 > @@ -0,0 +1,24 @@ > +/* PR target/116287 */ > +/* { dg-do run { target bmi2 } } */ > +/* { dg-options "-O2 -mbmi2" } */ > + > +#include <x86intrin.h> > + > +#include "bmi2-check.h" > + > +static void > +bmi2_test () > +{ > + unsigned int a = 0; > + if (__builtin_ia32_bzhi_si (a++, 0) != 0) > + abort (); > + if (a != 1) > + abort (); > +#ifdef __x86_64__ > + unsigned long long b = 0; > + if (__builtin_ia32_bzhi_di (b++, 0) != 0) > + abort (); > + if (b != 1) > + abort (); > +#endif > +} > --- gcc/testsuite/gcc.target/i386/tbm-pr116287.c.jj 2024-08-08 13:14:48.453532722 +0200 > +++ gcc/testsuite/gcc.target/i386/tbm-pr116287.c 2024-08-08 13:22:36.940482770 +0200 > @@ -0,0 +1,29 @@ > +/* PR target/116287 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -mtbm -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-not "link_error \\\(\\\);" "optimized" } } */ > + > +#include <x86intrin.h> > + > +extern void link_error (void); > + > +void > +tbm_test () > +{ > + unsigned int a = 0; > + if (__builtin_ia32_bextri_u32 (a++, 0) != 0) > + link_error (); > + if (__builtin_ia32_bextri_u32 (a++, 0x120) != 0) > + link_error (); > + if (a != 2) > + link_error (); > +#ifdef __x86_64__ > + unsigned long long b = 0; > + if (__builtin_ia32_bextr_u64 (b++, 0) != 0) > + link_error (); > + if (__builtin_ia32_bextr_u64 (b++, 0x140) != 0) > + link_error (); > + if (b != 2) > + link_error (); > +#endif > +} > > Jakub >
--- gcc/config/i386/i386.cc.jj 2024-08-01 14:33:28.172801480 +0200 +++ gcc/config/i386/i386.cc 2024-08-08 12:55:12.780696418 +0200 @@ -18549,9 +18549,11 @@ ix86_fold_builtin (tree fndecl, int n_ar unsigned int prec = TYPE_PRECISION (TREE_TYPE (args[0])); unsigned int start = tree_to_uhwi (args[1]); unsigned int len = (start & 0xff00) >> 8; + tree lhs_type = TREE_TYPE (TREE_TYPE (fndecl)); start &= 0xff; if (start >= prec || len == 0) - res = 0; + return omit_one_operand (lhs_type, build_zero_cst (lhs_type), + args[0]); else if (!tree_fits_uhwi_p (args[0])) break; else @@ -18560,7 +18562,7 @@ ix86_fold_builtin (tree fndecl, int n_ar len = prec; if (len < HOST_BITS_PER_WIDE_INT) res &= (HOST_WIDE_INT_1U << len) - 1; - return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), res); + return build_int_cstu (lhs_type, res); } break; @@ -18570,15 +18572,17 @@ ix86_fold_builtin (tree fndecl, int n_ar if (tree_fits_uhwi_p (args[1])) { unsigned int idx = tree_to_uhwi (args[1]) & 0xff; + tree lhs_type = TREE_TYPE (TREE_TYPE (fndecl)); if (idx >= TYPE_PRECISION (TREE_TYPE (args[0]))) return args[0]; if (idx == 0) - return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0); + return omit_one_operand (lhs_type, build_zero_cst (lhs_type), + args[0]); if (!tree_fits_uhwi_p (args[0])) break; unsigned HOST_WIDE_INT res = tree_to_uhwi (args[0]); res &= ~(HOST_WIDE_INT_M1U << idx); - return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), res); + return build_int_cstu (lhs_type, res); } break; --- gcc/testsuite/gcc.target/i386/bmi-pr116287.c.jj 2024-08-08 13:14:25.566827913 +0200 +++ gcc/testsuite/gcc.target/i386/bmi-pr116287.c 2024-08-08 13:21:32.718312216 +0200 @@ -0,0 +1,28 @@ +/* PR target/116287 */ +/* { dg-do run { target bmi } } */ +/* { dg-options "-O2 -mbmi" } */ + +#include <x86intrin.h> + +#include "bmi-check.h" + +static void +bmi_test () +{ + unsigned int a = 0; + if (__builtin_ia32_bextr_u32 (a++, 0) != 0) + abort (); + if (__builtin_ia32_bextr_u32 (a++, 0x120) != 0) + abort (); + if (a != 2) + abort (); +#ifdef __x86_64__ + unsigned long long b = 0; + if (__builtin_ia32_bextr_u64 (b++, 0) != 0) + abort (); + if (__builtin_ia32_bextr_u64 (b++, 0x140) != 0) + abort (); + if (b != 2) + abort (); +#endif +} --- gcc/testsuite/gcc.target/i386/bmi2-pr116287.c.jj 2024-08-08 13:22:55.263246127 +0200 +++ gcc/testsuite/gcc.target/i386/bmi2-pr116287.c 2024-08-08 13:30:44.851181267 +0200 @@ -0,0 +1,24 @@ +/* PR target/116287 */ +/* { dg-do run { target bmi2 } } */ +/* { dg-options "-O2 -mbmi2" } */ + +#include <x86intrin.h> + +#include "bmi2-check.h" + +static void +bmi2_test () +{ + unsigned int a = 0; + if (__builtin_ia32_bzhi_si (a++, 0) != 0) + abort (); + if (a != 1) + abort (); +#ifdef __x86_64__ + unsigned long long b = 0; + if (__builtin_ia32_bzhi_di (b++, 0) != 0) + abort (); + if (b != 1) + abort (); +#endif +} --- gcc/testsuite/gcc.target/i386/tbm-pr116287.c.jj 2024-08-08 13:14:48.453532722 +0200 +++ gcc/testsuite/gcc.target/i386/tbm-pr116287.c 2024-08-08 13:22:36.940482770 +0200 @@ -0,0 +1,29 @@ +/* PR target/116287 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtbm -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "link_error \\\(\\\);" "optimized" } } */ + +#include <x86intrin.h> + +extern void link_error (void); + +void +tbm_test () +{ + unsigned int a = 0; + if (__builtin_ia32_bextri_u32 (a++, 0) != 0) + link_error (); + if (__builtin_ia32_bextri_u32 (a++, 0x120) != 0) + link_error (); + if (a != 2) + link_error (); +#ifdef __x86_64__ + unsigned long long b = 0; + if (__builtin_ia32_bextr_u64 (b++, 0) != 0) + link_error (); + if (__builtin_ia32_bextr_u64 (b++, 0x140) != 0) + link_error (); + if (b != 2) + link_error (); +#endif +}