If we have

i1: [r1 + 24] = x
i2: r1 = r1 + 24;
i3: y = [r1]

then, if not using cselib, we do not generate a dependency between i3
and i1, since we compare memory addresses [r1] and [r1 + 24]. This is
somewhat lame, but safe since i2 depends on i1 and i3 depends on i2.
However, it breaks with the new optimization I've recently added, which
allows us to switch i3 and i2 by modifying the address in i3. We can end
up with
i3: y = [r1 + 24]
i1: [r1 + 24] = x
i2: r1 = r1 + 24
which is incorrect.

The following patch is a conservative way of fixing this by simply
transferring all backwards dependencies from i2 to i3. I thought about
trying to do better when using cselib for a while, but I wasn't quite
certain how flush_pending_lists would interact with this, and it almost
certainly doesn't really matter.

Bootstrapped and tested on x86_64-linux (boehm-gc.c/gctest.c appears to
fail randomly, otherwise no changes). Ok?


Bernd
	* sched-deps.c (find_inc): Add all dependencies from the inc_insn
	to the mem_insn.

Index: sched-deps.c
===================================================================
--- sched-deps.c	(revision 191838)
+++ sched-deps.c	(working copy)
@@ -4706,16 +4706,14 @@ find_inc (struct mem_inc_info *mii, bool
 	  if (backwards)
 	    {
 	      FOR_EACH_DEP (mii->inc_insn, SD_LIST_BACK, sd_it, dep)
-		if (modified_in_p (mii->inc_input, DEP_PRO (dep)))
-		  add_dependence_1 (mii->mem_insn, DEP_PRO (dep),
-				    REG_DEP_TRUE);
+		add_dependence_1 (mii->mem_insn, DEP_PRO (dep),
+				  REG_DEP_TRUE);
 	    }
 	  else
 	    {
 	      FOR_EACH_DEP (mii->inc_insn, SD_LIST_FORW, sd_it, dep)
-		if (modified_in_p (mii->inc_input, DEP_CON (dep)))
-		  add_dependence_1 (DEP_CON (dep), mii->mem_insn,
-				    REG_DEP_ANTI);
+		add_dependence_1 (DEP_CON (dep), mii->mem_insn,
+				  REG_DEP_ANTI);
 	    }
 	  return true;
 	}

Reply via email to