Message ID | 20240719111008.2566858-1-pan2.li@intel.com |
---|---|
State | New |
Headers | show |
Series | [v2] Internal-fn: Only allow type matches mode for internal fn[PR115961] | expand |
On Fri, Jul 19, 2024 at 4:11 AM <pan2.li@intel.com> wrote: > > From: Pan Li <pan2.li@intel.com> > > The direct_internal_fn_supported_p has no restrictions for the type > modes. For example the bitfield like below will be recog as .SAT_TRUNC. > > struct e > { > unsigned pre : 12; > unsigned a : 4; > }; > > __attribute__((noipa)) > void bug (e * v, unsigned def, unsigned use) { > e & defE = *v; > defE.a = min_u (use + 1, 0xf); > } > > This patch would like to check strictly for the direct_internal_fn_supported_p, > and only allows the type matches mode for ifn type tree pair. > > The below test suites are passed for this patch: > 1. The rv64gcv fully regression tests. > 2. The x86 bootstrap tests. > 3. The x86 fully regression tests. Note I just ran into basically the same bug with BIT_ANDC/BIT_IORC (which will be renamed to BIT_ANDN/BIT_IORN). > > PR target/115961 > > gcc/ChangeLog: > > * internal-fn.cc (type_strictly_matches_mode_p): Add new func > impl to check type strictly matches mode or not. > (type_pair_strictly_matches_mode_p): Ditto but for tree type > pair. > (direct_internal_fn_supported_p): Add above check for the tree > type pair. > > gcc/testsuite/ChangeLog: > > * g++.target/i386/pr115961-run-1.C: New test. > * g++.target/riscv/rvv/base/pr115961-run-1.C: New test. > > Signed-off-by: Pan Li <pan2.li@intel.com> > --- > gcc/internal-fn.cc | 32 +++++++++++++++++ > .../g++.target/i386/pr115961-run-1.C | 34 +++++++++++++++++++ > .../riscv/rvv/base/pr115961-run-1.C | 34 +++++++++++++++++++ > 3 files changed, 100 insertions(+) > create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C > create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C > > diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc > index 95946bfd683..5c21249318e 100644 > --- a/gcc/internal-fn.cc > +++ b/gcc/internal-fn.cc > @@ -4164,6 +4164,35 @@ direct_internal_fn_optab (internal_fn fn) > gcc_unreachable (); > } > > +/* Return true if TYPE's mode has the same format as TYPE, and if there is > + a 1:1 correspondence between the values that the mode can store and the > + values that the type can store. */ > + > +static bool > +type_strictly_matches_mode_p (const_tree type) > +{ > + if (VECTOR_TYPE_P (type)) > + return VECTOR_MODE_P (TYPE_MODE (type)); > + > + if (INTEGRAL_TYPE_P (type)) > + return type_has_mode_precision_p (type); > + > + if (SCALAR_FLOAT_TYPE_P (type) || COMPLEX_FLOAT_TYPE_P (type)) > + return true; > + > + return false; > +} > + > +/* Return true if both the first and the second type of tree pair are > + strictly matches their modes, or return false. */ Just a slight comment improvement: /* Returns true if both types of TYPE_PAIR strictly match their modes, else returns false. */ > + > +static bool > +type_pair_strictly_matches_mode_p (tree_pair type_pair) > +{ > + return type_strictly_matches_mode_p (type_pair.first) > + && type_strictly_matches_mode_p (type_pair.second); > +} > + > /* Return true if FN is supported for the types in TYPES when the > optimization type is OPT_TYPE. The types are those associated with > the "type0" and "type1" fields of FN's direct_internal_fn_info > @@ -4173,6 +4202,9 @@ bool > direct_internal_fn_supported_p (internal_fn fn, tree_pair types, > optimization_type opt_type) > { > + if (!type_pair_strictly_matches_mode_p (types)) > + return false; > + > switch (fn) > { > #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \ > diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C > new file mode 100644 > index 00000000000..b8c8aef3b17 > --- /dev/null > +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C This testcase could go in g++.dg/torture/ without the -O3 option. > @@ -0,0 +1,34 @@ > +/* PR target/115961 */ > +/* { dg-do run } */ > +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ > + > +struct e > +{ > + unsigned pre : 12; > + unsigned a : 4; > +}; > + > +static unsigned min_u (unsigned a, unsigned b) > +{ > + return (b < a) ? b : a; > +} > + > +__attribute__((noipa)) > +void bug (e * v, unsigned def, unsigned use) { > + e & defE = *v; > + defE.a = min_u (use + 1, 0xf); > +} > + > +__attribute__((noipa, optimize(0))) > +int main(void) > +{ > + e v = { 0xded, 3 }; > + > + bug(&v, 32, 33); > + > + if (v.a != 0xf) > + __builtin_abort (); > + > + return 0; > +} > +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ Since we are scanning for the negative it should pass on all targets even ones without SAT_TRUNC support. And then you should not need the other testcase either. Thanks, Andrew Pinski > diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C > new file mode 100644 > index 00000000000..b8c8aef3b17 > --- /dev/null > +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C > @@ -0,0 +1,34 @@ > +/* PR target/115961 */ > +/* { dg-do run } */ > +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ > + > +struct e > +{ > + unsigned pre : 12; > + unsigned a : 4; > +}; > + > +static unsigned min_u (unsigned a, unsigned b) > +{ > + return (b < a) ? b : a; > +} > + > +__attribute__((noipa)) > +void bug (e * v, unsigned def, unsigned use) { > + e & defE = *v; > + defE.a = min_u (use + 1, 0xf); > +} > + > +__attribute__((noipa, optimize(0))) > +int main(void) > +{ > + e v = { 0xded, 3 }; > + > + bug(&v, 32, 33); > + > + if (v.a != 0xf) > + __builtin_abort (); > + > + return 0; > +} > +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ > -- > 2.34.1 >
On Fri, Jul 19, 2024 at 1:10 PM <pan2.li@intel.com> wrote: > > From: Pan Li <pan2.li@intel.com> > > The direct_internal_fn_supported_p has no restrictions for the type > modes. For example the bitfield like below will be recog as .SAT_TRUNC. > > struct e > { > unsigned pre : 12; > unsigned a : 4; > }; > > __attribute__((noipa)) > void bug (e * v, unsigned def, unsigned use) { > e & defE = *v; > defE.a = min_u (use + 1, 0xf); > } > > This patch would like to check strictly for the direct_internal_fn_supported_p, > and only allows the type matches mode for ifn type tree pair. > > The below test suites are passed for this patch: > 1. The rv64gcv fully regression tests. > 2. The x86 bootstrap tests. > 3. The x86 fully regression tests. LGTM unless Richard S. has any more comments. Richard. > PR target/115961 > > gcc/ChangeLog: > > * internal-fn.cc (type_strictly_matches_mode_p): Add new func > impl to check type strictly matches mode or not. > (type_pair_strictly_matches_mode_p): Ditto but for tree type > pair. > (direct_internal_fn_supported_p): Add above check for the tree > type pair. > > gcc/testsuite/ChangeLog: > > * g++.target/i386/pr115961-run-1.C: New test. > * g++.target/riscv/rvv/base/pr115961-run-1.C: New test. > > Signed-off-by: Pan Li <pan2.li@intel.com> > --- > gcc/internal-fn.cc | 32 +++++++++++++++++ > .../g++.target/i386/pr115961-run-1.C | 34 +++++++++++++++++++ > .../riscv/rvv/base/pr115961-run-1.C | 34 +++++++++++++++++++ > 3 files changed, 100 insertions(+) > create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C > create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C > > diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc > index 95946bfd683..5c21249318e 100644 > --- a/gcc/internal-fn.cc > +++ b/gcc/internal-fn.cc > @@ -4164,6 +4164,35 @@ direct_internal_fn_optab (internal_fn fn) > gcc_unreachable (); > } > > +/* Return true if TYPE's mode has the same format as TYPE, and if there is > + a 1:1 correspondence between the values that the mode can store and the > + values that the type can store. */ > + > +static bool > +type_strictly_matches_mode_p (const_tree type) > +{ > + if (VECTOR_TYPE_P (type)) > + return VECTOR_MODE_P (TYPE_MODE (type)); > + > + if (INTEGRAL_TYPE_P (type)) > + return type_has_mode_precision_p (type); > + > + if (SCALAR_FLOAT_TYPE_P (type) || COMPLEX_FLOAT_TYPE_P (type)) > + return true; > + > + return false; > +} > + > +/* Return true if both the first and the second type of tree pair are > + strictly matches their modes, or return false. */ > + > +static bool > +type_pair_strictly_matches_mode_p (tree_pair type_pair) > +{ > + return type_strictly_matches_mode_p (type_pair.first) > + && type_strictly_matches_mode_p (type_pair.second); > +} > + > /* Return true if FN is supported for the types in TYPES when the > optimization type is OPT_TYPE. The types are those associated with > the "type0" and "type1" fields of FN's direct_internal_fn_info > @@ -4173,6 +4202,9 @@ bool > direct_internal_fn_supported_p (internal_fn fn, tree_pair types, > optimization_type opt_type) > { > + if (!type_pair_strictly_matches_mode_p (types)) > + return false; > + > switch (fn) > { > #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \ > diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C > new file mode 100644 > index 00000000000..b8c8aef3b17 > --- /dev/null > +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C > @@ -0,0 +1,34 @@ > +/* PR target/115961 */ > +/* { dg-do run } */ > +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ > + > +struct e > +{ > + unsigned pre : 12; > + unsigned a : 4; > +}; > + > +static unsigned min_u (unsigned a, unsigned b) > +{ > + return (b < a) ? b : a; > +} > + > +__attribute__((noipa)) > +void bug (e * v, unsigned def, unsigned use) { > + e & defE = *v; > + defE.a = min_u (use + 1, 0xf); > +} > + > +__attribute__((noipa, optimize(0))) > +int main(void) > +{ > + e v = { 0xded, 3 }; > + > + bug(&v, 32, 33); > + > + if (v.a != 0xf) > + __builtin_abort (); > + > + return 0; > +} > +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ > diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C > new file mode 100644 > index 00000000000..b8c8aef3b17 > --- /dev/null > +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C > @@ -0,0 +1,34 @@ > +/* PR target/115961 */ > +/* { dg-do run } */ > +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ > + > +struct e > +{ > + unsigned pre : 12; > + unsigned a : 4; > +}; > + > +static unsigned min_u (unsigned a, unsigned b) > +{ > + return (b < a) ? b : a; > +} > + > +__attribute__((noipa)) > +void bug (e * v, unsigned def, unsigned use) { > + e & defE = *v; > + defE.a = min_u (use + 1, 0xf); > +} > + > +__attribute__((noipa, optimize(0))) > +int main(void) > +{ > + e v = { 0xded, 3 }; > + > + bug(&v, 32, 33); > + > + if (v.a != 0xf) > + __builtin_abort (); > + > + return 0; > +} > +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ > -- > 2.34.1 >
Richard Biener <richard.guenther@gmail.com> writes: > On Fri, Jul 19, 2024 at 1:10 PM <pan2.li@intel.com> wrote: >> >> From: Pan Li <pan2.li@intel.com> >> >> The direct_internal_fn_supported_p has no restrictions for the type >> modes. For example the bitfield like below will be recog as .SAT_TRUNC. >> >> struct e >> { >> unsigned pre : 12; >> unsigned a : 4; >> }; >> >> __attribute__((noipa)) >> void bug (e * v, unsigned def, unsigned use) { >> e & defE = *v; >> defE.a = min_u (use + 1, 0xf); >> } >> >> This patch would like to check strictly for the direct_internal_fn_supported_p, >> and only allows the type matches mode for ifn type tree pair. >> >> The below test suites are passed for this patch: >> 1. The rv64gcv fully regression tests. >> 2. The x86 bootstrap tests. >> 3. The x86 fully regression tests. > > LGTM unless Richard S. has any more comments. LGTM too with Andrew's comments addressed. Thanks, Richard > > Richard. > >> PR target/115961 >> >> gcc/ChangeLog: >> >> * internal-fn.cc (type_strictly_matches_mode_p): Add new func >> impl to check type strictly matches mode or not. >> (type_pair_strictly_matches_mode_p): Ditto but for tree type >> pair. >> (direct_internal_fn_supported_p): Add above check for the tree >> type pair. >> >> gcc/testsuite/ChangeLog: >> >> * g++.target/i386/pr115961-run-1.C: New test. >> * g++.target/riscv/rvv/base/pr115961-run-1.C: New test. >> >> Signed-off-by: Pan Li <pan2.li@intel.com> >> --- >> gcc/internal-fn.cc | 32 +++++++++++++++++ >> .../g++.target/i386/pr115961-run-1.C | 34 +++++++++++++++++++ >> .../riscv/rvv/base/pr115961-run-1.C | 34 +++++++++++++++++++ >> 3 files changed, 100 insertions(+) >> create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C >> create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C >> >> diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc >> index 95946bfd683..5c21249318e 100644 >> --- a/gcc/internal-fn.cc >> +++ b/gcc/internal-fn.cc >> @@ -4164,6 +4164,35 @@ direct_internal_fn_optab (internal_fn fn) >> gcc_unreachable (); >> } >> >> +/* Return true if TYPE's mode has the same format as TYPE, and if there is >> + a 1:1 correspondence between the values that the mode can store and the >> + values that the type can store. */ >> + >> +static bool >> +type_strictly_matches_mode_p (const_tree type) >> +{ >> + if (VECTOR_TYPE_P (type)) >> + return VECTOR_MODE_P (TYPE_MODE (type)); >> + >> + if (INTEGRAL_TYPE_P (type)) >> + return type_has_mode_precision_p (type); >> + >> + if (SCALAR_FLOAT_TYPE_P (type) || COMPLEX_FLOAT_TYPE_P (type)) >> + return true; >> + >> + return false; >> +} >> + >> +/* Return true if both the first and the second type of tree pair are >> + strictly matches their modes, or return false. */ >> + >> +static bool >> +type_pair_strictly_matches_mode_p (tree_pair type_pair) >> +{ >> + return type_strictly_matches_mode_p (type_pair.first) >> + && type_strictly_matches_mode_p (type_pair.second); >> +} >> + >> /* Return true if FN is supported for the types in TYPES when the >> optimization type is OPT_TYPE. The types are those associated with >> the "type0" and "type1" fields of FN's direct_internal_fn_info >> @@ -4173,6 +4202,9 @@ bool >> direct_internal_fn_supported_p (internal_fn fn, tree_pair types, >> optimization_type opt_type) >> { >> + if (!type_pair_strictly_matches_mode_p (types)) >> + return false; >> + >> switch (fn) >> { >> #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \ >> diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C >> new file mode 100644 >> index 00000000000..b8c8aef3b17 >> --- /dev/null >> +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C >> @@ -0,0 +1,34 @@ >> +/* PR target/115961 */ >> +/* { dg-do run } */ >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ >> + >> +struct e >> +{ >> + unsigned pre : 12; >> + unsigned a : 4; >> +}; >> + >> +static unsigned min_u (unsigned a, unsigned b) >> +{ >> + return (b < a) ? b : a; >> +} >> + >> +__attribute__((noipa)) >> +void bug (e * v, unsigned def, unsigned use) { >> + e & defE = *v; >> + defE.a = min_u (use + 1, 0xf); >> +} >> + >> +__attribute__((noipa, optimize(0))) >> +int main(void) >> +{ >> + e v = { 0xded, 3 }; >> + >> + bug(&v, 32, 33); >> + >> + if (v.a != 0xf) >> + __builtin_abort (); >> + >> + return 0; >> +} >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ >> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C >> new file mode 100644 >> index 00000000000..b8c8aef3b17 >> --- /dev/null >> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C >> @@ -0,0 +1,34 @@ >> +/* PR target/115961 */ >> +/* { dg-do run } */ >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ >> + >> +struct e >> +{ >> + unsigned pre : 12; >> + unsigned a : 4; >> +}; >> + >> +static unsigned min_u (unsigned a, unsigned b) >> +{ >> + return (b < a) ? b : a; >> +} >> + >> +__attribute__((noipa)) >> +void bug (e * v, unsigned def, unsigned use) { >> + e & defE = *v; >> + defE.a = min_u (use + 1, 0xf); >> +} >> + >> +__attribute__((noipa, optimize(0))) >> +int main(void) >> +{ >> + e v = { 0xded, 3 }; >> + >> + bug(&v, 32, 33); >> + >> + if (v.a != 0xf) >> + __builtin_abort (); >> + >> + return 0; >> +} >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ >> -- >> 2.34.1 >>
> Just a slight comment improvement: > /* Returns true if both types of TYPE_PAIR strictly match their modes, > else returns false. */ > This testcase could go in g++.dg/torture/ without the -O3 option. > Since we are scanning for the negative it should pass on all targets > even ones without SAT_TRUNC support. And then you should not need the > other testcase either. Thanks all, will address above comments and commit it if no surprise from test. Pan -----Original Message----- From: Richard Sandiford <richard.sandiford@arm.com> Sent: Tuesday, July 23, 2024 10:03 PM To: Richard Biener <richard.guenther@gmail.com> Cc: Li, Pan2 <pan2.li@intel.com>; gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai; kito.cheng@gmail.com; tamar.christina@arm.com; jeffreyalaw@gmail.com; rdapp.gcc@gmail.com Subject: Re: [PATCH v2] Internal-fn: Only allow type matches mode for internal fn[PR115961] Richard Biener <richard.guenther@gmail.com> writes: > On Fri, Jul 19, 2024 at 1:10 PM <pan2.li@intel.com> wrote: >> >> From: Pan Li <pan2.li@intel.com> >> >> The direct_internal_fn_supported_p has no restrictions for the type >> modes. For example the bitfield like below will be recog as .SAT_TRUNC. >> >> struct e >> { >> unsigned pre : 12; >> unsigned a : 4; >> }; >> >> __attribute__((noipa)) >> void bug (e * v, unsigned def, unsigned use) { >> e & defE = *v; >> defE.a = min_u (use + 1, 0xf); >> } >> >> This patch would like to check strictly for the direct_internal_fn_supported_p, >> and only allows the type matches mode for ifn type tree pair. >> >> The below test suites are passed for this patch: >> 1. The rv64gcv fully regression tests. >> 2. The x86 bootstrap tests. >> 3. The x86 fully regression tests. > > LGTM unless Richard S. has any more comments. LGTM too with Andrew's comments addressed. Thanks, Richard > > Richard. > >> PR target/115961 >> >> gcc/ChangeLog: >> >> * internal-fn.cc (type_strictly_matches_mode_p): Add new func >> impl to check type strictly matches mode or not. >> (type_pair_strictly_matches_mode_p): Ditto but for tree type >> pair. >> (direct_internal_fn_supported_p): Add above check for the tree >> type pair. >> >> gcc/testsuite/ChangeLog: >> >> * g++.target/i386/pr115961-run-1.C: New test. >> * g++.target/riscv/rvv/base/pr115961-run-1.C: New test. >> >> Signed-off-by: Pan Li <pan2.li@intel.com> >> --- >> gcc/internal-fn.cc | 32 +++++++++++++++++ >> .../g++.target/i386/pr115961-run-1.C | 34 +++++++++++++++++++ >> .../riscv/rvv/base/pr115961-run-1.C | 34 +++++++++++++++++++ >> 3 files changed, 100 insertions(+) >> create mode 100644 gcc/testsuite/g++.target/i386/pr115961-run-1.C >> create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C >> >> diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc >> index 95946bfd683..5c21249318e 100644 >> --- a/gcc/internal-fn.cc >> +++ b/gcc/internal-fn.cc >> @@ -4164,6 +4164,35 @@ direct_internal_fn_optab (internal_fn fn) >> gcc_unreachable (); >> } >> >> +/* Return true if TYPE's mode has the same format as TYPE, and if there is >> + a 1:1 correspondence between the values that the mode can store and the >> + values that the type can store. */ >> + >> +static bool >> +type_strictly_matches_mode_p (const_tree type) >> +{ >> + if (VECTOR_TYPE_P (type)) >> + return VECTOR_MODE_P (TYPE_MODE (type)); >> + >> + if (INTEGRAL_TYPE_P (type)) >> + return type_has_mode_precision_p (type); >> + >> + if (SCALAR_FLOAT_TYPE_P (type) || COMPLEX_FLOAT_TYPE_P (type)) >> + return true; >> + >> + return false; >> +} >> + >> +/* Return true if both the first and the second type of tree pair are >> + strictly matches their modes, or return false. */ >> + >> +static bool >> +type_pair_strictly_matches_mode_p (tree_pair type_pair) >> +{ >> + return type_strictly_matches_mode_p (type_pair.first) >> + && type_strictly_matches_mode_p (type_pair.second); >> +} >> + >> /* Return true if FN is supported for the types in TYPES when the >> optimization type is OPT_TYPE. The types are those associated with >> the "type0" and "type1" fields of FN's direct_internal_fn_info >> @@ -4173,6 +4202,9 @@ bool >> direct_internal_fn_supported_p (internal_fn fn, tree_pair types, >> optimization_type opt_type) >> { >> + if (!type_pair_strictly_matches_mode_p (types)) >> + return false; >> + >> switch (fn) >> { >> #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \ >> diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C >> new file mode 100644 >> index 00000000000..b8c8aef3b17 >> --- /dev/null >> +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C >> @@ -0,0 +1,34 @@ >> +/* PR target/115961 */ >> +/* { dg-do run } */ >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ >> + >> +struct e >> +{ >> + unsigned pre : 12; >> + unsigned a : 4; >> +}; >> + >> +static unsigned min_u (unsigned a, unsigned b) >> +{ >> + return (b < a) ? b : a; >> +} >> + >> +__attribute__((noipa)) >> +void bug (e * v, unsigned def, unsigned use) { >> + e & defE = *v; >> + defE.a = min_u (use + 1, 0xf); >> +} >> + >> +__attribute__((noipa, optimize(0))) >> +int main(void) >> +{ >> + e v = { 0xded, 3 }; >> + >> + bug(&v, 32, 33); >> + >> + if (v.a != 0xf) >> + __builtin_abort (); >> + >> + return 0; >> +} >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ >> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C >> new file mode 100644 >> index 00000000000..b8c8aef3b17 >> --- /dev/null >> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C >> @@ -0,0 +1,34 @@ >> +/* PR target/115961 */ >> +/* { dg-do run } */ >> +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ >> + >> +struct e >> +{ >> + unsigned pre : 12; >> + unsigned a : 4; >> +}; >> + >> +static unsigned min_u (unsigned a, unsigned b) >> +{ >> + return (b < a) ? b : a; >> +} >> + >> +__attribute__((noipa)) >> +void bug (e * v, unsigned def, unsigned use) { >> + e & defE = *v; >> + defE.a = min_u (use + 1, 0xf); >> +} >> + >> +__attribute__((noipa, optimize(0))) >> +int main(void) >> +{ >> + e v = { 0xded, 3 }; >> + >> + bug(&v, 32, 33); >> + >> + if (v.a != 0xf) >> + __builtin_abort (); >> + >> + return 0; >> +} >> +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ >> -- >> 2.34.1 >>
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 95946bfd683..5c21249318e 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -4164,6 +4164,35 @@ direct_internal_fn_optab (internal_fn fn) gcc_unreachable (); } +/* Return true if TYPE's mode has the same format as TYPE, and if there is + a 1:1 correspondence between the values that the mode can store and the + values that the type can store. */ + +static bool +type_strictly_matches_mode_p (const_tree type) +{ + if (VECTOR_TYPE_P (type)) + return VECTOR_MODE_P (TYPE_MODE (type)); + + if (INTEGRAL_TYPE_P (type)) + return type_has_mode_precision_p (type); + + if (SCALAR_FLOAT_TYPE_P (type) || COMPLEX_FLOAT_TYPE_P (type)) + return true; + + return false; +} + +/* Return true if both the first and the second type of tree pair are + strictly matches their modes, or return false. */ + +static bool +type_pair_strictly_matches_mode_p (tree_pair type_pair) +{ + return type_strictly_matches_mode_p (type_pair.first) + && type_strictly_matches_mode_p (type_pair.second); +} + /* Return true if FN is supported for the types in TYPES when the optimization type is OPT_TYPE. The types are those associated with the "type0" and "type1" fields of FN's direct_internal_fn_info @@ -4173,6 +4202,9 @@ bool direct_internal_fn_supported_p (internal_fn fn, tree_pair types, optimization_type opt_type) { + if (!type_pair_strictly_matches_mode_p (types)) + return false; + switch (fn) { #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \ diff --git a/gcc/testsuite/g++.target/i386/pr115961-run-1.C b/gcc/testsuite/g++.target/i386/pr115961-run-1.C new file mode 100644 index 00000000000..b8c8aef3b17 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr115961-run-1.C @@ -0,0 +1,34 @@ +/* PR target/115961 */ +/* { dg-do run } */ +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ + +struct e +{ + unsigned pre : 12; + unsigned a : 4; +}; + +static unsigned min_u (unsigned a, unsigned b) +{ + return (b < a) ? b : a; +} + +__attribute__((noipa)) +void bug (e * v, unsigned def, unsigned use) { + e & defE = *v; + defE.a = min_u (use + 1, 0xf); +} + +__attribute__((noipa, optimize(0))) +int main(void) +{ + e v = { 0xded, 3 }; + + bug(&v, 32, 33); + + if (v.a != 0xf) + __builtin_abort (); + + return 0; +} +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */ diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C new file mode 100644 index 00000000000..b8c8aef3b17 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr115961-run-1.C @@ -0,0 +1,34 @@ +/* PR target/115961 */ +/* { dg-do run } */ +/* { dg-options "-O3 -fdump-rtl-expand-details" } */ + +struct e +{ + unsigned pre : 12; + unsigned a : 4; +}; + +static unsigned min_u (unsigned a, unsigned b) +{ + return (b < a) ? b : a; +} + +__attribute__((noipa)) +void bug (e * v, unsigned def, unsigned use) { + e & defE = *v; + defE.a = min_u (use + 1, 0xf); +} + +__attribute__((noipa, optimize(0))) +int main(void) +{ + e v = { 0xded, 3 }; + + bug(&v, 32, 33); + + if (v.a != 0xf) + __builtin_abort (); + + return 0; +} +/* { dg-final { scan-rtl-dump-not ".SAT_TRUNC " "expand" } } */