* builtins.def (BUILT_IN_LFLOOR, BUILT_IN_LFLOORF, BUILT_IN_LFLOORL)
authoruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Apr 2005 05:31:46 +0000 (05:31 +0000)
committeruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Apr 2005 05:31:46 +0000 (05:31 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97886 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/convert.c
gcc/fold-const.c
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-53.c [new file with mode: 0644]

index b2324c6..adeed7f 100644 (file)
@@ -1,3 +1,30 @@
+2005-04-09  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.
+
 2005-04-08  Ian Lance Taylor  <ian@airs.com>
 
        * c-common.def: Move FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT,
        * tree-chrec.c (chrec_convert): Return chrec_dont_know for constants
        that don't fit in their type after conversion.
 
-2005-04-05 Uros Bizjak <uros@kss-loka.si>
+2005-04-05  Uros Bizjak <uros@kss-loka.si>
 
        PR target/20421
        * config/i386/i386.md (frndintxf2_floor, frndintxf2_ceil)
index 56bdc87..034934c 100644 (file)
@@ -98,6 +98,7 @@ static void expand_errno_check (tree, rtx);
 static rtx expand_builtin_mathfn (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
+static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
 static rtx expand_builtin_args_info (tree);
 static rtx expand_builtin_next_arg (void);
 static rtx expand_builtin_va_start (tree);
@@ -161,6 +162,7 @@ static tree fold_builtin_trunc (tree, tree);
 static tree fold_builtin_floor (tree, tree);
 static tree fold_builtin_ceil (tree, tree);
 static tree fold_builtin_round (tree, tree);
+static tree fold_builtin_int_roundingfn (tree, tree);
 static tree fold_builtin_bitop (tree, tree);
 static tree fold_builtin_memcpy (tree, tree);
 static tree fold_builtin_mempcpy (tree, tree, int);
@@ -1548,7 +1550,9 @@ mathfn_built_in (tree type, enum built_in_function fn)
       CASE_MATHFN (BUILT_IN_J1)
       CASE_MATHFN (BUILT_IN_JN)
       CASE_MATHFN (BUILT_IN_LDEXP)
+      CASE_MATHFN (BUILT_IN_LFLOOR)
       CASE_MATHFN (BUILT_IN_LGAMMA)
+      CASE_MATHFN (BUILT_IN_LLFLOOR)
       CASE_MATHFN (BUILT_IN_LLRINT)
       CASE_MATHFN (BUILT_IN_LLROUND)
       CASE_MATHFN (BUILT_IN_LOG)
@@ -2112,6 +2116,100 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
   return target;
 }
 
+/* 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;
+}
+
 /* To evaluate powi(x,n), the floating point value x raised to the
    constant integer exponent n, we use a hybrid algorithm that
    combines the "window method" with look-up tables.  For an
@@ -5278,6 +5376,17 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
+    case BUILT_IN_LFLOOR:
+    case BUILT_IN_LFLOORF:
+    case BUILT_IN_LFLOORL:
+    case BUILT_IN_LLFLOOR:
+    case BUILT_IN_LLFLOORF:
+    case BUILT_IN_LLFLOORL:
+      target = expand_builtin_int_roundingfn (exp, target, subtarget);
+      if (target)
+       return target;
+      break;
+
     case BUILT_IN_POW:
     case BUILT_IN_POWF:
     case BUILT_IN_POWL:
@@ -6627,11 +6736,11 @@ fold_builtin_round (tree fndecl, tree arglist)
 }
 
 /* Fold function call to builtin lround, lroundf or lroundl (or the
-   corresponding long long versions).  Return NULL_TREE if no
-   simplification can be made.  */
+   corresponding long long versions) and other rounding functions.
+   Return NULL_TREE if no simplification can be made.  */
 
 static tree
-fold_builtin_lround (tree fndecl, tree arglist)
+fold_builtin_int_roundingfn (tree fndecl, tree arglist)
 {
   tree arg;
 
@@ -6651,7 +6760,30 @@ fold_builtin_lround (tree fndecl, tree arglist)
          HOST_WIDE_INT hi, lo;
          REAL_VALUE_TYPE r;
 
-         real_round (&r, TYPE_MODE (ftype), &x);
+         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:
+             real_floor (&r, TYPE_MODE (ftype), &x);
+             break;
+
+           case BUILT_IN_LROUND:
+           case BUILT_IN_LROUNDF:
+           case BUILT_IN_LROUNDL:
+           case BUILT_IN_LLROUND:
+           case BUILT_IN_LLROUNDF:
+           case BUILT_IN_LLROUNDL:
+             real_round (&r, TYPE_MODE (ftype), &x);
+             break;
+
+           default:
+             gcc_unreachable ();
+           }
+
          REAL_VALUE_TO_INT (&lo, &hi, r);
          result = build_int_cst_wide (NULL_TREE, lo, hi);
          if (int_fits_type_p (result, itype))
@@ -8196,13 +8328,19 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
     case BUILT_IN_RINTL:
       return fold_trunc_transparent_mathfn (fndecl, arglist);
 
+    case BUILT_IN_LFLOOR:
+    case BUILT_IN_LFLOORF:
+    case BUILT_IN_LFLOORL:
+    case BUILT_IN_LLFLOOR:
+    case BUILT_IN_LLFLOORF:
+    case BUILT_IN_LLFLOORL:
     case BUILT_IN_LROUND:
     case BUILT_IN_LROUNDF:
     case BUILT_IN_LROUNDL:
     case BUILT_IN_LLROUND:
     case BUILT_IN_LLROUNDF:
     case BUILT_IN_LLROUNDL:
-      return fold_builtin_lround (fndecl, arglist);
+      return fold_builtin_int_roundingfn (fndecl, arglist);
 
     case BUILT_IN_LRINT:
     case BUILT_IN_LRINTF:
index c7cfb08..36a644c 100644 (file)
@@ -260,9 +260,15 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_JNL, "jnl", BT_FN_LONGDOUBLE_INT_LONGDOUBLE, AT
 DEF_LIB_BUILTIN        (BUILT_IN_LDEXP, "ldexp", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPF, "ldexpf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPL, "ldexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_LFLOOR, "lfloor", BT_FN_LONG_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN        (BUILT_IN_LFLOORF, "lfloorf", BT_FN_LONG_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN        (BUILT_IN_LFLOORL, "lfloorl", BT_FN_LONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_LGAMMA, "lgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_LGAMMAF, "lgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_LGAMMAL, "lgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_LLFLOOR, "llfloor", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN        (BUILT_IN_LLFLOORF, "llfloorf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN        (BUILT_IN_LLFLOORL, "llfloorl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_LLRINT, "llrint", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_LLRINTF, "llrintf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_LLRINTL, "llrintl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
index f900ace..79aef21 100644 (file)
@@ -349,6 +349,13 @@ convert_to_integer (tree type, tree expr)
       
       switch (fcode)
         {
+       case BUILT_IN_FLOOR: case BUILT_IN_FLOORF: case BUILT_IN_FLOORL:
+         if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
+           fn = mathfn_built_in (s_intype, BUILT_IN_LLFLOOR);
+         else
+           fn = mathfn_built_in (s_intype, BUILT_IN_LFLOOR);
+         break;
+
        case BUILT_IN_ROUND: case BUILT_IN_ROUNDF: case BUILT_IN_ROUNDL:
          if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
            fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND);
index 6a84630..4d7ee93 100644 (file)
@@ -10619,6 +10619,8 @@ tree_expr_nonnegative_p (tree t)
            CASE_BUILTIN_F (BUILT_IN_FLOOR)
            CASE_BUILTIN_F (BUILT_IN_FMOD)
            CASE_BUILTIN_F (BUILT_IN_LDEXP)
+           CASE_BUILTIN_F (BUILT_IN_LFLOOR)
+           CASE_BUILTIN_F (BUILT_IN_LLFLOOR)
            CASE_BUILTIN_F (BUILT_IN_LLRINT)
            CASE_BUILTIN_F (BUILT_IN_LLROUND)
            CASE_BUILTIN_F (BUILT_IN_LRINT)
index 92b1c20..42a525f 100644 (file)
@@ -119,6 +119,7 @@ static const char * const optabs[] =
   "copysign_optab->handlers[$A].insn_code = CODE_FOR_$(copysign$F$a3$)",
   "sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)",
   "floor_optab->handlers[$A].insn_code = CODE_FOR_$(floor$a2$)",
+  "lfloor_optab->handlers[$A].insn_code = CODE_FOR_$(lfloor$a2$)",
   "ceil_optab->handlers[$A].insn_code = CODE_FOR_$(ceil$a2$)",
   "round_optab->handlers[$A].insn_code = CODE_FOR_$(round$a2$)",
   "btrunc_optab->handlers[$A].insn_code = CODE_FOR_$(btrunc$a2$)",
index ecaff98..d672744 100644 (file)
@@ -5033,6 +5033,7 @@ init_optabs (void)
   parity_optab = init_optab (PARITY);
   sqrt_optab = init_optab (SQRT);
   floor_optab = init_optab (UNKNOWN);
+  lfloor_optab = init_optab (UNKNOWN);
   ceil_optab = init_optab (UNKNOWN);
   round_optab = init_optab (UNKNOWN);
   btrunc_optab = init_optab (UNKNOWN);
index 53958fc..a1c2d37 100644 (file)
@@ -186,6 +186,7 @@ enum optab_index
   OTI_log1p,
   /* Rounding functions */
   OTI_floor,
+  OTI_lfloor,
   OTI_ceil,
   OTI_btrunc,
   OTI_round,
@@ -313,6 +314,7 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define log2_optab (optab_table[OTI_log2])
 #define log1p_optab (optab_table[OTI_log1p])
 #define floor_optab (optab_table[OTI_floor])
+#define lfloor_optab (optab_table[OTI_lfloor])
 #define ceil_optab (optab_table[OTI_ceil])
 #define btrunc_optab (optab_table[OTI_btrunc])
 #define round_optab (optab_table[OTI_round])
index f6f8cef..14258a1 100644 (file)
@@ -1,3 +1,7 @@
+2005-04-09  Uros Bizjak  <uros@kss-loka.si>
+
+       * gcc.dg/builtins-53.c: New test.
+
 2005-04-08  Diego Novillo  <dnovillo@redhat.com>
 
        * g++.dg/tree-ssa/pr18178.C: New test.
diff --git a/gcc/testsuite/gcc.dg/builtins-53.c b/gcc/testsuite/gcc.dg/builtins-53.c
new file mode 100644 (file)
index 0000000..6b1a6f8
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (C) 2005 Free Software Foundation.
+
+   Check that (long)floor, (long)floorf, (long)floorl,
+   (long long)floor, (long long)floorf and (long long)floorl
+   built-in functions compile.
+
+   Written by Uros Bizjak, 5th April 2005.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern double floor(double);
+extern float floorf(float);
+extern long double floorl(long double);
+
+
+long int test1(double x)
+{
+  return floor(x);
+}
+
+long long int test2(double x)
+{
+  return floor(x);
+}
+
+long int test1f(float x)
+{
+  return floorf(x);
+}
+
+long long int test2f(float x)
+{
+  return floorf(x);
+}
+
+long int test1l(long double x)
+{
+  return floorl(x);
+}
+
+long long int test2l(long double x)
+{
+  return floorl(x);
+}