[gcc r14-9418] VECT: Fix ICE for vectorizable LD/ST when both len and store are enabled
https://gcc.gnu.org/g:993c6de642ffeb2867edbe80ff2a72c0a2eb604e commit r14-9418-g993c6de642ffeb2867edbe80ff2a72c0a2eb604e Author: Pan Li Date: Sun Mar 10 11:02:35 2024 +0800 VECT: Fix ICE for vectorizable LD/ST when both len and store are enabled This patch would like to fix one ICE in vectorizable_store when both the loop_masks and loop_lens are enabled. The ICE looks like below when build with "-march=rv64gcv -O3". during GIMPLE pass: vect test.c: In function ādā: test.c:6:6: internal compiler error: in vectorizable_store, at tree-vect-stmts.cc:8691 6 | void d() { | ^ 0x37a6f2f vectorizable_store .../__RISC-V_BUILD__/../gcc/tree-vect-stmts.cc:8691 0x37b861c vect_analyze_stmt(vec_info*, _stmt_vec_info*, bool*, _slp_tree*, _slp_instance*, vec*) .../__RISC-V_BUILD__/../gcc/tree-vect-stmts.cc:13242 0x1db5dca vect_analyze_loop_operations .../__RISC-V_BUILD__/../gcc/tree-vect-loop.cc:2208 0x1db885b vect_analyze_loop_2 .../__RISC-V_BUILD__/../gcc/tree-vect-loop.cc:3041 0x1dba029 vect_analyze_loop_1 .../__RISC-V_BUILD__/../gcc/tree-vect-loop.cc:3481 0x1dbabad vect_analyze_loop(loop*, vec_info_shared*) .../__RISC-V_BUILD__/../gcc/tree-vect-loop.cc:3639 0x1e389d1 try_vectorize_loop_1 .../__RISC-V_BUILD__/../gcc/tree-vectorizer.cc:1066 0x1e38f3d try_vectorize_loop .../__RISC-V_BUILD__/../gcc/tree-vectorizer.cc:1182 0x1e39230 execute .../__RISC-V_BUILD__/../gcc/tree-vectorizer.cc:1298 There are two ways to reach vectorizer LD/ST, one is the analysis and the other is transform. We cannot have both the lens and the masks enabled during transform but it is valid during analysis. Given the transform doesn't required cost_vec, we can only enable the assert based on cost_vec is NULL or not. Below testsuites are passed for this patch: * The x86 bootstrap tests. * The x86 fully regression tests. * The aarch64 fully regression tests. * The riscv fully regressison tests. gcc/ChangeLog: * tree-vect-stmts.cc (vectorizable_store): Enable the assert during transform process. (vectorizable_load): Ditto. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/pr114195-1.c: New test. Signed-off-by: Pan Li Diff: --- gcc/testsuite/gcc.target/riscv/rvv/base/pr114195-1.c | 15 +++ gcc/tree-vect-stmts.cc | 18 ++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr114195-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr114195-1.c new file mode 100644 index 000..a67b847112b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr114195-1.c @@ -0,0 +1,15 @@ +/* Test that we do not have ice when compile */ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -ftree-vectorize" } */ + +long a, b; +extern short c[]; + +void d() { + for (int e = 0; e < 35; e = 2) { +a = ({ a < 0 ? a : 0; }); +b = ({ b < 0 ? b : 0; }); + +c[e] = 0; + } +} diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 14a3ffb5f02..e8617439a48 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -8697,8 +8697,13 @@ vectorizable_store (vec_info *vinfo, ? &LOOP_VINFO_LENS (loop_vinfo) : NULL); - /* Shouldn't go with length-based approach if fully masked. */ - gcc_assert (!loop_lens || !loop_masks); + /* The vect_transform_stmt and vect_analyze_stmt will go here but there + are some difference here. We cannot enable both the lens and masks + during transform but it is allowed during analysis. + Shouldn't go with length-based approach if fully masked. */ + if (cost_vec == NULL) +/* The cost_vec is NULL during transfrom. */ +gcc_assert ((!loop_lens || !loop_masks)); /* Targets with store-lane instructions must not require explicit realignment. vect_supportable_dr_alignment always returns either @@ -10577,8 +10582,13 @@ vectorizable_load (vec_info *vinfo, ? &LOOP_VINFO_LENS (loop_vinfo) : NULL); - /* Shouldn't go with length-based approach if fully masked. */ - gcc_assert (!loop_lens || !loop_masks); + /* The vect_transform_stmt and vect_analyze_stmt will go here but there + are some difference here. We cannot enable both the lens and masks + during transform but it is allowed during analysis. + Shouldn't go with length-based approach if fully masked. */ + if (cost_vec == NULL) +/* The cost_vec is NULL during transfrom. */ +gcc_assert ((!loop_lens || !loop_masks)); /* Targets with store-lane instructions must not require explicit realignment. vect_supportable_dr_alignment always returns either
[gcc r14-9419] [committed] [PR tree-optimization/110199] Simplify MIN/MAX more often
https://gcc.gnu.org/g:8fe27ed193d60f6cd8b34761858a720c95eabbdb commit r14-9419-g8fe27ed193d60f6cd8b34761858a720c95eabbdb Author: jlaw Date: Sun Mar 10 11:58:00 2024 -0600 [committed] [PR tree-optimization/110199] Simplify MIN/MAX more often So as I mentioned in the BZ, the case of t = MIN_EXPR (A, B) where we know something about the relationship between A and B can be trivially handled by some existing code in DOM. That existing code would simplify when A == B. But by testing GE and LE instead of EQ we can cover more cases with minimal effort. When applicable the MIN/MAX turns into a simple copy. I made one other change. We have other binary operations that we simplify when we know something about the relationship between the operands. That code was not canonicalizing the order of operands when building the expression to lookup in the hash tables to discover that relationship. Since those paths are only testing for equality, we can trivially reverse them and not have to worry about changing codes or anything like that. So extremely safe and avoids having to come back and fix that code to match the MIN_EXPR/MAX_EXPR case later. Bootstrapped on x86 and also tested on the crosses. I briefly thought there was an sh regression, but that was actually the recent fwprop changes twiddling code generation for one test. PR tree-optimization/110199 gcc/ * tree-ssa-scopedtables.cc (avail_exprs_stack::simplify_binary_operation): Generalize handling of MIN_EXPR/MAX_EXPR to allow additional simplifications. Canonicalize comparison operands for other cases. gcc/testsuite * gcc.dg/tree-ssa/minmax-27.c: New test. * gcc.dg/tree-ssa/minmax-28.c: New test. Diff: --- gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c | 118 ++ gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c | 117 + gcc/tree-ssa-scopedtables.cc | 53 -- 3 files changed, 282 insertions(+), 6 deletions(-) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c new file mode 100644 index 000..4b94203b0d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c @@ -0,0 +1,118 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + + +int min1(int a, int b) +{ +if (a <= b) +return a < b ? a : b; +return 0; +} + +int min2(int a, int b) +{ +if (a <= b) +return a > b ? b : a; +return 0; +} + +int min3(int a, int b) +{ +if (a < b) +return a < b ? a : b; +return 0; +} + +int min4(int a, int b) +{ +if (a < b) +return a > b ? b : a; +return 0; +} + +int min5(int a, int b) +{ +if (a <= b) +return a <= b ? a : b; +return 0; +} + +int min6(int a, int b) +{ +if (a <= b) +return a >= b ? b : a; +return 0; +} + +int min7(int a, int b) +{ +if (a < b) +return a <= b ? a : b; +return 0; +} + +int min8(int a, int b) +{ +if (b > a) +return a >= b ? b : a; +return 0; +} + +int min9(int a, int b) +{ +if (b >= a) +return a < b ? a : b; +return 0; +} + +int min10(int a, int b) +{ +if (b >= a) +return a > b ? b : a; +return 0; +} + +int min11(int a, int b) +{ +if (b > a) +return a < b ? a : b; +return 0; +} + +int min12(int a, int b) +{ +if (b > a) +return a > b ? b : a; +return 0; +} + +int min13(int a, int b) +{ +if (b >= a) +return a <= b ? a : b; +return 0; +} + +int min14(int a, int b) +{ +if (b >= a) +return a >= b ? b : a; +return 0; +} + +int min15(int a, int b) +{ +if (b > a) +return a <= b ? a : b; +return 0; +} + +int min16(int a, int b) +{ +if (b > a) +return a >= b ? b : a; +return 0; +} + +/* { dg-final { scan-tree-dump-not "MIN_EXPR" "dom2" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c new file mode 100644 index 000..732126d7449 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c @@ -0,0 +1,117 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + +int max1(int a, int b) +{ +if (a <= b) +return a < b ? b : a; +return 0; +} + +int max2(int a, int b) +{ +if (a <= b) +return a > b ? a : b; +return 0; +} + +int max3(int a, int b) +{ +if (a < b) +return a < b ? b : a; +return 0; +} + +int max4(int a, int b) +{ +if (a < b) +return a > b ? a : b; +return 0; +} + +int max5(int a, int b) +{ +if (a <= b) +return a <= b ? b : a; +return 0; +} + +int max6(int a, int b) +{ +if (a <= b) +return a >= b ? a : b; +return 0; +} + +int max7(int a, int b) +{ +if (a < b) +re
[gcc r14-9420] d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285]
https://gcc.gnu.org/g:a84b98c62d90bf9e8b01038f624a62725e6a44db commit r14-9420-ga84b98c62d90bf9e8b01038f624a62725e6a44db Author: Iain Buclaw Date: Sun Mar 10 17:49:06 2024 +0100 d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285] The way that the target hook preferPassByRef is implemented, it relied on the GCC "back-end" tree type to determine whether or not to use `ref' ABI for D `in' parameters; e.g: prefer by value if it is expected that the target will pass the type around in registers. Building the GCC tree type depends on the AST type being complete - all semantic processing is finished - but as this hook is called from the front-end, this will not be the case for forward referenced or self-referencing types. The consensus in upstream is that `in' parameters should always be implicitly `ref', but as the front-end does not yet support all types being rvalue references, limit this just static arrays and structs. PR d/112285 PR d/112290 gcc/d/ChangeLog: * d-target.cc (Target::preferPassByRef): Return true for all static array and struct types. gcc/testsuite/ChangeLog: * gdc.dg/pr112285.d: New test. * gdc.dg/pr112290.d: New test. Diff: --- gcc/d/d-target.cc | 25 + gcc/testsuite/gdc.dg/pr112285.d | 13 + gcc/testsuite/gdc.dg/pr112290.d | 15 +++ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index b9d124422b7..127b9d7ce7c 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -575,31 +575,16 @@ Target::supportsLinkerDirective (void) const } /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to - be passed by reference or by valie. This is used only when compiling with + be passed by reference or by value. This is used only when compiling with `-fpreview=in' enabled. */ bool Target::preferPassByRef (Type *param_type) { - if (param_type->size () == SIZE_INVALID) + /* See note in Target::isReturnOnStack. */ + Type *tb = param_type->toBasetype (); + if (tb->size () == SIZE_INVALID) return false; - tree type = build_ctype (param_type); - - /* Prefer a `ref' if the type is an aggregate, and its size is greater than - its alignment. */ - if (AGGREGATE_TYPE_P (type) - && (!valid_constant_size_p (TYPE_SIZE_UNIT (type)) - || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0)) -return true; - - /* If the back-end is always going to pass this by invisible reference. */ - if (pass_by_reference (NULL, function_arg_info (type, true))) -return true; - - /* If returning the parameter means the caller will do RVO. */ - if (targetm.calls.return_in_memory (type, NULL_TREE)) -return true; - - return false; + return (tb->ty == TY::Tstruct || tb->ty == TY::Tsarray); } diff --git a/gcc/testsuite/gdc.dg/pr112285.d b/gcc/testsuite/gdc.dg/pr112285.d new file mode 100644 index 000..5ca100a74a9 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112285.d @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112285 +{ +} + +class C112285 +{ +S112285 s; +void f112285(in C112285) +{ +} +} diff --git a/gcc/testsuite/gdc.dg/pr112290.d b/gcc/testsuite/gdc.dg/pr112290.d new file mode 100644 index 000..7456fc21be1 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112290.d @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112290a +{ +S112290b* p; +bool opEquals(in S112290a) +{ +return p == p; +} +} + +struct S112290b +{ +string s; +}
[gcc r13-8415] d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285]
https://gcc.gnu.org/g:025ff57c19efae6c8d76df6b93e7d9827017acc9 commit r13-8415-g025ff57c19efae6c8d76df6b93e7d9827017acc9 Author: Iain Buclaw Date: Sun Mar 10 17:49:06 2024 +0100 d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285] The way that the target hook preferPassByRef is implemented, it relied on the GCC "back-end" tree type to determine whether or not to use `ref' ABI for D `in' parameters; e.g: prefer by value if it is expected that the target will pass the type around in registers. Building the GCC tree type depends on the AST type being complete - all semantic processing is finished - but as this hook is called from the front-end, this will not be the case for forward referenced or self-referencing types. The consensus in upstream is that `in' parameters should always be implicitly `ref', but as the front-end does not yet support all types being rvalue references, limit this just static arrays and structs. PR d/112285 PR d/112290 gcc/d/ChangeLog: * d-target.cc (Target::preferPassByRef): Return true for all static array and struct types. gcc/testsuite/ChangeLog: * gdc.dg/pr112285.d: New test. * gdc.dg/pr112290.d: New test. * gdc.test/compilable/previewin.d: Adjust testcase. (cherry picked from commit a84b98c62d90bf9e8b01038f624a62725e6a44db) Diff: --- gcc/d/d-target.cc | 25 + gcc/testsuite/gdc.dg/pr112285.d | 13 + gcc/testsuite/gdc.dg/pr112290.d | 15 +++ gcc/testsuite/gdc.test/compilable/previewin.d | 6 -- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index 4c7a212703e..73366fdde16 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -575,31 +575,16 @@ Target::supportsLinkerDirective (void) const } /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to - be passed by reference or by valie. This is used only when compiling with + be passed by reference or by value. This is used only when compiling with `-fpreview=in' enabled. */ bool Target::preferPassByRef (Type *param_type) { - if (param_type->size () == SIZE_INVALID) + /* See note in Target::isReturnOnStack. */ + Type *tb = param_type->toBasetype (); + if (tb->size () == SIZE_INVALID) return false; - tree type = build_ctype (param_type); - - /* Prefer a `ref' if the type is an aggregate, and its size is greater than - its alignment. */ - if (AGGREGATE_TYPE_P (type) - && (!valid_constant_size_p (TYPE_SIZE_UNIT (type)) - || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0)) -return true; - - /* If the back-end is always going to pass this by invisible reference. */ - if (pass_by_reference (NULL, function_arg_info (type, true))) -return true; - - /* If returning the parameter means the caller will do RVO. */ - if (targetm.calls.return_in_memory (type, NULL_TREE)) -return true; - - return false; + return (tb->ty == TY::Tstruct || tb->ty == TY::Tsarray); } diff --git a/gcc/testsuite/gdc.dg/pr112285.d b/gcc/testsuite/gdc.dg/pr112285.d new file mode 100644 index 000..5ca100a74a9 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112285.d @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112285 +{ +} + +class C112285 +{ +S112285 s; +void f112285(in C112285) +{ +} +} diff --git a/gcc/testsuite/gdc.dg/pr112290.d b/gcc/testsuite/gdc.dg/pr112290.d new file mode 100644 index 000..7456fc21be1 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112290.d @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112290a +{ +S112290b* p; +bool opEquals(in S112290a) +{ +return p == p; +} +} + +struct S112290b +{ +string s; +} diff --git a/gcc/testsuite/gdc.test/compilable/previewin.d b/gcc/testsuite/gdc.test/compilable/previewin.d index 8926fbd6aa7..558005c5280 100644 --- a/gcc/testsuite/gdc.test/compilable/previewin.d +++ b/gcc/testsuite/gdc.test/compilable/previewin.d @@ -79,14 +79,11 @@ version (Win64) { void checkReal(in real p) { -// ref for x87 real, value for double-precision real -static assert(__traits(isRef, p) == (real.sizeof > 8)); } struct RGB { ubyte r, g, b; } void checkNonPowerOf2(in RGB p) { -static assert(__traits(isRef, p)); } } else version (X86_64) // Posix x86_64 @@ -94,7 +91,6 @@ else version (X86_64) // Posix x86_64 struct Empty {} // 1 dummy byte passed on the stack void checkEmptyStruct(in Empty p) { -static assert(!__traits(isRef, p)); } static if (is(__vector(double[4]))) @@ -102,7 +98,6 @@ else version (X86_64) // Posix x86_6
[gcc r12-10202] d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285]
https://gcc.gnu.org/g:ec3a01024dd86c51d1e563df9395123765cf548d commit r12-10202-gec3a01024dd86c51d1e563df9395123765cf548d Author: Iain Buclaw Date: Sun Mar 10 17:49:06 2024 +0100 d: Fix -fpreview=in ICEs with forward referenced parameter [PR112285] The way that the target hook preferPassByRef is implemented, it relied on the GCC "back-end" tree type to determine whether or not to use `ref' ABI for D `in' parameters; e.g: prefer by value if it is expected that the target will pass the type around in registers. Building the GCC tree type depends on the AST type being complete - all semantic processing is finished - but as this hook is called from the front-end, this will not be the case for forward referenced or self-referencing types. The consensus in upstream is that `in' parameters should always be implicitly `ref', but as the front-end does not yet support all types being rvalue references, limit this just static arrays and structs. PR d/112285 PR d/112290 gcc/d/ChangeLog: * d-target.cc (Target::preferPassByRef): Return true for all static array and struct types. gcc/testsuite/ChangeLog: * gdc.dg/pr112285.d: New test. * gdc.dg/pr112290.d: New test. * gdc.test/compilable/previewin.d: Adjust testcase. (cherry picked from commit 025ff57c19efae6c8d76df6b93e7d9827017acc9) Diff: --- gcc/d/d-target.cc | 25 + gcc/testsuite/gdc.dg/pr112285.d | 13 + gcc/testsuite/gdc.dg/pr112290.d | 15 +++ gcc/testsuite/gdc.test/compilable/previewin.d | 6 -- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index d4350e593e4..f80ea466e24 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -586,31 +586,16 @@ Target::supportsLinkerDirective (void) const } /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to - be passed by reference or by valie. This is used only when compiling with + be passed by reference or by value. This is used only when compiling with `-fpreview=in' enabled. */ bool Target::preferPassByRef (Type *param_type) { - if (param_type->size () == SIZE_INVALID) + /* See note in Target::isReturnOnStack. */ + Type *tb = param_type->toBasetype (); + if (tb->size () == SIZE_INVALID) return false; - tree type = build_ctype (param_type); - - /* Prefer a `ref' if the type is an aggregate, and its size is greater than - its alignment. */ - if (AGGREGATE_TYPE_P (type) - && (!valid_constant_size_p (TYPE_SIZE_UNIT (type)) - || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0)) -return true; - - /* If the back-end is always going to pass this by invisible reference. */ - if (pass_by_reference (NULL, function_arg_info (type, true))) -return true; - - /* If returning the parameter means the caller will do RVO. */ - if (targetm.calls.return_in_memory (type, NULL_TREE)) -return true; - - return false; + return (tb->ty == TY::Tstruct || tb->ty == TY::Tsarray); } diff --git a/gcc/testsuite/gdc.dg/pr112285.d b/gcc/testsuite/gdc.dg/pr112285.d new file mode 100644 index 000..5ca100a74a9 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112285.d @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112285 +{ +} + +class C112285 +{ +S112285 s; +void f112285(in C112285) +{ +} +} diff --git a/gcc/testsuite/gdc.dg/pr112290.d b/gcc/testsuite/gdc.dg/pr112290.d new file mode 100644 index 000..7456fc21be1 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr112290.d @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-additional-options "-fpreview=in" } +struct S112290a +{ +S112290b* p; +bool opEquals(in S112290a) +{ +return p == p; +} +} + +struct S112290b +{ +string s; +} diff --git a/gcc/testsuite/gdc.test/compilable/previewin.d b/gcc/testsuite/gdc.test/compilable/previewin.d index 8926fbd6aa7..558005c5280 100644 --- a/gcc/testsuite/gdc.test/compilable/previewin.d +++ b/gcc/testsuite/gdc.test/compilable/previewin.d @@ -79,14 +79,11 @@ version (Win64) { void checkReal(in real p) { -// ref for x87 real, value for double-precision real -static assert(__traits(isRef, p) == (real.sizeof > 8)); } struct RGB { ubyte r, g, b; } void checkNonPowerOf2(in RGB p) { -static assert(__traits(isRef, p)); } } else version (X86_64) // Posix x86_64 @@ -94,7 +91,6 @@ else version (X86_64) // Posix x86_64 struct Empty {} // 1 dummy byte passed on the stack void checkEmptyStruct(in Empty p) { -static assert(!__traits(isRef, p)); } static if (is(__vector(double[4]))) @@ -102,7 +98,6 @@ else version (X86_64) // Posix x86_
[gcc r14-9422] Fold: Fix up merge_truthop_with_opposite_arm for NaNs [PR95351]
https://gcc.gnu.org/g:31ce2e993d09dcad1ce139a2848a28de5931056d commit r14-9422-g31ce2e993d09dcad1ce139a2848a28de5931056d Author: Andrew Pinski Date: Sun Mar 10 22:17:09 2024 + Fold: Fix up merge_truthop_with_opposite_arm for NaNs [PR95351] The problem here is that merge_truthop_with_opposite_arm would use the type of the result of the comparison rather than the operands of the comparison to figure out if we are honoring NaNs. This fixes that oversight and now we get the correct results in this case. Committed as obvious after a bootstrap/test on x86_64-linux-gnu. PR middle-end/95351 gcc/ChangeLog: * fold-const.cc (merge_truthop_with_opposite_arm): Use the type of the operands of the comparison and not the type of the comparison. gcc/testsuite/ChangeLog: * gcc.dg/float_opposite_arm-1.c: New test. Signed-off-by: Andrew Pinski Diff: --- gcc/fold-const.cc | 3 ++- gcc/testsuite/gcc.dg/float_opposite_arm-1.c | 17 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 43105d20be3..299c22bf391 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -6420,7 +6420,6 @@ static tree merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop, bool rhs_only) { - tree type = TREE_TYPE (cmpop); enum tree_code code = TREE_CODE (cmpop); enum tree_code truthop_code = TREE_CODE (op); tree lhs = TREE_OPERAND (op, 0); @@ -6436,6 +6435,8 @@ merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop, if (TREE_CODE_CLASS (code) != tcc_comparison) return NULL_TREE; + tree type = TREE_TYPE (TREE_OPERAND (cmpop, 0)); + if (rhs_code == truthop_code) { tree newrhs = merge_truthop_with_opposite_arm (loc, rhs, cmpop, rhs_only); diff --git a/gcc/testsuite/gcc.dg/float_opposite_arm-1.c b/gcc/testsuite/gcc.dg/float_opposite_arm-1.c new file mode 100644 index 000..d2dbff35066 --- /dev/null +++ b/gcc/testsuite/gcc.dg/float_opposite_arm-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-original -fdump-tree-optimized" } */ +/* { dg-add-options ieee } */ +/* PR middle-end/95351 */ + +int Foo(double possiblyNAN, double b, double c) +{ +return (possiblyNAN <= 2.0) || ((possiblyNAN > 2.0) && (b > c)); +} + +/* Make sure we don't remove either >/<= */ + +/* { dg-final { scan-tree-dump "possiblyNAN > 2.0e.0" "original" } } */ +/* { dg-final { scan-tree-dump "possiblyNAN_\[0-9\]+.D. > 2.0e.0" "optimized" } } */ + +/* { dg-final { scan-tree-dump "possiblyNAN <= 2.0e.0" "original" } } */ +/* { dg-final { scan-tree-dump "possiblyNAN_\[0-9\]+.D. <= 2.0e.0" "optimized" } } */