This fixes an ICE if post-reload compare elimination is done and the target
supports post_inc and similar modes, as pdp11 does. The ICE is caused by a
generated PARALLEL that has the side effect twice, which is not legal.
(Ideally it would generate a similar RTL suitable for a matching constraint
with the side effect omitted; I may try for that later on if that is still
supported by the constraint machinery.)
Tested against my in-progress CCmode pdp11 target. Ok to commit?
paul
gcc/ChangeLog:
2018-06-05 Paul Koning <[email protected]>
* compare-elim.c (addr_side_effect_check): New function.
(addr_side_effect_p): Ditto.
(try_merge_compare): Don't merge compare if address contains a
side effect.
Index: compare-elim.c
===================================================================
--- compare-elim.c (revision 261207)
+++ compare-elim.c (working copy)
@@ -127,6 +127,23 @@
static vec<comparison *> all_compares;
+/* Callback function used by addr_side_effect_p. */
+static int
+addr_side_effect_check (rtx mem ATTRIBUTE_UNUSED, rtx op ATTRIBUTE_UNUSED,
+ rtx dest ATTRIBUTE_UNUSED, rtx src ATTRIBUTE_UNUSED,
+ rtx srcoff ATTRIBUTE_UNUSED, void *arg ATTRIBUTE_UNUSED)
+{
+ return 1;
+}
+
+/* Check if addr has side effects (contains autoinc or autodec
+ operations). */
+static int
+addr_side_effect_p (rtx addr)
+{
+ return for_each_inc_dec (addr, addr_side_effect_check, NULL);
+}
+
/* Look for a "conforming" comparison, as defined above. If valid, return
the rtx for the COMPARE itself. */
@@ -690,6 +707,13 @@
return false;
rtx src = SET_SRC (set);
+
+ /* If the source uses addressing modes with side effects, we can't
+ do the merge because we'd end up with a PARALLEL that has two
+ instances of that side effect in it. */
+ if (addr_side_effect_p (src))
+ return false;
+
rtx flags = maybe_select_cc_mode (cmp, src, CONST0_RTX (GET_MODE (src)));
if (!flags)
{
@@ -809,6 +833,12 @@
else
return false;
+ /* If the source uses addressing modes with side effects, we can't
+ do the merge because we'd end up with a PARALLEL that has two
+ instances of that side effect in it. */
+ if (addr_side_effect_p (cmp_src))
+ return false;
+
/* Determine if we ought to use a different CC_MODE here. */
flags = maybe_select_cc_mode (cmp, cmp_src, in_b);
if (flags == NULL)