re PR target/77326 ([avr] Invalid optimization omits comparison)
authorGeorg-Johann Lay <avr@gjlay.de>
Wed, 21 Sep 2016 09:17:32 +0000 (09:17 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Wed, 21 Sep 2016 09:17:32 +0000 (09:17 +0000)
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

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/avr/torture/pr77326.c [new file with mode: 0644]

index 7fe08476e546b980274fa6ad7b4c6c616f930b81..b7c06f4993cfd3652376249a66cb98e5afb88f42 100644 (file)
@@ -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
index 148a61df7217f39115d72836a8cf32ac1a2b3f96..5ac65b7b82aad1dd185b1db4fc375815531219f4 100644 (file)
@@ -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;
index adc6422545816af9ac1b74ccf192e51598b1a149..bc9d2b01a1279ea3e19c211b17ee1baf347b2277 100644 (file)
@@ -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 (file)
index 0000000..7fe11ec
--- /dev/null
@@ -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;
+}