gimple, internal-fn: Add IFN_TRAP and use it for __builtin_unreachable [PR106099]

__builtin_unreachable and __ubsan_handle_builtin_unreachable don't
use vops, they are marked const/leaf/noreturn/nothrow/cold.
But __builtin_trap uses vops, isn't const, just leaf/noreturn/nothrow/cold.
This is I believe so that when users explicitly use __builtin_trap in their
sources they get stores visible at the trap side.
-fsanitize=unreachable -fsanitize-undefined-trap-on-error used to transform
__builtin_unreachable to __builtin_trap even in the past, but the sanopt pass
has TODO_update_ssa, so it worked fine.

Now that gimple_build_builtin_unreachable can build a __builtin_trap call
right away, we can run into problems that whenever we need it we would need
to either manually or through TODO_update* ensure the vops being updated.

Though, as it is originally __builtin_unreachable which is just implemented
as trap, I think for this case it is fine to avoid vops.  For this the
patch introduces IFN_TRAP, which has ECF_* flags like __builtin_unreachable
and is expanded as __builtin_trap.

2022-07-28  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/106099
	* internal-fn.def (TRAP): New internal fn.
	* internal-fn.h (expand_TRAP): Declare.
	* internal-fn.cc (expand_TRAP): Define.
	* gimple.cc (gimple_build_builtin_unreachable): For BUILT_IN_TRAP,
	use internal fn rather than builtin.

	* gcc.dg/ubsan/pr106099.c: New test.
This commit is contained in:
Jakub Jelinek 2022-07-28 12:42:14 +02:00
parent 0652087375
commit f64eb63667
5 changed files with 31 additions and 1 deletions

View File

@ -430,7 +430,16 @@ gimple_build_builtin_unreachable (location_t loc)
{
tree data = NULL_TREE;
tree fn = sanitize_unreachable_fn (&data, loc);
gcall *g = gimple_build_call (fn, data != NULL_TREE, data);
gcall *g;
if (DECL_FUNCTION_CODE (fn) != BUILT_IN_TRAP)
g = gimple_build_call (fn, data != NULL_TREE, data);
else
{
/* Instead of __builtin_trap use .TRAP, so that it doesn't
need vops. */
gcc_checking_assert (data == NULL_TREE);
g = gimple_build_call_internal (IFN_TRAP, 0);
}
gimple_set_location (g, loc);
return g;
}

View File

@ -4494,3 +4494,9 @@ expand_SPACESHIP (internal_fn, gcall *stmt)
if (!rtx_equal_p (target, ops[0].value))
emit_move_insn (target, ops[0].value);
}
void
expand_TRAP (internal_fn, gcall *)
{
expand_builtin_trap ();
}

View File

@ -456,6 +456,10 @@ DEF_INTERNAL_FN (SHUFFLEVECTOR, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
/* <=> optimization. */
DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
/* __builtin_trap created from/for __builtin_unreachable. */
DEF_INTERNAL_FN (TRAP, ECF_CONST | ECF_LEAF | ECF_NORETURN
| ECF_NOTHROW | ECF_COLD, NULL)
#undef DEF_INTERNAL_INT_FN
#undef DEF_INTERNAL_FLT_FN
#undef DEF_INTERNAL_FLT_FLOATN_FN

View File

@ -242,6 +242,7 @@ extern void expand_internal_call (internal_fn, gcall *);
extern void expand_PHI (internal_fn, gcall *);
extern void expand_SHUFFLEVECTOR (internal_fn, gcall *);
extern void expand_SPACESHIP (internal_fn, gcall *);
extern void expand_TRAP (internal_fn, gcall *);
extern bool vectorized_internal_fn_supported_p (internal_fn, tree);

View File

@ -0,0 +1,10 @@
/* PR tree-optimization/106099 */
/* { dg-do compile } */
/* { dg-options "-O -fsanitize=unreachable -fsanitize-undefined-trap-on-error -fno-tree-ccp -fno-tree-dominator-opts" } */
void
foo (void)
{
for (unsigned i = 0; i == 0; i++)
;
}