OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
index b937d3d..e8fef17 100644 (file)
@@ -2841,10 +2841,7 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target)
   tree fndecl = get_callee_fndecl (exp);
   tree arg;
   enum machine_mode mode;
-
-  /* There's no easy way to detect the case we need to set EDOM.  */
-  if (flag_errno_math)
-    return NULL_RTX;
+  enum built_in_function fallback_fn = BUILT_IN_NONE;
 
   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
      gcc_unreachable ();
@@ -2854,46 +2851,78 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target)
   switch (DECL_FUNCTION_CODE (fndecl))
     {
     CASE_FLT_FN (BUILT_IN_IRINT):
+      fallback_fn = BUILT_IN_LRINT;
+      /* FALLTHRU */
     CASE_FLT_FN (BUILT_IN_LRINT):
     CASE_FLT_FN (BUILT_IN_LLRINT):
-      builtin_optab = lrint_optab; break;
+      builtin_optab = lrint_optab;
+      break;
 
     CASE_FLT_FN (BUILT_IN_IROUND):
+      fallback_fn = BUILT_IN_LROUND;
+      /* FALLTHRU */
     CASE_FLT_FN (BUILT_IN_LROUND):
     CASE_FLT_FN (BUILT_IN_LLROUND):
-      builtin_optab = lround_optab; break;
+      builtin_optab = lround_optab;
+      break;
 
     default:
       gcc_unreachable ();
     }
 
+  /* There's no easy way to detect the case we need to set EDOM.  */
+  if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
+    return NULL_RTX;
+
   /* Make a suitable register to place result in.  */
   mode = TYPE_MODE (TREE_TYPE (exp));
 
-  target = gen_reg_rtx (mode);
+  /* There's no easy way to detect the case we need to set EDOM.  */
+  if (!flag_errno_math)
+    {
+      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.  */
-  CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
+      /* 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.  */
+      CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
 
-  op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
+      op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
 
-  start_sequence ();
+      start_sequence ();
 
-  if (expand_sfix_optab (target, op0, builtin_optab))
-    {
-      /* Output the entire sequence.  */
-      insns = get_insns ();
+      if (expand_sfix_optab (target, op0, builtin_optab))
+       {
+         /* 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) and call to the library function
+        with the stabilized argument list.  */
       end_sequence ();
-      emit_insn (insns);
-      return target;
     }
 
-  /* If we were unable to expand via the builtin, stop the sequence
-     (without outputting the insns) and call to the library function
-     with the stabilized argument list.  */
-  end_sequence ();
+  if (fallback_fn != BUILT_IN_NONE)
+    {
+      /* Fall back to rounding to long int.  Use implicit_p 0 - for non-C99
+        targets, (int) round (x) should never be transformed into
+        BUILT_IN_IROUND and if __builtin_iround is called directly, emit
+        a call to lround in the hope that the target provides at least some
+        C99 functions.  This should result in the best user experience for
+        not full C99 targets.  */
+      tree fallback_fndecl = mathfn_built_in_1 (TREE_TYPE (arg),
+                                               fallback_fn, 0);
+
+      exp = build_call_nofold_loc (EXPR_LOCATION (exp),
+                                  fallback_fndecl, 1, arg);
+
+      target = expand_call (exp, NULL_RTX, target == const0_rtx);
+      return convert_to_mode (mode, target, 0);
+    }
 
   target = expand_call (exp, target, target == const0_rtx);
 
@@ -4692,7 +4721,14 @@ expand_builtin_trap (void)
 {
 #ifdef HAVE_trap
   if (HAVE_trap)
-    emit_insn (gen_trap ());
+    {
+      rtx insn = emit_insn (gen_trap ());
+      /* For trap insns when not accumulating outgoing args force
+        REG_ARGS_SIZE note to prevent crossjumping of calls with
+        different args sizes.  */
+      if (!ACCUMULATE_OUTGOING_ARGS)
+       add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
+    }
   else
 #endif
     emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
@@ -9656,7 +9692,16 @@ fold_builtin_logb (location_t loc, tree arg, tree rettype)
       case rvc_inf:
        /* If arg is Inf or NaN and we're logb, return it.  */
        if (TREE_CODE (rettype) == REAL_TYPE)
-         return fold_convert_loc (loc, rettype, arg);
+         {
+           /* For logb(-Inf) we have to return +Inf.  */
+           if (real_isinf (value) && real_isneg (value))
+             {
+               REAL_VALUE_TYPE tem;
+               real_inf (&tem);
+               return build_real (rettype, tem);
+             }
+           return fold_convert_loc (loc, rettype, arg);
+         }
        /* Fall through... */
       case rvc_zero:
        /* Zero may set errno and/or raise an exception for logb, also
@@ -11898,7 +11943,7 @@ fold_builtin_strspn (location_t loc, tree s1, tree s2)
       if (p1 && p2)
        {
          const size_t r = strspn (p1, p2);
-         return size_int (r);
+         return build_int_cst (size_type_node, r);
        }
 
       /* If either argument is "", return NULL_TREE.  */
@@ -11943,7 +11988,7 @@ fold_builtin_strcspn (location_t loc, tree s1, tree s2)
       if (p1 && p2)
        {
          const size_t r = strcspn (p1, p2);
-         return size_int (r);
+         return build_int_cst (size_type_node, r);
        }
 
       /* If the first argument is "", return NULL_TREE.  */