minor code-quality regression vs. 2.95

Zack Weinberg zack@wolery.cumb.org
Thu Apr 13 23:29:00 GMT 2000


On Thu, Apr 13, 2000 at 04:16:47PM -0500, Clinton Popetz wrote:
> On Wed, Apr 12, 2000 at 03:08:38PM -0700, Zack Weinberg wrote:
>  
> > I also can't figure out how we get from 'val / 512' to ix86_expand_branch.
> > There's no divdi pattern, and the ashrdi patterns don't generate the
> > branch and addition.  It must be hiding somewhere in the machine
> > independent code, but I don't know where.
> 
> expand_divmod does this when branches are cheap.  

Hmm... expand_divmod calls do_cmp_and_jump, which looks like it would
be the appropriate place to teach GCC that DImode < 0 or >= 0 can be
done by looking only at the high word.  But when I do that (see patch
below), it doesn't help, because i386 has a cmpdi pattern.  This
seems silly to me... why not let the generic code synthesize it?

With the patch below _and_ cmpdi commented out of i386.md, I get the
same assembly as 2.95 produced.  (The patch is overly long due to
indentation changes.)

zw

===================================================================
Index: expmed.c
--- expmed.c	2000/04/10 11:51:53	1.57
+++ expmed.c	2000/04/14 06:24:47
@@ -4563,58 +4563,84 @@ do_cmp_and_jump (arg1, arg2, op, mode, l
      enum rtx_code op;
      enum machine_mode mode;
 {
-  /* If this mode is an integer too wide to compare properly,
-     compare word by word.  Rely on cse to optimize constant cases.  */
+  rtx label2, word0;
 
-  if (GET_MODE_CLASS (mode) == MODE_INT
-      && ! can_compare_p (op, mode, ccp_jump))
+  if (GET_MODE_CLASS (mode) != MODE_INT
+      || can_compare_p (op, mode, ccp_jump))
     {
-      rtx label2 = gen_label_rtx ();
-
+      emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, 0, label);
+      return;
+    }
+    
+  /* Special case some word-by-word compares against zero.  */
+  if (arg2 == const0_rtx)
+    {
       switch (op)
 	{
-	case LTU:
-	  do_jump_by_parts_greater_rtx (mode, 1, arg2, arg1, label2, label);
-	  break;
-
-	case LEU:
-	  do_jump_by_parts_greater_rtx (mode, 1, arg1, arg2, label, label2);
-	  break;
-
-	case LT:
-	  do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label2, label);
-	  break;
-
-	case GT:
-	  do_jump_by_parts_greater_rtx (mode, 0, arg1, arg2, label2, label);
-	  break;
+	case LTU:  return;			/* always false */
+	case GEU:  emit_jump (label); return;	/* always true */
+	case LEU:  op = EQ;  break;		/* equivalent */
+	case GTU:  op = NE;  break;
 
+	case LT:	/* a < 0 or a >= 0 depend only on the high word.  */
 	case GE:
-	  do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label, label2);
-	  break;
+	  if (WORDS_BIG_ENDIAN)
+	    word0 = operand_subword_force (arg1, 0, mode);
+	  else
+	    word0 = operand_subword_force (arg1, (GET_MODE_SIZE (mode)
+						  / UNITS_PER_WORD) - 1, mode);
+		
+	  emit_cmp_and_jump_insns (word0, arg2, op, NULL_RTX,
+				   word_mode, 0, 0, label);
+	  return;
 
-	  /* do_jump_by_parts_equality_rtx compares with zero.  Luckily
-	     that's the only equality operations we do */
-	case EQ:
-	  if (arg2 != const0_rtx || mode != GET_MODE(arg1))
-	    abort();
-	  do_jump_by_parts_equality_rtx (arg1, label2, label);
-	  break;
-
-	case NE:
-	  if (arg2 != const0_rtx || mode != GET_MODE(arg1))
-	    abort();
-	  do_jump_by_parts_equality_rtx (arg1, label, label2);
-	  break;
-
-	default:
-	  abort();
+	default: break;
 	}
-
-      emit_label (label2);
     }
-  else
+
+  /* If this mode is an integer too wide to compare properly,
+     compare word by word.  Rely on cse to optimize constant cases.  */
+
+  label2  = gen_label_rtx ();
+  switch (op)
     {
-      emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, 0, label);
+    case LTU:
+      do_jump_by_parts_greater_rtx (mode, 1, arg2, arg1, label2, label);
+      break;
+
+    case LEU:
+      do_jump_by_parts_greater_rtx (mode, 1, arg1, arg2, label, label2);
+      break;
+
+    case LT:
+      do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label2, label);
+      break;
+
+    case GT:
+      do_jump_by_parts_greater_rtx (mode, 0, arg1, arg2, label2, label);
+      break;
+
+    case GE:
+      do_jump_by_parts_greater_rtx (mode, 0, arg2, arg1, label, label2);
+      break;
+
+      /* do_jump_by_parts_equality_rtx compares with zero.  Luckily
+	 that's the only equality operations we do */
+    case EQ:
+      if (arg2 != const0_rtx || mode != GET_MODE(arg1))
+	abort();
+      do_jump_by_parts_equality_rtx (arg1, label2, label);
+      break;
+
+    case NE:
+      if (arg2 != const0_rtx || mode != GET_MODE(arg1))
+	abort();
+      do_jump_by_parts_equality_rtx (arg1, label, label2);
+      break;
+
+    default:
+      abort();
     }
+
+  emit_label (label2);
 }


More information about the Gcc mailing list