aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2016-09-21 09:17:32 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2016-09-21 09:17:32 +0000
commitbc084f84b3baee7b9fdc73cc05b6aa8adf1e97e5 (patch)
treede1b810bcf4ee0b024d117dbedd3ed67f5be8921 /gcc
parentc075003a1fc901d487c4cca0b10847d8fc1135fb (diff)
downloadgcc-bc084f84b3baee7b9fdc73cc05b6aa8adf1e97e5.zip
gcc-bc084f84b3baee7b9fdc73cc05b6aa8adf1e97e5.tar.gz
gcc-bc084f84b3baee7b9fdc73cc05b6aa8adf1e97e5.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/avr/avr.c40
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/pr77326.c26
4 files changed, 75 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7fe0847..b7c06f4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2016-09-21 Georg-Johann Lay <avr@gjlay.de>
+
+ 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 <rguenther@suse.de>
PR tree-optimization/77648
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 148a61d..5ac65b7 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, &regs_used);
+ }
+
+ if (cc_status.value2
+ && !CONSTANT_P (cc_status.value2))
+ {
+ find_all_hard_regs (cc_status.value2, &regs_used);
+ }
+
+ find_all_hard_reg_sets (insn, &regs_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 adc6422..bc9d2b0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-09-21 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/77326
+ * gcc.target/avr/torture/pr77326.c: New test.
+
2016-09-21 Louis Krupp <louis.krupp@zoho.com>
* 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 0000000..7fe11ec
--- /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;
+}