This is the mail archive of the gcc-patches@gcc.gnu.org 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] REG_EQUAL notes on floatlib comparison libcalls


Zack's recent clean-up of optab.c's prepare_float_lib_cmp reminded
me of an optimization I've been meaning to add there for a while.
For soft-float targets, we're currently unable to optimize floating
point comparisons once the function has been lowered to RTL.  The
problem is that such comparisons appear as anonymous libcall functions
to the RTL optimizers, so even if both operands can be determined to be
compile-time constants, GCC is still unable to optimize the comparison
away.

The solution is to annotate these libcalls with their semantics using
REG_EQUAL notes, much like we now do with SQRT libcalls.  By placing
a suitable REG_EQUAL on the REG_RETVAL instruction of the libcall
sequence, we can describe the floatlib function's return value.  This
is sufficient so that should the RTL optimizers propagate constant
operands into the REG_EQUAL note, the note may be simplified to a
constant value, and thereby eliminate the libcall.

Because the semantics/return values of the floatlib comparison functions
don't exactly correspond to their RTL operator equivalents, the code
below generates if_then_else expressions that reproduce suitable return
values when the FLOAT_LIB_COMPARE_RETURNS_BOOL target macro is false.


With this patch the following function is optimized on i686-pc-linux-gnu
when compiled with the options "-O2 -msoft-float".

int foo()
{
  double x = 2.0;
  double y = 3.0;
  return x < y;
}


Previously, the generated code would contain a call to __ltdf2.

Much to my shock, after I'd written this patch, I discovered that
using hardware floating point and compiling with just "-O2" fails
to optimize away the comparison!  Another one for my list :>


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

Ok for mainline?


2003-10-05  Roger Sayle  <roger@eyesopen.com>

	* optabs.c (prepare_float_lib_cmp):  Attach a REG_EQUAL note
	describing the return value of the comparison libcall to the
	REG_RETVAL instruction of the emitted sequence.


Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.190
diff -c -3 -p -r1.190 optabs.c
*** optabs.c	4 Oct 2003 21:36:01 -0000	1.190
--- optabs.c	5 Oct 2003 23:44:19 -0000
*************** prepare_float_lib_cmp (rtx *px, rtx *py,
*** 3877,3882 ****
--- 3877,3883 ----
    rtx y = protect_from_queue (*py, 0);
    enum machine_mode orig_mode = GET_MODE (x);
    enum machine_mode mode;
+   rtx before_call;
    rtx libfunc = 0;
    rtx result;

*************** prepare_float_lib_cmp (rtx *px, rtx *py,
*** 3903,3914 ****
        y = convert_to_mode (mode, y, 0);
      }

    if (comparison == UNORDERED
        || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
      comparison = NE;

-   result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
- 				    word_mode, 2, x, mode, y, mode);
    *px = result;
    *py = const0_rtx;
    *pmode = word_mode;
--- 3904,4000 ----
        y = convert_to_mode (mode, y, 0);
      }

+   before_call = get_last_insn ();
+
+   result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
+ 				    word_mode, 2, x, mode, y, mode);
+
+   /* If we're optimizing attach a REG_EQUAL note describing the semantics
+      of the libcall to the RTL.  The allows the RTL optimizers to delete
+      the libcall if the condition can be determined at compile-time.  */
+   if (optimize
+       && ! side_effects_p (x)
+       && ! side_effects_p (y))
+     {
+       /* Search backwards through the insns emitted above looking for
+ 	 the instruction with the REG_RETVAL note.  */
+       rtx last = get_last_insn ();
+       while (last != before_call)
+ 	{
+ 	  if (find_reg_note (last, REG_RETVAL, NULL))
+ 	    break;
+ 	  last = PREV_INSN (last);
+ 	}
+
+       if (last != before_call)
+ 	{
+ 	  rtx equiv;
+ 	  if (comparison == UNORDERED)
+ 	    {
+ 	      rtx temp = simplify_gen_relational (NE, word_mode,
+ 						  mode, x, x);
+ 	      equiv = simplify_gen_relational (NE, word_mode,
+ 					       mode, x, x);
+ 	      equiv = simplify_gen_ternary (IF_THEN_ELSE, word_mode,
+ 					    word_mode, temp,
+ 					    const_true_rtx, equiv);
+ 	    }
+ 	  else
+ 	    {
+ 	      equiv = simplify_gen_relational (comparison, word_mode,
+ 					       mode, x, y);
+ 	      if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
+ 		{
+ 		  rtx true_rtx, false_rtx;
+
+ 		  switch (comparison)
+ 		    {
+ 		    case EQ:
+ 		      true_rtx = const0_rtx;
+ 		      false_rtx = const_true_rtx;
+ 		      break;
+
+ 		    case NE:
+ 		      true_rtx = const_true_rtx;
+ 		      false_rtx = const0_rtx;
+ 		      break;
+
+ 		    case GT:
+ 		      true_rtx = const1_rtx;
+ 		      false_rtx = const0_rtx;
+ 		      break;
+
+ 		    case GE:
+ 		      true_rtx = const0_rtx;
+ 		      false_rtx = constm1_rtx;
+ 		      break;
+
+ 		    case LT:
+ 		      true_rtx = constm1_rtx;
+ 		      false_rtx = const0_rtx;
+ 		      break;
+
+ 		    case LE:
+ 		      true_rtx = const0_rtx;
+ 		      false_rtx = const1_rtx;
+ 		      break;
+
+ 		    default:
+ 		      abort ();
+ 		    }
+ 		  equiv = simplify_gen_ternary (IF_THEN_ELSE, word_mode,
+ 						word_mode, equiv,
+ 						true_rtx, false_rtx);
+ 		}
+ 	    }
+ 	  set_unique_reg_note (last, REG_EQUAL, equiv);
+ 	}
+     }
+
    if (comparison == UNORDERED
        || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
      comparison = NE;

    *px = result;
    *py = const0_rtx;
    *pmode = word_mode;


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


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