This is the mail archive of the 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]

[PATCH] Minor improvement to if-conversion

The following patch is a minor tweak to GCC's if-conversion.
Whilst testing an earlier patch, I noticed that we weren't
optimizing the following function on x86.

int foo(int x, int y)
  return x < 0 ? y : 0;

but are currently generating the following (-O2 -fomit-frame-pointer)

foo:    movl    4(%esp), %edx
        testl   %edx, %edx
        movl    8(%esp), %eax
        js      .L4
        xorl    %eax, %eax
.L4:    ret

Investigating further the noce_try_sign_mask optimization is not being
triggered because the rtx_cost of "t", a read from memory, is considered
to expensive.

The problem is that GCC's if-conversion fails to distinguish between

	x = expensive;
	if (cond)
	  x = 0;


	if (cond)
	  x = 0;
	  x = expensive;

In the first case, "expensive" is originally always evaluated, so
always evaluating it in an ifcvt sequence is acceptable, but in the
second case, we don't want to introduce an "expensive" evaluation.
Clearly, in the long term, tree-ssa will implement Partial Dead
Code Elimination (PDCE), so if-conversion should never see the
first form where the expensive assignment is partially dead.
In the meantime, the patch below improves GCC's if-conversion
infrastructure to record whether insn_b is unconditionally executed
in the current code, which is then used by noce_try_sign_mask.
The other if-conversion stategies can also probably benefit from
this additional information.

With this change we now generate the much prettier:

foo:    movl    4(%esp), %eax
        sarl    $31, %eax
        andl    8(%esp), %eax

The following patch has been tested on i686-pc-linux-gnu with a
full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?

2004-07-06  Roger Sayle  <>

	* ifcvt.c (struct noce_if_info): Add a Boolean b_unconditional field.
	(noce_try_sign_mask): Tweak rtx_cost check if t is evaluated anyway.
	(noce_process_if_block): Initialize if_info.b_unconditional if insn_b
	is currently executed unconditionally, i.e. not in "else_bb".

Index: ifcvt.c
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.153
diff -c -3 -p -r1.153 ifcvt.c
*** ifcvt.c	4 Jul 2004 14:57:34 -0000	1.153
--- ifcvt.c	5 Jul 2004 21:04:51 -0000
*************** struct noce_if_info
*** 579,584 ****
--- 579,586 ----
    rtx insn_a, insn_b;
    rtx x, a, b;
    rtx jump, cond, cond_earliest;
+   /* True if "b" was originally evaluated unconditionally.  */
+   bool b_unconditional;

  static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int);
*************** noce_try_sign_mask (struct noce_if_info
*** 1730,1737 ****
    if (GET_MODE (m) != mode)
      return FALSE;

!   /* This is only profitable if T is cheap.  */
!   if (rtx_cost (t, SET) >= COSTS_N_INSNS (2))
      return FALSE;

    start_sequence ();
--- 1732,1742 ----
    if (GET_MODE (m) != mode)
      return FALSE;

!   /* This is only profitable if T is cheap, or T is unconditionally
!      executed/evaluated in the original insn sequence.  */
!   if (rtx_cost (t, SET) >= COSTS_N_INSNS (2)
!       && (!if_info->b_unconditional
!           || t != if_info->b))
      return FALSE;

    start_sequence ();
*************** noce_process_if_block (struct ce_if_bloc
*** 1983,1988 ****
--- 1988,1994 ----
    if_info.x = x;
    if_info.a = a;
    if_info.b = b;
+   if_info.b_unconditional = else_bb == 0;

    /* Try optimizations in some approximation of a useful order.  */
    /* ??? Should first look to see if X is live incoming at all.  If it

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

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