aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr
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/config/avr
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/config/avr')
-rw-r--r--gcc/config/avr/avr.c40
1 files changed, 38 insertions, 2 deletions
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;