tree-optimization/101868 - avoid PRE of trapping mems across calls

This backports a fix for the omission of a check of trapping mems
when hoisting them across calls that might not return.  This was
originally done as part of a fix to handle const functions that throw
properly.

2021-08-17  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/101373
	PR tree-optimization/101868
	* tree-ssa-pre.c (prune_clobbered_mems): Also prune trapping
	references when the BB may not return.

	* gcc.dg/lto/pr101868_0.c: New testcase.
	* gcc.dg/lto/pr101868_1.c: Likewise.
	* gcc.dg/lto/pr101868_2.c: Likewise.
	* gcc.dg/lto/pr101868_3.c: Likewise.
This commit is contained in:
Richard Biener 2021-08-17 08:38:35 +02:00
parent a0a0499b8b
commit ee875b63b2
5 changed files with 82 additions and 0 deletions

View File

@ -0,0 +1,33 @@
/* { dg-lto-do run } */
/* { dg-lto-options { "-O2 -fno-strict-aliasing -flto" } } */
typedef unsigned long VALUE;
__attribute__ ((cold))
void rb_check_type(VALUE, int);
static VALUE
repro(VALUE dummy, VALUE hash)
{
if (hash == 0) {
rb_check_type(hash, 1);
}
else if (*(long *)hash) {
rb_check_type(hash, 1);
}
return *(long *)hash;
}
static VALUE (*that)(VALUE dummy, VALUE hash) = repro;
int
main(int argc, char **argv)
{
argc--;
that(0, argc);
rb_check_type(argc, argc);
}

View File

@ -0,0 +1,23 @@
typedef unsigned long VALUE;
__attribute__ ((noreturn)) void rexc_raise(VALUE mesg);
VALUE rb_donothing(VALUE klass);
static void
funexpected_type(VALUE x, int xt, int t)
{
rexc_raise(rb_donothing(0));
}
__attribute__ ((cold))
void
rb_check_type(VALUE x, int t)
{
int xt;
if (x == 0) {
funexpected_type(x, xt, t);
}
}

View File

@ -0,0 +1,11 @@
typedef unsigned long VALUE;
static void thing(void) {}
static void (*ptr)(void) = &thing;
VALUE
rb_donothing(VALUE klass)
{
ptr();
return 0;
}

View File

@ -0,0 +1,8 @@
typedef unsigned long VALUE;
__attribute__((noreturn))
void
rexc_raise(VALUE mesg)
{
__builtin_exit(0);
}

View File

@ -2070,6 +2070,13 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block)
&& value_dies_in_block_x (expr, block))))
to_remove = i;
}
/* If the REFERENCE may trap make sure the block does not contain
a possible exit point.
??? This is overly conservative if we translate AVAIL_OUT
as the available expression might be after the exit point. */
if (BB_MAY_NOTRETURN (block)
&& vn_reference_may_trap (ref))
to_remove = i;
}
else if (expr->kind == NARY)
{