public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Correct fix for scheduler bug PR11320
@ 2011-07-14 10:05 Bernd Schmidt
  2011-07-14 11:29 ` Andrey Belevantsev
                   ` (3 more replies)
  0 siblings, 4 replies; 25+ messages in thread
From: Bernd Schmidt @ 2011-07-14 10:05 UTC (permalink / raw)
  To: GCC Patches; +Cc: Eric Botcazou, Steve Ellcey, Vladimir N. Makarov

[-- Attachment #1: Type: text/plain, Size: 2341 bytes --]

PR11320 was a scheduler problem where an instruction was moved backwards
across a branch, leading to
	addl r14 = @ltoffx(.LC2), r1
	;;
	(p7) addl r14 = 1, r0		<--- r14 clobbered
	;;
	(p7) st4 [r15] = r14
	ld8.mov r14 = [r14], .LC2	<--- crash
	(branch was here)

At the time, this was solved by a patch that recognizes when a register
is conditionally set in a basic block, and then treats the branch as
setting such a register:

http://gcc.gnu.org/ml/gcc-patches/2003-07/msg01044.html

"The proposed fix is to say that JUMP_INSNs set the registers that are
live on entry of the fallthrough block and are conditionally set before
the jump, because they can be considered as restoring the former value
of the conditionally set registers."

While it is true that a jump could be seen as setting the correct value
for a register, this isn't at all related to conditional sets. Consider
a trivial example:

a = b + 3;
if (b > 0) { use a } else { use a }

where the value of a is different in each branch of the else, with no
conditional execution in sight. From the point of view of the uses, it
can be argued that the jump sets the value, but this is irrelevant for
scheduling purposes.

There's nothing wrong with using a wrong value in an instruction hoisted
across a branch if the result of that instruction will (eventually) be
dead. We do this all the time in sched-ebb. The patch needlessly
restricts scheduling opportunities and should be reverted.

The real problem here is that the ia64 backend lies to the rest of the
compiler; it produces a load instruction without showing a MEM anywhere
in the instruction pattern. Hence, the following patch, which reverts
the bogus scheduler changes and adds a MEM to a pattern in ia64.md. The
represenation is somewhat weird, but no more so than before where the
load was represented as a plain LO_SUM. The documentation I have doesn't
mention ld8.mov, so I'll have to leave it to the ia64 maintainers to
choose between this change or implement something more involved.

Bootstrapped and tested without regressions on ia64-linux with
languages=c,c++,obj,fortran and --disable-shared; that was what I could
get to work at all at the moment. Even then, C++ seems pretty broken.
I've also built a 3.3 cross-cc1 to see if the original bug is still
fixed (it is).

Ok (scheduler & ia64 bits)?


Bernd

[-- Attachment #2: pr11320.diff --]
[-- Type: text/plain, Size: 9898 bytes --]

	Revert
	2003-07-10  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR optimization/11320
	* sched-int.h (struct deps) [reg_conditional_sets]: New field.
	(struct sched_info) [compute_jump_reg_dependencies]: New prototype.
	* sched-deps.c (sched_analyze_insn) [JUMP_INSN]: Update call to
	current_sched_info->compute_jump_reg_dependencies. Record which
	registers are used and which registers are set by the jump.
	Clear deps->reg_conditional_sets after a barrier.
	Set deps->reg_conditional_sets if the insn is a COND_EXEC.
	Clear deps->reg_conditional_sets if the insn is not a COND_EXEC.
	(init_deps): Initialize reg_conditional_sets.
	(free_deps): Clear reg_conditional_sets.
	* sched-ebb.c (compute_jump_reg_dependencies): New prototype.
	Mark registers live on entry of the fallthrough block and conditionally
	set as set by the jump. Mark registers live on entry of non-fallthrough
	blocks as used by the jump.
	* sched-rgn.c (compute_jump_reg_dependencies): New prototype.
	Mark new parameters as unused.

	* config/ia64/ia64.md (load_symptr_low): Show a MEM.
	* config/ia64/ia64.c (ia64_expand_load_address): Generate it.

Index: gcc/sched-ebb.c
===================================================================
--- gcc/sched-ebb.c	(revision 176195)
+++ gcc/sched-ebb.c	(working copy)
@@ -238,28 +238,18 @@
   return 1;
 }
 
- /* INSN is a JUMP_INSN, COND_SET is the set of registers that are
-    conditionally set before INSN.  Store the set of registers that
-    must be considered as used by this jump in USED and that of
-    registers that must be considered as set in SET.  */
+ /* INSN is a JUMP_INSN.  Store the set of registers that
+    must be considered as used by this jump in USED.  */
 
 void
-ebb_compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used,
-				   regset set)
+ebb_compute_jump_reg_dependencies (rtx insn, regset used)
 {
   basic_block b = BLOCK_FOR_INSN (insn);
   edge e;
   edge_iterator ei;
 
   FOR_EACH_EDGE (e, ei, b->succs)
-    if (e->flags & EDGE_FALLTHRU)
-      /* The jump may be a by-product of a branch that has been merged
-	 in the main codepath after being conditionalized.  Therefore
-	 it may guard the fallthrough block from using a value that has
-	 conditionally overwritten that of the main codepath.  So we
-	 consider that it restores the value of the main codepath.  */
-      bitmap_and (set, df_get_live_in (e->dest), cond_set);
-    else
+    if ((e->flags & EDGE_FALLTHRU) == 0)
       bitmap_ior_into (used, df_get_live_in (e->dest));
 }
 
Index: gcc/modulo-sched.c
===================================================================
--- gcc/modulo-sched.c	(revision 176195)
+++ gcc/modulo-sched.c	(working copy)
@@ -252,9 +252,7 @@
 
 static void
 compute_jump_reg_dependencies (rtx insn ATTRIBUTE_UNUSED,
-			       regset cond_exec ATTRIBUTE_UNUSED,
-			       regset used ATTRIBUTE_UNUSED,
-			       regset set ATTRIBUTE_UNUSED)
+			       regset used ATTRIBUTE_UNUSED)
 {
 }
 
Index: gcc/sched-deps.c
===================================================================
--- gcc/sched-deps.c	(revision 176195)
+++ gcc/sched-deps.c	(working copy)
@@ -568,7 +568,7 @@
 	  (rev1==rev2
 	  ? reversed_comparison_code (cond2, NULL)
 	  : GET_CODE (cond2))
-      && XEXP (cond1, 0) == XEXP (cond2, 0)
+      && rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
       && XEXP (cond1, 1) == XEXP (cond2, 1))
     return 1;
   return 0;
@@ -2722,14 +2722,13 @@
 
           if (sched_deps_info->compute_jump_reg_dependencies)
             {
-              regset_head tmp_uses, tmp_sets;
-              INIT_REG_SET (&tmp_uses);
-              INIT_REG_SET (&tmp_sets);
+              regset_head tmp;
+              INIT_REG_SET (&tmp);
 
-              (*sched_deps_info->compute_jump_reg_dependencies)
-                (insn, &deps->reg_conditional_sets, &tmp_uses, &tmp_sets);
+              (*sched_deps_info->compute_jump_reg_dependencies) (insn, &tmp);
+
               /* Make latency of jump equal to 0 by using anti-dependence.  */
-              EXECUTE_IF_SET_IN_REG_SET (&tmp_uses, 0, i, rsi)
+              EXECUTE_IF_SET_IN_REG_SET (&tmp, 0, i, rsi)
                 {
                   struct deps_reg *reg_last = &deps->reg_last[i];
                   add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI);
@@ -2744,10 +2743,8 @@
                       reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses);
                     }
                 }
-              IOR_REG_SET (reg_pending_sets, &tmp_sets);
 
-              CLEAR_REG_SET (&tmp_uses);
-              CLEAR_REG_SET (&tmp_sets);
+              CLEAR_REG_SET (&tmp);
             }
 
 	  /* All memory writes and volatile reads must happen before the
@@ -2920,10 +2917,7 @@
 	      add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
 
 	      if (!deps->readonly)
-		{
-		  reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
-		  SET_REGNO_REG_SET (&deps->reg_conditional_sets, i);
-		}
+		reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
 	    }
 	}
       else
@@ -2985,7 +2979,6 @@
 		  reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
 		  reg_last->uses_length = 0;
 		  reg_last->clobbers_length = 0;
-		  CLEAR_REGNO_REG_SET (&deps->reg_conditional_sets, i);
 		}
 	    }
 	}
@@ -3083,8 +3076,6 @@
                              && sel_insn_is_speculation_check (insn)))
 	flush_pending_lists (deps, insn, true, true);
 
-      if (!deps->readonly)
-        CLEAR_REG_SET (&deps->reg_conditional_sets);
       reg_pending_barrier = NOT_A_BARRIER;
     }
 
@@ -3521,7 +3512,6 @@
   else
     deps->reg_last = XCNEWVEC (struct deps_reg, max_reg);
   INIT_REG_SET (&deps->reg_last_in_use);
-  INIT_REG_SET (&deps->reg_conditional_sets);
 
   deps->pending_read_insns = 0;
   deps->pending_read_mems = 0;
@@ -3590,7 +3580,6 @@
 	free_INSN_LIST_list (&reg_last->clobbers);
     }
   CLEAR_REG_SET (&deps->reg_last_in_use);
-  CLEAR_REG_SET (&deps->reg_conditional_sets);
 
   /* As we initialize reg_last lazily, it is possible that we didn't allocate
      it at all.  */
@@ -3600,8 +3589,7 @@
   deps = NULL;
 }
 
-/* Remove INSN from dependence contexts DEPS.  Caution: reg_conditional_sets
-   is not handled.  */
+/* Remove INSN from dependence contexts DEPS.  */
 void
 remove_from_deps (struct deps_desc *deps, rtx insn)
 {
Index: gcc/sched-int.h
===================================================================
--- gcc/sched-int.h	(revision 176195)
+++ gcc/sched-int.h	(working copy)
@@ -173,7 +173,7 @@
 
 extern int max_issue (struct ready_list *, int, state_t, bool, int *);
 
-extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
+extern void ebb_compute_jump_reg_dependencies (rtx, regset);
 
 extern edge find_fallthru_edge_from (basic_block);
 
@@ -511,9 +511,6 @@
      in reg_last[N].{uses,sets,clobbers}.  */
   regset_head reg_last_in_use;
 
-  /* Element N is set for each register that is conditionally set.  */
-  regset_head reg_conditional_sets;
-
   /* Shows the last value of reg_pending_barrier associated with the insn.  */
   enum reg_pending_barrier_mode last_reg_pending_barrier;
 
@@ -1117,7 +1114,7 @@
   /* Called when computing dependencies for a JUMP_INSN.  This function
      should store the set of registers that must be considered as set by
      the jump in the regset.  */
-  void (*compute_jump_reg_dependencies) (rtx, regset, regset, regset);
+  void (*compute_jump_reg_dependencies) (rtx, regset);
 
   /* Start analyzing insn.  */
   void (*start_insn) (rtx);
Index: gcc/sched-rgn.c
===================================================================
--- gcc/sched-rgn.c	(revision 176195)
+++ gcc/sched-rgn.c	(working copy)
@@ -2062,7 +2062,7 @@
 static int schedule_more_p (void);
 static const char *rgn_print_insn (const_rtx, int);
 static int rgn_rank (rtx, rtx);
-static void compute_jump_reg_dependencies (rtx, regset, regset, regset);
+static void compute_jump_reg_dependencies (rtx, regset);
 
 /* Functions for speculative scheduling.  */
 static void rgn_add_remove_insn (rtx, int);
@@ -2295,16 +2295,12 @@
   return BLOCK_TO_BB (BLOCK_NUM (next)) == BLOCK_TO_BB (BLOCK_NUM (insn));
 }
 
-/* INSN is a JUMP_INSN, COND_SET is the set of registers that are
-   conditionally set before INSN.  Store the set of registers that
-   must be considered as used by this jump in USED and that of
-   registers that must be considered as set in SET.  */
+/* INSN is a JUMP_INSN.  Store the set of registers that must be
+   considered as used by this jump in USED.  */
 
 static void
 compute_jump_reg_dependencies (rtx insn ATTRIBUTE_UNUSED,
-			       regset cond_exec ATTRIBUTE_UNUSED,
-			       regset used ATTRIBUTE_UNUSED,
-			       regset set ATTRIBUTE_UNUSED)
+			       regset used ATTRIBUTE_UNUSED)
 {
   /* Nothing to do here, since we postprocess jumps in
      add_branch_dependences.  */
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 176195)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -1047,7 +1047,7 @@
       tmp = gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
       emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
 
-      tmp = gen_rtx_LO_SUM (Pmode, dest, src);
+      tmp = gen_rtx_LO_SUM (Pmode, gen_rtx_MEM (Pmode, dest), src);
       emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
 
       if (addend)
Index: gcc/config/ia64/ia64.md
===================================================================
--- gcc/config/ia64/ia64.md	(revision 176195)
+++ gcc/config/ia64/ia64.md	(working copy)
@@ -777,7 +777,7 @@
 
 (define_insn "*load_symptr_low"
   [(set (match_operand:DI 0 "register_operand" "=r")
-	(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+	(lo_sum:DI (mem:DI (match_operand:DI 1 "register_operand" "r"))
 		   (match_operand 2 "got_symbolic_operand" "s")))]
   "reload_completed"
 {

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2011-08-05 18:19 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-14 10:05 Correct fix for scheduler bug PR11320 Bernd Schmidt
2011-07-14 11:29 ` Andrey Belevantsev
2011-07-14 11:42   ` Bernd Schmidt
2011-07-14 12:19 ` Eric Botcazou
2011-07-14 12:24   ` Bernd Schmidt
2011-07-14 12:39     ` Eric Botcazou
2011-07-14 13:09       ` Bernd Schmidt
2011-07-14 13:46         ` Eric Botcazou
2011-07-14 16:11 ` Richard Henderson
2011-07-14 16:27   ` Bernd Schmidt
2011-07-14 16:30     ` Bernd Schmidt
2011-07-14 16:34       ` Richard Henderson
2011-07-14 16:43         ` Bernd Schmidt
2011-07-14 16:44     ` Richard Henderson
2011-07-14 16:48       ` Bernd Schmidt
2011-07-14 19:48         ` Richard Henderson
2011-07-19 13:00 ` Andreas Schwab
2011-07-19 14:13   ` Bernd Schmidt
2011-07-19 14:41     ` Andreas Schwab
2011-07-22 14:12   ` Bernd Schmidt
2011-07-22 17:28     ` Eric Botcazou
2011-07-22 18:36       ` Richard Henderson
2011-07-22 18:44         ` Bernd Schmidt
2011-08-05 17:54           ` Bernd Schmidt
2011-08-05 18:45             ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).