Avoid optimizing memory references with side effects in compare-elim.c

Message ID 349DB135-BAC7-416E-9D8E-12A65CC21F1B@comcast.net
State New
Headers show
Series
  • Avoid optimizing memory references with side effects in compare-elim.c
Related show

Commit Message

Paul Koning June 5, 2018, 5:49 p.m.
(Resending -- forgot to include a test case.)

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  <ni1d@arrl.net>

	* 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.
	* gcc.c-torture/compile/20180605-1.c: New test case.

Patch

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)
Index: testsuite/gcc.c-torture/compile/20180605-1.c
===================================================================
--- testsuite/gcc.c-torture/compile/20180605-1.c	(nonexistent)
+++ testsuite/gcc.c-torture/compile/20180605-1.c	(working copy)
@@ -0,0 +1,9 @@ 
+void f (int *p, int n)
+{
+    int j = 0, k;
+    
+    for (int i = 0; i < n; i++)
+        if ((k = *p++) > 0)
+            j += k;
+    return j;
+}