diff options
author | Mikael Pettersson <mikpe@it.uu.se> | 2014-02-27 20:02:18 +0100 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2014-02-27 12:02:18 -0700 |
commit | 728acca06e395451f2aa26ffbadb8b90af24c90b (patch) | |
tree | 54fb29df472b4dafd12a4cf8703a088a272047d7 /gcc/cse.c | |
parent | b076556843574ba6beb9712502af8ed135944b83 (diff) | |
download | gcc-728acca06e395451f2aa26ffbadb8b90af24c90b.zip gcc-728acca06e395451f2aa26ffbadb8b90af24c90b.tar.gz gcc-728acca06e395451f2aa26ffbadb8b90af24c90b.tar.bz2 |
re PR rtl-optimization/49847 (NULL deref in fold_rtx (prev_insn_cc0 == NULL))
PR rtl-optimization/49847
* cse.c (fold_rtx) Handle case where cc0 setter and cc0 user
are in different blocks.
* doc/tm.texi (Condition Code Status): Update documention for
relative locations of cc0-setter and cc0-user.
PR rtl-optimization/49847
* g++.dg/pr49847.C: New test.
Co-Authored-By: Jeff Law <law@redhat.com>
From-SVN: r208203
Diffstat (limited to 'gcc/cse.c')
-rw-r--r-- | gcc/cse.c | 24 |
1 files changed, 21 insertions, 3 deletions
@@ -3199,9 +3199,27 @@ fold_rtx (rtx x, rtx insn) #ifdef HAVE_cc0 case CC0: - folded_arg = prev_insn_cc0; - mode_arg = prev_insn_cc0_mode; - const_arg = equiv_constant (folded_arg); + /* The cc0-user and cc0-setter may be in different blocks if + the cc0-setter potentially traps. In that case PREV_INSN_CC0 + will have been cleared as we exited the block with the + setter. + + While we could potentially track cc0 in this case, it just + doesn't seem to be worth it given that cc0 targets are not + terribly common or important these days and trapping math + is rarely used. The combination of those two conditions + necessary to trip this situation is exceedingly rare in the + real world. */ + if (!prev_insn_cc0) + { + const_arg = NULL_RTX; + } + else + { + folded_arg = prev_insn_cc0; + mode_arg = prev_insn_cc0_mode; + const_arg = equiv_constant (folded_arg); + } break; #endif |