From: Georg-Johann Lay Date: Wed, 21 Sep 2016 09:17:32 +0000 (+0000) Subject: re PR target/77326 ([avr] Invalid optimization omits comparison) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bc084f84b3baee7b9fdc73cc05b6aa8adf1e97e5;p=gcc.git re PR target/77326 ([avr] Invalid optimization omits comparison) gcc/ PR target/77326 * config/avr/avr.c (avr_notice_update_cc) [CC_NONE]: If insn touches some regs mentioned in cc_status, do CC_STATUS_INIT. gcc/testsuite/ PR target/77326 * gcc.target/avr/torture/pr77326.c: New test. From-SVN: r240306 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7fe08476e54..b7c06f4993c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-09-21 Georg-Johann Lay + + PR target/77326 + * config/avr/avr.c (avr_notice_update_cc) [CC_NONE]: If insn + touches some regs mentioned in cc_status, do CC_STATUS_INIT. + 2016-09-21 Richard Biener PR tree-optimization/77648 diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 148a61df721..5ac65b7b82a 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -2511,8 +2511,44 @@ avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn) break; case CC_NONE: - /* Insn does not affect CC at all. */ - break; + /* Insn does not affect CC at all, but it might set some registers + that are stored in cc_status. If such a register is affected by + the current insn, for example by means of a SET or a CLOBBER, + then we must reset cc_status; cf. PR77326. + + Unfortunately, set_of cannot be used as reg_overlap_mentioned_p + will abort on COMPARE (which might be found in cc_status.value1/2). + Thus work out the registers set by the insn and regs mentioned + in cc_status.value1/2. */ + + if (cc_status.value1 + || cc_status.value2) + { + HARD_REG_SET regs_used; + HARD_REG_SET regs_set; + CLEAR_HARD_REG_SET (regs_used); + + if (cc_status.value1 + && !CONSTANT_P (cc_status.value1)) + { + find_all_hard_regs (cc_status.value1, ®s_used); + } + + if (cc_status.value2 + && !CONSTANT_P (cc_status.value2)) + { + find_all_hard_regs (cc_status.value2, ®s_used); + } + + find_all_hard_reg_sets (insn, ®s_set, false); + + if (hard_reg_set_intersect_p (regs_used, regs_set)) + { + CC_STATUS_INIT; + } + } + + break; // CC_NONE case CC_SET_N: CC_STATUS_INIT; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index adc64225458..bc9d2b01a12 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-09-21 Georg-Johann Lay + + PR target/77326 + * gcc.target/avr/torture/pr77326.c: New test. + 2016-09-21 Louis Krupp * gfortran.dg/pr68078.f90: Run on x86_64_*_linux* only. diff --git a/gcc/testsuite/gcc.target/avr/torture/pr77326.c b/gcc/testsuite/gcc.target/avr/torture/pr77326.c new file mode 100644 index 00000000000..7fe11ec390a --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr77326.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-Wl,--defsym,test1=0" } */ + +extern void test1 (void) __attribute__((weak)); + +__attribute__((noinline,noclone)) +static void va_pseudo (int flag, ...) +{ + __asm ("nop":); +} + +__attribute__((noinline,noclone)) +static void func (void) +{ + va_pseudo (0, 0, 0, 0); + + if (test1) + __builtin_abort (); +} + +int main (void) +{ + func(); + __builtin_exit (0); + return 0; +}