From b9a15a8325ba89b926e3c437b7961829a6b2fa2b Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Fri, 3 Jul 2020 17:37:33 +0200 Subject: [PATCH] ipa-sra: Avoid transitive splits with type mismatches (PR 96040) PR 96040 revealed IPA-SRA, when checking whether an intended split is the same as the one in a called function does not also check if the types match and the transformation code does not handle any resulting type mismatches. This patch simply avoids the the split in the case of mismatches, so that we do not have to be careful about invalid floating-point values being passed in floating point registers and related issues. gcc/ChangeLog: 2020-07-03 Martin Jambor PR ipa/96040 * ipa-sra.c (all_callee_accesses_present_p): Do not accept type mismatched accesses. gcc/testsuite/ChangeLog: 2020-07-03 Martin Jambor PR ipa/96040 * gcc.dg/ipa/pr96040.c: New test. --- gcc/ipa-sra.c | 4 ++- gcc/testsuite/gcc.dg/ipa/pr96040.c | 57 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/pr96040.c diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c index c81e8869e7a..03e3fc55daf 100644 --- a/gcc/ipa-sra.c +++ b/gcc/ipa-sra.c @@ -3271,7 +3271,9 @@ all_callee_accesses_present_p (isra_param_desc *param_desc, continue; param_access *pacc = find_param_access (param_desc, argacc->unit_offset, argacc->unit_size); - if (!pacc || !pacc->certain) + if (!pacc + || !pacc->certain + || !types_compatible_p (argacc->type, pacc->type)) return false; } return true; diff --git a/gcc/testsuite/gcc.dg/ipa/pr96040.c b/gcc/testsuite/gcc.dg/ipa/pr96040.c new file mode 100644 index 00000000000..af7e9c4ed94 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr96040.c @@ -0,0 +1,57 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -std=c99" } */ + + +int puts(const char *); +int snprintf(char *, unsigned long, const char *, ...); +unsigned long strspn(const char *, const char *); + +struct TValue { + union { + long long i; + double n; + } value_; + unsigned char tt_; +}; + +static int tostringbuff (struct TValue *num, char *str) { + int len; + if (num->tt_ == 3) { + len = snprintf(str,50,"%lld",num->value_.i); + } else { + len = snprintf(str,50,"%.14g",num->value_.n); + if (str[strspn(str, "-0123456789")] == '\0') { + str[len++] = '.'; + str[len++] = '0'; + } + } + return len; +} + +void unused (int *buff, struct TValue *num) { + char junk[50]; + *buff += tostringbuff(num, junk); +} + +char space[400]; + +void addnum2buff (int *buff, struct TValue *num) __attribute__((__noinline__)); +void addnum2buff (int *buff, struct TValue *num) { + *buff += tostringbuff(num, space); +} + +int __attribute__((noipa)) check_space (char *s) +{ + return (s[0] == '1' && s[1] == '.' && s[2] =='0' && s[3] == '\0'); +} + +int main(void) { + int buff = 0; + struct TValue num; + num.value_.n = 1.0; + num.tt_ = 19; + addnum2buff(&buff, &num); + if (!check_space(space)) + __builtin_abort (); + return 0; +} -- 2.30.2