g++-10.0.0-alpha20191117 snapshot (r278376) and 9.2.0 ICE when compiling the following testcase w/ -O1 -fno-early-inlining: int x8 () { return ([rn = nullptr] () { return rn; } ()) ? 1 : 0; } % g++-10.0.0-alpha20191117 -O1 -fno-early-inlining -c hfy7acky.C during GIMPLE pass: phiopt hfy7acky.C: In function 'int x8()': hfy7acky.C:5:1: internal compiler error: in wide_int_to_tree_1, at tree.c:1530 5 | } | ^ 0x7ae494 wide_int_to_tree_1 /var/tmp/portage/sys-devel/gcc-10.0.0_alpha20191117/work/gcc-10-20191117/gcc/tree.c:1530 0x10b76d4 minmax_replacement /var/tmp/portage/sys-devel/gcc-10.0.0_alpha20191117/work/gcc-10-20191117/gcc/tree-ssa-phiopt.c:1389 0x10bb49b tree_ssa_phiopt_worker /var/tmp/portage/sys-devel/gcc-10.0.0_alpha20191117/work/gcc-10-20191117/gcc/tree-ssa-phiopt.c:348
Started with r265909. NULLPTR_TYPE only allows value 0, so doing rhs = wide_int_to_tree (TREE_TYPE (rhs), wi::min_value (TREE_TYPE (rhs)) + 1); for it ICEs. I'd say we should guard that only for INTEGRAL_TYPE_P types and perhaps pointer/reference types too, though transformation of == NULL to < (void *) 1 looks really weird.
For pointers, it boils down whether say void * foo (void *p) { return p ? p : (void *) 1; } optimization into MAX_EXPR <1B, p> is valid or not. The original code doesn't involve any non-equality comparisons, while MAX_EXPR is a non-equality comparison which ought to be valid only as long as the two pointers are pointing into the same object. Another possibility would be for pointers to do this optimization, but perform the MIN_EXPR/MAX_EXPR in pointer sized ints instead. So, the fix can be either NULLPTR_TYPE specific, like: --- gcc/tree-ssa-phiopt.c 2019-11-20 09:25:42.552157763 +0100 +++ gcc/tree-ssa-phiopt.c 2019-11-24 18:56:50.657172109 +0100 @@ -1381,7 +1381,8 @@ minmax_replacement (basic_block cond_bb, /* Turn EQ/NE of extreme values to order comparisons. */ if ((cmp == NE_EXPR || cmp == EQ_EXPR) - && TREE_CODE (rhs) == INTEGER_CST) + && TREE_CODE (rhs) == INTEGER_CST + && TREE_CODE (TREE_TYPE (rhs)) != NULLPTR_TYPE) { if (wi::eq_p (wi::to_wide (rhs), wi::min_value (TREE_TYPE (rhs)))) { @@ -1407,7 +1408,8 @@ minmax_replacement (basic_block cond_bb, larger = rhs; /* If we have smaller < CST it is equivalent to smaller <= CST-1. Likewise smaller <= CST is equivalent to smaller < CST+1. */ - if (TREE_CODE (larger) == INTEGER_CST) + if (TREE_CODE (larger) == INTEGER_CST + && TREE_CODE (TREE_TYPE (larger)) != NULLPTR_TYPE) { if (cmp == LT_EXPR) { @@ -1435,7 +1437,8 @@ minmax_replacement (basic_block cond_bb, larger = gimple_cond_lhs (cond); /* If we have larger > CST it is equivalent to larger >= CST+1. Likewise larger >= CST is equivalent to larger > CST-1. */ - if (TREE_CODE (smaller) == INTEGER_CST) + if (TREE_CODE (smaller) == INTEGER_CST + && TREE_CODE (TREE_TYPE (larger)) != NULLPTR_TYPE) { wi::overflow_type overflow; if (cmp == GT_EXPR) or instead of it say && (INTEGRAL_TYPE_P (TREE_TYPE (rhs)) || POINTER_TYPE_P (TREE_TYPE (rhs))), or just && INTEGRAL_TYPE_P (TREE_TYPE (rhs)), and if allowing POINTER_TYPE_P, we can also special case new_stmt = gimple_build_assign (result, minmax, arg0, arg1); for pointers by casting to integers and back. Thoughts?
INTEGRAL_TYPE_P
Created attachment 47350 [details] gcc10-pr92644.patch Untested fix.
Author: jakub Date: Tue Nov 26 08:43:27 2019 New Revision: 278720 URL: https://gcc.gnu.org/viewcvs?rev=278720&root=gcc&view=rev Log: PR tree-optimization/92644 * tree-ssa-phiopt.c (minmax_replacement): Add INTEGRAL_TYPE_P check next to INTEGER_CST checks. * g++.dg/opt/pr92644.C: New test. Added: trunk/gcc/testsuite/g++.dg/opt/pr92644.C Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-ssa-phiopt.c
Fixed on the trunk so far.
Author: jakub Date: Fri Dec 20 16:58:07 2019 New Revision: 279652 URL: https://gcc.gnu.org/viewcvs?rev=279652&root=gcc&view=rev Log: Backported from mainline 2019-11-26 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/92644 * tree-ssa-phiopt.c (minmax_replacement): Add INTEGRAL_TYPE_P check next to INTEGER_CST checks. * g++.dg/opt/pr92644.C: New test. Added: branches/gcc-9-branch/gcc/testsuite/g++.dg/opt/pr92644.C Modified: branches/gcc-9-branch/gcc/ChangeLog branches/gcc-9-branch/gcc/testsuite/ChangeLog branches/gcc-9-branch/gcc/tree-ssa-phiopt.c
Fixed for 9.3+ too.
I believe, it can be closed now, as the gcc 8 branch is not affected?
.