diff options
author | Kyrylo Tkachov <kyrylo.tkachov@arm.com> | 2016-07-05 16:37:40 +0000 |
---|---|---|
committer | Kyrylo Tkachov <ktkachov@gcc.gnu.org> | 2016-07-05 16:37:40 +0000 |
commit | 7a98fb6ed6f1b1b7d78466dfdb66bb919740098e (patch) | |
tree | 0ba36dd360470fd0381b51efa94c83ba0c3fa0f8 /gcc | |
parent | 1e3d54b4299c69b4e40205dd7d6cabc888b307c5 (diff) | |
download | gcc-7a98fb6ed6f1b1b7d78466dfdb66bb919740098e.zip gcc-7a98fb6ed6f1b1b7d78466dfdb66bb919740098e.tar.gz gcc-7a98fb6ed6f1b1b7d78466dfdb66bb919740098e.tar.bz2 |
[RTL ifcvt] PR rtl-optimization/71594: ICE in noce_emit_cmove due to mismatched source modes
PR rtl-optimization/71594
* ifcvt.c (noce_convert_multiple_sets): Wrap new_val or old_val
into subregs of appropriate mode before trying to emit a conditional
move.
* gcc.dg/torture/pr71594.c: New test.
From-SVN: r238013
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/ifcvt.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr71594.c | 15 |
4 files changed, 62 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c746866..f189d6a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-07-05 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR rtl-optimization/71594 + * ifcvt.c (noce_convert_multiple_sets): Wrap new_val or old_val + into subregs of appropriate mode before trying to emit a conditional + move. + 2016-07-05 Jan Hubicka <jh@suse.cz> * tree-scalar-evolution.c (iv_can_overflow_p): New function. diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index fd29516..f7f120e 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -3228,6 +3228,41 @@ noce_convert_multiple_sets (struct noce_if_info *if_info) if (if_info->then_else_reversed) std::swap (old_val, new_val); + + /* We allow simple lowpart register subreg SET sources in + bb_ok_for_noce_convert_multiple_sets. Be careful when processing + sequences like: + (set (reg:SI r1) (reg:SI r2)) + (set (reg:HI r3) (subreg:HI (r1))) + For the second insn new_val or old_val (r1 in this example) will be + taken from the temporaries and have the wider mode which will not + match with the mode of the other source of the conditional move, so + we'll end up trying to emit r4:HI = cond ? (r1:SI) : (r3:HI). + Wrap the two cmove operands into subregs if appropriate to prevent + that. */ + if (GET_MODE (new_val) != GET_MODE (temp)) + { + machine_mode src_mode = GET_MODE (new_val); + machine_mode dst_mode = GET_MODE (temp); + if (GET_MODE_SIZE (src_mode) <= GET_MODE_SIZE (dst_mode)) + { + end_sequence (); + return FALSE; + } + new_val = lowpart_subreg (dst_mode, new_val, src_mode); + } + if (GET_MODE (old_val) != GET_MODE (temp)) + { + machine_mode src_mode = GET_MODE (old_val); + machine_mode dst_mode = GET_MODE (temp); + if (GET_MODE_SIZE (src_mode) <= GET_MODE_SIZE (dst_mode)) + { + end_sequence (); + return FALSE; + } + old_val = lowpart_subreg (dst_mode, old_val, src_mode); + } + /* Actually emit the conditional move. */ rtx temp_dest = noce_emit_cmove (if_info, temp, cond_code, x, y, new_val, old_val); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d57f9c3..13e3d68 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-07-05 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR rtl-optimization/71594 + * gcc.dg/torture/pr71594.c: New test. + 2016-07-05 Jan Hubicka <jh@suse.cz> * gcc.dg/tree-ssa/scev-14.c: new testcase. diff --git a/gcc/testsuite/gcc.dg/torture/pr71594.c b/gcc/testsuite/gcc.dg/torture/pr71594.c new file mode 100644 index 0000000..468a9f6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr71594.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "--param max-rtl-if-conversion-insns=2" } */ + +unsigned short a; +int b, c; +int *d; +void fn1() { + *d = 24; + for (; *d <= 65;) { + unsigned short *e = &a; + b = (a &= 0 <= 0) < (c ?: (*e %= *d)); + for (; *d <= 83;) + ; + } +} |