[Bug c++/86216] g++ ICE on valid code: verify_ssa failed
rguenth at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Jul 13 09:01:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86216
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jakub at gcc dot gnu.org
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
The interesting thing is that the RHS _1 is from a different function, a
SAVE_EXPR expansion actually, which means this is another case of
cross-function
tree sharing (I remember fixing such thing in the fortran FE).
Breakpoint 7, gimplify_save_expr (expr_p=0x7ffff6db3b18, pre_p=0x7fffffffd058,
post_p=0x7fffffffca98) at ../../src/trunk/gcc/gimplify.c:5870
5870 enum gimplify_status ret = GS_ALL_DONE;
$38 = <save_expr 0x7ffff6da3a80>
$39 = <function_decl 0x7ffff6dac100 b>
...
Breakpoint 7, gimplify_save_expr (expr_p=0x7ffff6da3ab8, pre_p=0x7fffffffc658,
post_p=0x7fffffffc458) at ../../src/trunk/gcc/gimplify.c:5870
5870 enum gimplify_status ret = GS_ALL_DONE;
$42 = <save_expr 0x7ffff6da3a80>
$43 = <function_decl 0x7ffff6dac400 operator()>
(gdb) p (*expr_p)->base.public_flag
$45 = 1
I guess we can track down at least the SAVE_EXPR case with
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c (revision 262624)
+++ gcc/gimplify.c (working copy)
@@ -869,7 +869,11 @@ copy_if_shared_r (tree *tp, int *walk_su
/* Otherwise, mark the node as visited and keep looking. */
else
- TREE_VISITED (t) = 1;
+ {
+ if (TREE_CODE (t) == SAVE_EXPR)
+ gcc_assert (!SAVE_EXPR_RESOLVED_P (t));
+ TREE_VISITED (t) = 1;
+ }
return NULL_TREE;
}
It's probably easy that this case of sharing happens for nested functions
since most type sizes are wrapped in SAVE_EXPRs and those do not get
unshared even when that is explicitely asked for.
But it looks like the tree sharing happens outside of a SAVE_EXPR given
we have at gimplify_function_tree time
{
intptr_t & n [value-expr: this->__n];
intptr_t & n [value-expr: this->__n];
{
<<cleanup_point <<< Unknown tree: expr_stmt
(void) (*n = (intptr_t) ((unsigned int) (_1 + 1) * 4)) >>>>>;
}
}
where _1 + 1 was what a SAVE_EXPR was resolved to but here we should have
seen the DECL created for it rather than the in-place gimplified result.
The .original dump though has
;; Function b(intptr_t, T) [with T = int; intptr_t =
int]::<lambda()>::<lambda()> (null)
;; enabled by -tree-original
{
intptr_t & n [value-expr: this->__n];
intptr_t & n [value-expr: this->__n];
{
<<cleanup_point <<< Unknown tree: expr_stmt
(void) (*n = (intptr_t) ((unsigned int) ((sizetype) (SAVE_EXPR <(ssizetype)
arg + -1>) + 1) * 4)) >>>>>;
}
}
it looks like there's tree sharing for a bigger part of the expression...
Indeed, between the above and
{
intptr_t & n [value-expr: this->__n];
intptr_t & n [value-expr: this->__n];
{
{
typedef struct __lambda3 __lambda3;
<<cleanup_point <<< Unknown tree: expr_stmt
(void) (*n = (intptr_t) ((unsigned int) ((sizetype) (SAVE_EXPR <(ssizetype)
arg + -1>) + 1) * 4)) >>>>>;
<<cleanup_point <<< Unknown tree: expr_stmt
b(intptr_t, T) [with T = int; intptr_t =
int]::<lambda()>::<lambda()>::operator() (&TARGET_EXPR <D.2347, {.__n=n}>)
>>>>>;
}
}
}
we have shared
arg:0 <plus_expr 0x7ffff6dae140 type <integer_type
0x7ffff6c5b000 sizetype>
side-effects
arg:0 <nop_expr 0x7ffff6da3aa0 type <integer_type
0x7ffff6c5b000 sizetype>
side-effects
arg:0 <save_expr 0x7ffff6da3a80 type <integer_type
0x7ffff6c5b150 ssizetype>
side-effects arg:0 <plus_expr 0x7ffff6daee60>
t.ii:3:22 start: t.ii:3:22 finish: t.ii:3:26>>
arg:1 <integer_cst 0x7ffff6c3df78 constant 1>>>
which is the (sizetype) (SAVE_EXPR <(ssizetype) arg + -1>) + 1 part.
<nop_expr 0x7ffff6db30e0
vs.
<nop_expr 0x7ffff6da3e00
type <integer_type 0x7ffff6c5b7e0 long unsigned int public unsigned DI
size <integer_cst 0x7ffff6c3de70 constant 64>
unit-size <integer_cst 0x7ffff6c3de88 constant 8>
align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7ffff6c5b7e0 precision:64 min <integer_cst 0x7ffff6c5e150 0> max <integer_cst
0x7ffff6c3e5c0 18446744073709551615>
pointer_to_this <pointer_type 0x7ffff6c6b498>>
side-effects
arg:0 <mult_expr 0x7ffff6dae168
type <integer_type 0x7ffff6c5b000 sizetype public unsigned DI size
<integer_cst 0x7ffff6c3de70 64> unit-size <integer_cst 0x7ffff6c3de88 8>
align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7ffff6c5b000 precision:64 min <integer_cst 0x7ffff6c3dea0 0> max <integer_cst
0x7ffff6c3e560 18446744073709551615>>
side-effects
arg:0 <plus_expr 0x7ffff6dae140 type <integer_type 0x7ffff6c5b000
sizetype>
side-effects
these nodes are built by c_sizeof_or_alignof_type
#4 0x0000000000bde3e2 in c_sizeof_or_alignof_type (loc=283249,
type=<array_type 0x7ffff6da95e8 ArrTy>, is_sizeof=true, min_alignof=false,
complain=1) at ../../src/trunk/gcc/c-family/c-common.c:3650
3650 value = fold_convert_loc (loc, size_type_node, value);
where TYPE_SIZE_UNIT of type is
((sizetype) (SAVE_EXPR <(ssizetype) arg - 1>) + 1) * 4
which is of course asking for trouble :/
In the end this is layout_type doing
2483 if (TYPE_SIZE_UNIT (element))
2484 TYPE_SIZE_UNIT (type)
2485 = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (element),
length);
on (sizetype) (SAVE_EXPR <(ssizetype) arg - 1>) + 1
The gimplifier is not set up to do unsharing across functions, so this has
to be fixed elsewhere. The particular case could be fixed in
c_sizeof_or_alignof_type by doing unshare_expr on TYPE_SIZE_UNIT for all
types that might be shared between functions (thus where the gimplifier
doesn't take care of unsharing).
Or we could make layout_type make sure to wrap all non-constant TYPE_*
in a SAVE_EXPR.
So the following patch restores the ICE we see in earlier releases.
I have audited all possibly variable-size processing in c-common.c.
Any comments?
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c (revision 262624)
+++ gcc/c-family/c-common.c (working copy)
@@ -3635,7 +3635,8 @@ c_sizeof_or_alignof_type (location_t loc
{
if (is_sizeof)
/* Convert in case a char is more than one unit. */
- value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+ value = size_binop_loc (loc, CEIL_DIV_EXPR,
+ unshare_expr (TYPE_SIZE_UNIT (type)),
size_int (TYPE_PRECISION (char_type_node)
/ BITS_PER_UNIT));
else if (min_alignof)
@@ -6210,7 +6211,8 @@ fold_offsetof (tree expr, tree type, enu
"member %qD", t);
return error_mark_node;
}
- off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
+ off = size_binop_loc (input_location, PLUS_EXPR,
+ unshare_expr (DECL_FIELD_OFFSET (t)),
size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
/ BITS_PER_UNIT));
break;
@@ -6266,7 +6268,8 @@ fold_offsetof (tree expr, tree type, enu
}
t = convert (sizetype, t);
- off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+ off = size_binop (MULT_EXPR,
+ unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (expr))), t);
break;
case COMPOUND_EXPR:
More information about the Gcc-bugs
mailing list