Fix tree-optimization/101941: IPA splitting out function with error attribute

The Linux kernel started to fail compile when the jump threader was improved
(r12-2591-g2e96b5f14e4025691). This failure was due to the IPA splitting code
decided now to split off the basic block which contained two functions,
one of those functions included the error attribute on them.  This patch fixes
the problem by disallowing basic blocks from being split which contain functions
that have either the error or warning attribute on them.

The two new testcases are to make sure we still split the function for other
places if we reject the one case.

Committed as approved after Bootstrapped and tested on x86_64-linux-gnu with no regressions.

	PR tree-optimization/101941

gcc/ChangeLog:

	* ipa-split.cc (visit_bb): Disallow function calls where
	the function has either error or warning attribute.

gcc/testsuite/ChangeLog:

	* gcc.c-torture/compile/pr101941-1.c: New test.
	* gcc.dg/tree-ssa/pr101941-1.c: New test.
This commit is contained in:
Andrew Pinski 2021-11-17 02:45:22 +00:00
parent 8f6b62e0f0
commit 76fe494230
3 changed files with 149 additions and 28 deletions

View file

@ -873,7 +873,6 @@ visit_bb (basic_block bb, basic_block return_bb,
gimple *stmt = gsi_stmt (bsi);
tree op;
ssa_op_iter iter;
tree decl;
if (is_gimple_debug (stmt))
continue;
@ -899,33 +898,52 @@ visit_bb (basic_block bb, basic_block return_bb,
can_split = false;
}
/* Check builtins that prevent splitting. */
if (gimple_code (stmt) == GIMPLE_CALL
&& (decl = gimple_call_fndecl (stmt)) != NULL_TREE
&& fndecl_built_in_p (decl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (decl))
{
/* FIXME: once we will allow passing non-parm values to split part,
we need to be sure to handle correct builtin_stack_save and
builtin_stack_restore. At the moment we are safe; there is no
way to store builtin_stack_save result in non-SSA variable
since all calls to those are compiler generated. */
case BUILT_IN_APPLY:
case BUILT_IN_APPLY_ARGS:
case BUILT_IN_VA_START:
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Cannot split: builtin_apply and va_start.\n");
can_split = false;
break;
case BUILT_IN_EH_POINTER:
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Cannot split: builtin_eh_pointer.\n");
can_split = false;
break;
default:
break;
}
/* Check calls that would prevent splitting. */
if (gimple_code (stmt) == GIMPLE_CALL)
{
if (tree decl = gimple_call_fndecl (stmt))
{
/* Check builtins that would prevent splitting. */
if (fndecl_built_in_p (decl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (decl))
{
/* FIXME: once we will allow passing non-parm values to
split part, we need to be sure to handle correct
builtin_stack_save and builtin_stack_restore. At the
moment we are safe; there is no way to store
builtin_stack_save result in non-SSA variable since all
calls to those are compiler generated. */
case BUILT_IN_APPLY:
case BUILT_IN_APPLY_ARGS:
case BUILT_IN_VA_START:
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Cannot split: builtin_apply and va_start.\n");
can_split = false;
break;
case BUILT_IN_EH_POINTER:
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Cannot split: builtin_eh_pointer.\n");
can_split = false;
break;
default:
break;
}
/* Calls that function has either the warning or error
attribute on it should not be split off into another
function. */
if (lookup_attribute ("warning", DECL_ATTRIBUTES (decl))
|| lookup_attribute ("error", DECL_ATTRIBUTES (decl)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Cannot split: warning or error attribute.\n");
can_split = false;
}
}
}
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
bitmap_set_bit (set_ssa_names, SSA_NAME_VERSION (op));

View file

@ -0,0 +1,50 @@
/* { dg-additional-options "-fconserve-stack" } */
/* Check to make sure that if
rfc4106_set_hash_subkey gets split,
the error function does not gets split away
from the if statement conditionalizing it. */
struct crypto_aes_ctx {
char key_dec[128];
};
int rfc4106_set_hash_subkey_hash_subkey;
void __write_overflow(void)__attribute__((__error__("")));
void __write_overflow1(void);
void aes_encrypt(void*);
void fortify_panic(const char*) __attribute__((__noreturn__)) ;
char *rfc4106_set_hash_subkey(struct crypto_aes_ctx *ctx) {
void *a = &ctx->key_dec[0];
unsigned p_size = __builtin_object_size(a, 0);
#ifdef __OPTIMIZE__
if (p_size < 16) {
__write_overflow1();
fortify_panic(__func__);
}
if (p_size < 32) {
__write_overflow();
fortify_panic(__func__);
}
#endif
aes_encrypt(ctx);
return ctx->key_dec;
}
char *(*gg)(struct crypto_aes_ctx *) = rfc4106_set_hash_subkey;
void a(void)
{
struct crypto_aes_ctx ctx;
rfc4106_set_hash_subkey(&ctx);
}
void b(void)
{
struct crypto_aes_ctx ctx;
ctx.key_dec[0] = 0;
rfc4106_set_hash_subkey(&ctx);
}

View file

@ -0,0 +1,53 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fconserve-stack -fdump-tree-optimized" } */
/* Check to make sure that if
rfc4106_set_hash_subkey gets split,
the error function does not gets split away
from the if statement conditionalizing it.
Checking this via the scan tree also. */
struct crypto_aes_ctx {
char key_dec[128];
};
int rfc4106_set_hash_subkey_hash_subkey;
void __write_overflow(void)__attribute__((__error__("")));
void __write_overflow1(void);
void aes_encrypt(void*);
void fortify_panic(const char*) __attribute__((__noreturn__)) ;
char *rfc4106_set_hash_subkey(struct crypto_aes_ctx *ctx) {
void *a = &ctx->key_dec[0];
unsigned p_size = __builtin_object_size(a, 0);
#ifdef __OPTIMIZE__
if (p_size < 16) {
__write_overflow1();
fortify_panic(__func__);
}
if (p_size < 32) {
__write_overflow();
fortify_panic(__func__);
}
#endif
aes_encrypt(ctx);
return ctx->key_dec;
}
char *(*gg)(struct crypto_aes_ctx *) = rfc4106_set_hash_subkey;
void a(void)
{
struct crypto_aes_ctx ctx;
rfc4106_set_hash_subkey(&ctx);
}
void b(void)
{
struct crypto_aes_ctx ctx;
ctx.key_dec[0] = 0;
rfc4106_set_hash_subkey(&ctx);
}
/* This testcase should still split out one of the above basic blocks dealing
with __write_overflow. */
/* { dg-final { scan-tree-dump-times "Function rfc4106_set_hash_subkey.part" 1 "optimized" } } */