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]
Other format: [Raw text]

Fix PR rtl-optimization/28636


It's a regression present at -O2 on the 4.0 and 4.1 branches (latent on 
the mainline) for LP64 IA-64 platforms.  The interesting bits are:

struct input_ty
{
  unsigned char *buffer_position;
  unsigned char *buffer_end;
};

int check_header (struct input_ty *deeper)
{
[...]
    if (((deeper)->buffer_position < (deeper)->buffer_end
         ? *((deeper)->buffer_position)++
         : input_getc_complicated((deeper))) < 0)


It turns out that, even at -O2, the RTL combiner is the first pass to deduce 
that

  *((deeper)->buffer_position)++ < 0

is always false.  So it will simplify the condition; but on IA-64 the load 
contains a POST_INC

(insn 22 21 24 2 (set (reg:DI 352)
        (zero_extend:DI (mem:QI (post_inc:DI (reg:DI 343 [ D.1386 ])) [0 S1 
A8]))) 35 {zero_extendqidi2} (nil)
    (expr_list:REG_INC (reg:DI 343 [ D.1386 ])
        (nil)))

and this will get lost in the process.  The simplification to zero can happen 
in (at least) 3 places in the combiner which all need to test for side-effects 
in order to get correct code on the 4.1 branch.


The problem does not show up on the mainline because fold_binary is able to 
simplify

  (int) <unsigned char expr> < 0

to false during parsing, thanks to

2006-02-24  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (fold_comparison): New subroutine of fold_binary
	containing transformations common to both the equality and
	ordering relational operators, factored out of fold_binary.
	(fold_binary): Separate out the equality operators (EQ_EXPR
	and NE_EXPR) from the ordering operators (LT_EXPR, GT_EXPR,
	LE_EXPR and GE_EXPR), calling fold_comparison to perform the
	transformations common to both.
	(fold_div_compare): Fix latent bugs in the previously unreachable
	LT_EXPR and GE_EXPR cases.

The code in fold_binary that triggers on the mainline is present on the 4.1 
branch but the function is so convoluted in the latter case as to prevent 
this code from simply being reached...


Bootstrapped/regtested on IA-64/HP-UX, applied to all active branches.  It has 
no effects on the gcc.c-torture/compile testcases at -O2 on this platform.


2006-09-10  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR rtl-optimization/28636
	* combine.c (force_to_mode): Test for side-effects before
	substituting by zero.
	(simplify_shift_const): Likewise for zero or other constants.


2006-09-10  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* gcc.c-torture/execute/20060910-1.c: New test.


-- 
Eric Botcazou
Index: combine.c
===================================================================
--- combine.c	(revision 116795)
+++ combine.c	(working copy)
@@ -7022,7 +7022,7 @@ force_to_mode (rtx x, enum machine_mode 
   nonzero = nonzero_bits (x, mode);
 
   /* If none of the bits in X are needed, return a zero.  */
-  if (! just_select && (nonzero & mask) == 0)
+  if (!just_select && (nonzero & mask) == 0 && !side_effects_p (x))
     x = const0_rtx;
 
   /* If X is a CONST_INT, return a new one.  Do this here since the
@@ -8802,14 +8802,14 @@ simplify_shift_const (rtx x, enum rtx_co
 	      == 0))
 	code = LSHIFTRT;
 
-      if (code == LSHIFTRT
-	  && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
-	  && !(nonzero_bits (varop, shift_mode) >> count))
-	varop = const0_rtx;
-      if (code == ASHIFT
-	  && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
-	  && !((nonzero_bits (varop, shift_mode) << count)
-	       & GET_MODE_MASK (shift_mode)))
+      if (((code == LSHIFTRT
+	    && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+	    && !(nonzero_bits (varop, shift_mode) >> count))
+	   || (code == ASHIFT
+	       && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+	       && !((nonzero_bits (varop, shift_mode) << count)
+		    & GET_MODE_MASK (shift_mode))))
+	  && !side_effects_p (varop))
 	varop = const0_rtx;
 
       switch (GET_CODE (varop))
@@ -9443,9 +9443,12 @@ simplify_shift_const (rtx x, enum rtx_co
       if (outer_op == AND)
 	x = simplify_and_const_int (NULL_RTX, result_mode, x, outer_const);
       else if (outer_op == SET)
-	/* This means that we have determined that the result is
-	   equivalent to a constant.  This should be rare.  */
-	x = GEN_INT (outer_const);
+	{
+	  /* This means that we have determined that the result is
+	     equivalent to a constant.  This should be rare.  */
+	  if (!side_effects_p (x))
+	    x = GEN_INT (outer_const);
+	}
       else if (GET_RTX_CLASS (outer_op) == RTX_UNARY)
 	x = simplify_gen_unary (outer_op, result_mode, x, result_mode);
       else
/* PR rtl-optimization/28636 */
/* Origin: Andreas Schwab <schwab@suse.de> */

extern void abort(void);

struct input_ty
{
  unsigned char *buffer_position;
  unsigned char *buffer_end;
};

int input_getc_complicated (struct input_ty *x) { return 0; }

int check_header (struct input_ty *deeper)
{
  unsigned len;
  for (len = 0; len < 6; len++)
    if (((deeper)->buffer_position < (deeper)->buffer_end
         ? *((deeper)->buffer_position)++
         : input_getc_complicated((deeper))) < 0)
      return 0;
  return 1;
}

struct input_ty s;
unsigned char b[6];

int main (void)
{
  s.buffer_position = b;
  s.buffer_end = b + sizeof b;
  if (!check_header(&s))
    abort();
  if (s.buffer_position != s.buffer_end)
    abort();
  return 0;
}

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