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