PATCH: robust min/max wrt constants

DJ Delorie dj@redhat.com
Fri Jul 27 12:45:00 GMT 2001


Follow up to http://gcc.gnu.org/ml/gcc-patches/2001-07/msg00901.html

Minor change to set cond_earliest correctly.  No regressions on
ix86-linux or ia64-linux.

2001-07-27  DJ Delorie  <dj@redhat.com>

	* ifcvt.c (noce_get_alt_condition): If the condition is a
	compare against a constant, try to adjust the compare to have
	the desired constant in it so that min/max optimizations
	happen more often.

Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.58
diff -p -3 -r1.58 ifcvt.c
*** ifcvt.c	2001/07/22 21:42:35	1.58
--- ifcvt.c	2001/07/27 19:26:41
***************
*** 1,5 ****
  /* If-conversion support.
!    Copyright (C) 2000 Free Software Foundation, Inc.
  
     This file is part of GNU CC.
  
--- 1,5 ----
  /* If-conversion support.
!    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
  
     This file is part of GNU CC.
  
*************** noce_get_alt_condition (if_info, target,
*** 1149,1154 ****
--- 1149,1262 ----
    reverse
      = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
        && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (if_info->jump);
+ 
+   /* If we're looking for a constant, try to make the conditional
+      have that constant in it.  There are two reasons why it may
+      not have the constant we want:
+ 
+      1. GCC may have needed to put the constant in a register, because
+         the target can't compare directly against that constant.  For
+         this case, we look for a SET immediately before the comparison
+         that puts a constant in that register.
+ 
+      2. GCC may have canonicalized the conditional, for example
+ 	replacing "if x < 4" with "if x <= 3".  We can undo that (or
+ 	make equivalent types of changes) to get the constants we need
+ 	if they're off by one in the right direction.  */
+ 
+   if (GET_CODE (target) == CONST_INT)
+     {
+       enum rtx_code code = GET_CODE (if_info->cond);
+       rtx op_a = XEXP (if_info->cond, 0);
+       rtx op_b = XEXP (if_info->cond, 1);
+       rtx prev_insn;
+ 
+       /* First, look to see if we put a constant in a register.  */
+       prev_insn = PREV_INSN (if_info->cond_earliest);
+       if (prev_insn
+ 	  && INSN_P (prev_insn)
+ 	  && GET_CODE (PATTERN (prev_insn)) == SET)
+ 	{
+ 	  rtx src = find_reg_equal_equiv_note (prev_insn);
+ 	  if (!src)
+ 	    src = SET_SRC (PATTERN (prev_insn));
+ 	  if (GET_CODE (src) == CONST_INT)
+ 	    {
+ 	      if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
+ 		{
+ 		  op_a = src;
+ 		  if_info->cond_earliest = prev_insn;
+ 		}
+ 	      else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
+ 		{
+ 		  op_b = src;
+ 		  if_info->cond_earliest = prev_insn;
+ 		}
+ 
+ 	      if (GET_CODE (op_a) == CONST_INT)
+ 		{
+ 		  rtx tmp = op_a;
+ 		  op_a = op_b;
+ 		  op_b = tmp;
+ 		  code = swap_condition (code);
+ 		}
+ 	    }
+ 	}
+ 
+       /* Now, look to see if we can get the right constant by
+ 	 adjusting the conditional.  */
+       if (GET_CODE (op_b) == CONST_INT)
+ 	{
+ 	  HOST_WIDE_INT desired_val = INTVAL (target);
+ 	  HOST_WIDE_INT actual_val = INTVAL (op_b);
+ 
+ 	  switch (code)
+ 	    {
+ 	    case LT:
+ 	      if (actual_val == desired_val + 1)
+ 		{
+ 		  code = LE;
+ 		  op_b = GEN_INT (desired_val);
+ 		}
+ 	      break;
+ 	    case LE:
+ 	      if (actual_val == desired_val - 1)
+ 		{
+ 		  code = LT;
+ 		  op_b = GEN_INT (desired_val);
+ 		}
+ 	      break;
+ 	    case GT:
+ 	      if (actual_val == desired_val - 1)
+ 		{
+ 		  code = GE;
+ 		  op_b = GEN_INT (desired_val);
+ 		}
+ 	      break;
+ 	    case GE:
+ 	      if (actual_val == desired_val + 1)
+ 		{
+ 		  code = GT;
+ 		  op_b = GEN_INT (desired_val);
+ 		}
+ 	      break;
+ 	    default:
+ 	      break;
+ 	    }
+ 	}
+ 
+       /* If we made any changes, generate a new conditional that is
+ 	 equivalent to what we started with, but has the right
+ 	 constants in it.  */
+       if (code != GET_CODE (if_info->cond)
+ 	  || op_a != XEXP (if_info->cond, 0)
+ 	  || op_b != XEXP (if_info->cond, 1))
+ 	{
+ 	  cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
+ 	  *earliest = if_info->cond_earliest;
+ 	  return cond;
+ 	}
+     }
  
    cond = canonicalize_condition (if_info->jump, cond, reverse,
  				 earliest, target);



More information about the Gcc-patches mailing list