diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2016-09-21 09:17:32 +0000 |
---|---|---|
committer | Georg-Johann Lay <gjl@gcc.gnu.org> | 2016-09-21 09:17:32 +0000 |
commit | bc084f84b3baee7b9fdc73cc05b6aa8adf1e97e5 (patch) | |
tree | de1b810bcf4ee0b024d117dbedd3ed67f5be8921 /gcc/config/avr | |
parent | c075003a1fc901d487c4cca0b10847d8fc1135fb (diff) | |
download | gcc-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.c | 40 |
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, ®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; |