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]

Re: [PATCH, midlevel]: Convert (int)floor -> lfloor, take 2


Roger,

attached to this message, please find the expand_builtin_int_roundingfn.c function that implements all your suggestions. Additionally, a trivial ATTR_MATHFN_FPROUNDING change to builtins.def was implemented, but not included in this message.

BTW: I would suggest a name {expand,fold}_builtin_int_roundingfn () for this function, mainly because fold_builtin_roundingfn () could be introduced instead of 4 separate fold_builtin_{trunc, floor, ceil, round} () functions. ChangeLog was updated to reflect this change.

Then finally, I don't really like the way you've implemented the
fallback path, by attempting to "goto fallback:" at the top of
the function, and then having to check/differentiate the fallback
case using "if (builtin_optab != fallback_optab)".

Instead, I think it would be better to avoid the uses of goto,
and instead recursively invoke "expand_expr" or "expand_builtin_mathfn"
to perform the lowering for you. Currently you're tieing your routine
in knots jumping backwards and forwards in an attempt to do everything
directly.


This is an example how the forest can't be seen because all of the trees. :) Appropriate function that can handle BUILT_IN_FLOOR is just a couple of screens higher.

Becomes something like:

+      fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
+      exp = build_function_call_expr (fallback_fndecl, arglist);
+      target = expand_builtin (exp, NULL_RTX, NULL_RTX, mode, false);
+      expand_fix (tmp, target, 0);



Instead of expand_builtin(), an expand_builtin_mathfn () could be used directly in new expand_builtin_int_roundingfn (), as you suggested above.

Attached expand_builtin_roundingfn () was bootstrapped/regtested on i686-pc-linux-gnu for c and c++ as part of my earlier patch. Middle-end patch was bootstrapped/regtested with and without i386 backend patch. Additionally, a povray-3.50c was built using '-O2 -march=pentium -ffast-math D__NO_MATH_INLINES' and the results were checked for correctness. In other words, when backend patch is plugged in, this optimization works well and finds all 39 optimization opportunities in povray (in fact even a couple more).

Follwing this infrastructure change, a (int) ceil (float(x)) implementation could be just copy-n-paste stuff. I think that (int) trunc (float(x)) patch will be a bit different, it should convert BUILT_IN_TRUNC directly into FIX_TRUNC_EXPR.

2005-04-08 Uros Bizjak <uros@kss-loka.si>

   * builtins.def (BUILT_IN_LFLOOR, BUILT_IN_LFLOORF, BUILT_IN_LFLOORL)
   (BUILT_IN_LLFLOOR, BUILT_IN_LLFLOORF, BUILT_IN_LLFLOORL): New.
   * optabs.h (enum optab_index): Add new OTI_lfloor.
   (lfloor_optab): Define corresponding macro.
   * optabs.c (init_optabs): Initialize lfloor_optab.
   * genopinit.c (optabs): Implement lfloor_optab using lfloorsi2
   and lfloordi2 patterns.

   * builtins.c (expand_builtin_int_roundingfn): New prototype.
   (expand_builtin_int_roundingfn): New function.
   (fold_builtin_int_roundingfn): New prototype.
   (fold_builtin_int_roundingfn): New function, renamed from
   fold_builtin_lround.
   Handle BUILT_IN_LROUND{,F,L}, BUILT_IN_LLROUND{,F,L} and
   BUILT_IN_LFLOOR{,F,L}, BUILT_IN_LLFLOOR{,F,L}.
   (fold_builtin_1): Fold BUILT_IN_LFLOOR{,F,L} and
   BUILT_IN_LLFLOOR{,F,L} using fold_builtin_int_roundingfn.
   (mathfn_built_in): Handle BUILT_IN LFLOOR and BUILT_IN_LLFLOOR.
   (expand_builtin): Expand BUILT_IN_LFLOOR{,F,L} and
   BUILT_IN_LLFLOOR{,F,L} using expand_builtin_int_roundingfn.

   * convert.c (convert_to_integer): Convert (long int)floor{,f,l},
   into lfloor built-in function and (long long int)floor{,f,l} into
   llfloor built-in-function.
   * fold-const.c (tree_expr_nonnegative_p): Add BUILT_IN_LFLOOR and
   BUILT_IN_LLFLOOR.

testsuite:

* gcc.dg/builtins-53.c: New test.

Many thanks for your patience.


Thank you for your instructions and explanation!

Uros.
/* Expand a call to one of the builtin rounding functions (lfloor).
   If expanding via optab fails, lower expression to (int)(floor(x)).
   EXP is the expression that is a call to the builtin function;
   if convenient, the result should be placed in TARGET.  SUBTARGET may
   be used as the target for computing one of EXP's operands.  */

static rtx
expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
{
  optab builtin_optab;
  rtx op0, insns, tmp;
  tree fndecl = get_callee_fndecl (exp);
  tree arglist = TREE_OPERAND (exp, 1);
  enum built_in_function fallback_fn;
  tree fallback_fndecl;
  enum machine_mode mode;
  tree arg, narg;

  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
    gcc_unreachable ();

  arg = TREE_VALUE (arglist);

  switch (DECL_FUNCTION_CODE (fndecl))
    {
    case BUILT_IN_LFLOOR:
    case BUILT_IN_LFLOORF:
    case BUILT_IN_LFLOORL:
    case BUILT_IN_LLFLOOR:
    case BUILT_IN_LLFLOORF:
    case BUILT_IN_LLFLOORL:
      builtin_optab = lfloor_optab;
      fallback_fn = BUILT_IN_FLOOR;
      break;

    default:
      gcc_unreachable ();
    }

  /* Make a suitable register to place result in.  */
  mode = TYPE_MODE (TREE_TYPE (exp));

  /* Before working hard, check whether the instruction is available.  */
  if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
    {
      target = gen_reg_rtx (mode);

      /* Wrap the computation of the argument in a SAVE_EXPR, as we may
	 need to expand the argument again.  This way, we will not perform
	 side-effects more the once.  */
      narg = builtin_save_expr (arg);
      if (narg != arg)
	{
	  arg = narg;
	  arglist = build_tree_list (NULL_TREE, arg);
	  exp = build_function_call_expr (fndecl, arglist);
	}

      op0 = expand_expr (arg, subtarget, VOIDmode, 0);

      start_sequence ();

      /* Compute into TARGET.
	 Set TARGET to wherever the result comes back.  */
      target = expand_unop (mode, builtin_optab, op0, target, 0);

      if (target != 0)
	{
	  /* Output the entire sequence.  */
	  insns = get_insns ();
	  end_sequence ();
	  emit_insn (insns);
	  return target;
	}

      /* If we were unable to expand via the builtin, stop the sequence
	 (without outputting the insns).  */
      end_sequence ();
    }

  /* Fall back to floating point rounding optab.  */
  fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
  exp = build_function_call_expr (fallback_fndecl, arglist);

  tmp = expand_builtin_mathfn (exp, NULL_RTX, NULL_RTX);

  /* Truncate the result of floating point optab to integer
     via expand_fix ().  */
  target = gen_reg_rtx (mode);
  expand_fix (target, tmp, 0);

  return target;
}

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