This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Fix the __bad_udelay lossage when CVS gcc compiles 2.4.0 kernel


Hi!

This patch fixes gcc.c-torture/execute/20010119-1.c (and when compiling some
linux 2.4.0 modules undefined __bad_udelay references). I wrote about what's
going on yesterday, but this patch is far simpler because it records just a
single machine mode in which (compare:CC* (const_{int,double}) (const_{int,double}))
should be done. Most machine descriptions use just a single register for
integer condition codes (either cc0_rtx or one hard register) and even when
they don't do so, compare is usually fairly close to if_then_else at
integrate time.
Ok to commit?
Bootstrapped on i386-redhat-linux, no regressions.

2001-01-23  Jakub Jelinek  <jakub@redhat.com>

	* integrate.h (struct inline_remap): Add compare_src, compare_mode.
	* integrate.c (expand_inline_function): Initialize them.
	(subst_constants): If changing COMPARE so that both its arguments
	will be VOIDmode and the comparison mode will be lost, note
	compare_mode.  Use the recorded compare_mode to optimize
	IF_THEN_ELSE.

--- gcc/integrate.h.jj	Thu Dec  7 10:57:28 2000
+++ gcc/integrate.h	Tue Jan 23 13:46:01 2001
@@ -112,6 +112,10 @@ struct inline_remap
   /* Record the last thing assigned to cc0.  */
   rtx last_cc0_value;
 #endif
+  /* Note mode of COMPARE if the mode would be otherwise lost (comparing of
+     two VOIDmode constants.  */
+  rtx compare_src;
+  enum machine_mode compare_mode;
 };
 
 /* Return a copy of an rtx (as needed), substituting pseudo-register,
--- gcc/integrate.c.jj	Sun Jan  7 12:30:15 2001
+++ gcc/integrate.c	Tue Jan 23 14:19:38 2001
@@ -788,6 +788,8 @@ expand_inline_function (fndecl, parms, t
   map->max_insnno = inl_max_uid;
 
   map->integrating = 1;
+  map->compare_src = NULL_RTX;
+  map->compare_mode = VOIDmode;
 
   /* const_equiv_varray maps pseudos in our routine to constants, so
      it needs to be large enough for all our pseudos.  This is the
@@ -2440,6 +2442,25 @@ subst_constants (loc, insn, map, memonly
 	rtx *dest_loc = &SET_DEST (x);
 	rtx dest = *dest_loc;
 	rtx src, tem;
+	enum machine_mode compare_mode = VOIDmode;
+
+	/* If SET_SRC is a COMPARE which subst_constants would turn into
+	   COMPARE of 2 VOIDmode constants, note the mode in which comparison
+	   is to be done.  */
+	if (GET_CODE (SET_SRC (x)) == COMPARE)
+	  {
+	    src = SET_SRC (x);
+	    if (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
+#ifdef HAVE_cc0
+		|| dest == cc0_rtx
+#endif
+		)
+	      {
+		compare_mode = GET_MODE (XEXP (src, 0));
+		if (compare_mode == VOIDmode)
+		  compare_mode = GET_MODE (XEXP (src, 1));
+	      }
+	  }
 
 	subst_constants (&SET_SRC (x), insn, map, memonly);
 	src = SET_SRC (x);
@@ -2495,8 +2516,22 @@ subst_constants (loc, insn, map, memonly
 	    /* Normally, this copy won't do anything.  But, if SRC is a COMPARE
 	       it will cause us to save the COMPARE with any constants
 	       substituted, which is what we want for later.  */
-	    map->equiv_sets[map->num_sets].equiv = copy_rtx (src);
+	    rtx src_copy = copy_rtx (src);
+	    map->equiv_sets[map->num_sets].equiv = src_copy;
 	    map->equiv_sets[map->num_sets++].dest = dest;
+	    if (compare_mode != VOIDmode
+		&& GET_CODE (src) == COMPARE
+		&& (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
+#ifdef HAVE_cc0
+		    || dest == cc0_rtx
+#endif
+		    )
+		&& GET_MODE (XEXP (src, 0)) == VOIDmode
+		&& GET_MODE (XEXP (src, 1)) == VOIDmode)
+	      {
+		map->compare_src = src_copy;
+		map->compare_mode = compare_mode;
+	      }
 	  }
       }
       return;
@@ -2600,9 +2635,34 @@ subst_constants (loc, insn, map, memonly
 	if (op0_mode == MAX_MACHINE_MODE)
 	  abort ();
 
-	new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
-					  XEXP (x, 0), XEXP (x, 1),
-					  XEXP (x, 2));
+	if (code == IF_THEN_ELSE)
+	  {
+	    rtx op0 = XEXP (x, 0);
+
+	    if (GET_RTX_CLASS (GET_CODE (op0)) == '<'
+		&& GET_MODE (op0) == VOIDmode
+		&& ! side_effects_p (op0)
+		&& XEXP (op0, 0) == map->compare_src
+		&& GET_MODE (XEXP (op0, 1)) == VOIDmode)
+	      {
+		/* We have compare of two VOIDmode constants for which
+		   we recorded the comparison mode.  */
+		rtx temp =
+		  simplify_relational_operation (GET_CODE (op0),
+						 map->compare_mode,
+						 XEXP (op0, 0),
+						 XEXP (op0, 1));
+
+		if (temp == const0_rtx)
+		  new = XEXP (x, 2);
+		else if (temp == const1_rtx)
+		  new = XEXP (x, 1);
+	      }
+	  }
+	if (!new)
+	  new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
+					    XEXP (x, 0), XEXP (x, 1),
+					    XEXP (x, 2));
 	break;
       }
 

	Jakub

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]