[PATCH] Avoid generating always-taken conditional branches.

Roger Sayle roger@eyesopen.com
Sat Jun 15 06:51:00 GMT 2002


The following patch to expr.c avoids generating RTL for conditional
branches that are always taken or always not taken.  The calls to
simplify_relational_operation in expr.c are guarded by tests that
both operands of the comparison are integer constants, but
simplify_relational_operation can simplify many more cases including
things such as "(ltu x 0)" and "(gteu x 0)" which must always be
constant due to the unsigned nature of the comparison.  The patch
below simply removes the checks for CONST_INT and always calls
simplify_relational_operation.  I also needed to check "unsignedp"
to pass the correct comparison condition.


Now for the long story :>  My recent patch to simplify the logic
in toplev.c introduced some new testsuite regressions on mips-elf.
Thanks to the analysis by Jeff Law, it turns out that that patch
results in calling cleanup_cfg even in non-optimizing compilation.
This in turn is inverting the sense of an always-not-taken conditional
branch to an always-taken conditional branch, which survives the
entire GCC back-end and produces a warning in GAS for mips-elf.

The reason this doesn't cause problems on i686 or powerpc is that
the backend patterns for conditional branches in many backends are
clever enough to recognize that they've been asked to emit an
unconditional branch.  Rather than force this as a requirement in
all backend,s my view is that such RTL needn't/shouldn't be output
by the middle-end, performing the checks once in common code.

As a specific example, consider gcc.c-torture/compile/20020106-1.c:

int foo ()
{
  extern long long Y;
  return (0 > Y++);
}

The comparison "Y < 0" is generated by do_jump_by_parts_greater.
Representing Y as signed high-part hy, and unsigned low-part ly,
this output as "(hy < 0) || ((hy == 0) && (ly < 0))".  This is
the correct form for performing comparisons by parts, but notice
(ly < 0) where ly is unsigned, this is always false, and the
entire comparison reduces to "hy < 0".

It turns out that do_jump_by_parts actually emits its comparisons
via do_compare_rtx_and_jump, and, as described above, fixing the
simplify_relational_operation call there, avoids these instructions
appearing in the RTL.  I also fixed compare_from_rtx purely because
it contained identical code.


This patch has been tested with "make bootstrap" and "make -k check"
on i686-pc-linux-gnu, all languages except Ada and treelang, with no
new regressions.  I've also tested it on the mips-elf simulator
where if fixes about 14 testsuite failures (including all 9 regressions
that I introduced by calling cleanup_cfg).

Thanks again to Jeff.

Ok for mainline?



2002-06-15  Roger Sayle  <roger@eyesopen.com>

	* expr.c (compare_from_rtx): Call simplify_relational_operation
	on all comparisons, not just those between integer constants,
	with the correct (possibly unsigned) comparison code.
	(do_compare_rtx_and_jump): Likewise.


Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.465
diff -c -3 -p -r1.465 expr.c
*** expr.c	11 Jun 2002 12:21:29 -0000	1.465
--- expr.c	15 Jun 2002 04:58:23 -0000
*************** compare_from_rtx (op0, op1, code, unsign
*** 10045,10050 ****
--- 10045,10051 ----
       enum machine_mode mode;
       rtx size;
  {
+   enum rtx_code ucode;
    rtx tem;

    /* If one operand is constant, make it the second one.  Only do this
*************** compare_from_rtx (op0, op1, code, unsign
*** 10066,10073 ****

    do_pending_stack_adjust ();

!   if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT
!       && (tem = simplify_relational_operation (code, mode, op0, op1)) != 0)
      return tem;

  #if 0
--- 10067,10074 ----

    do_pending_stack_adjust ();

!   ucode = unsignedp ? unsigned_condition (code) : code;
!   if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
      return tem;

  #if 0
*************** do_compare_rtx_and_jump (op0, op1, code,
*** 10117,10122 ****
--- 10118,10124 ----
       rtx size;
       rtx if_false_label, if_true_label;
  {
+   enum rtx_code ucode;
    rtx tem;
    int dummy_true_label = 0;

*************** do_compare_rtx_and_jump (op0, op1, code,
*** 10148,10155 ****

    do_pending_stack_adjust ();

!   if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT
!       && (tem = simplify_relational_operation (code, mode, op0, op1)) != 0)
      {
        if (tem == const_true_rtx)
  	{
--- 10150,10157 ----

    do_pending_stack_adjust ();

!   ucode = unsignedp ? unsigned_condition (code) : code;
!   if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
      {
        if (tem == const_true_rtx)
  	{

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833



More information about the Gcc-patches mailing list