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, i386]: Implement ldexp{,f,l} functions as built-in x87 intrinsics


Hello!

This patch implements ldexp{,f,l} as built-in x87 intrinsics. Patch is bootstrapped on pentium4-pc-linux-gnu, regtested for c and c++. A testsuite change is also included that checks these functions.

These x87 intrinsics are guarded with flag_unsafe_math_optimizations.

BTW: It looks that scalbn{,f,l} functions are the same as ldexp{,f,l}. Could these builtins be implemented with the same patterns as corresponding ldexp{,f,l} patterns?

BTW2: I think that the only remaining builtins missing from mathinline.h are now fma() and hypot(). In follow-up patch, I plan to implement these, and after that, gcc could define __NO_MATH_INLINES without any problems.

2005-02-11 Uros Bizjak <uros@kss-loka.si>

   * optabs.h (enum optab_index): Add new OTI_ldexp.
   (ldexp_optab): Define corresponding macro.
   * optabs.c (init_optabs): Initialize ldexp_optab.
   * genopinit.c (optabs): Implement ldexp_optab using ldexp?f3
   patterns.
   * builtins.c (expand_builtin_mathfn_2): Handle BUILT_IN_LDEXP{,F,L}
   using ldexp_optab.
   (expand_builtin): Expand BUILT_IN_LDEXP{,F,L} using
   expand_builtin_mathfn_2 if flag_unsafe_math_optimizations is set.

   * config/i386/i386.md (ldexpsf3, ldexpdf3, ldexpxf3): New expanders
   to implement ldexpf, ldexp and ldexpl built-ins as inline x87
   intrinsics.

testsuite:

* gcc.dg/builtins-34.c: Also check ldexp*.

Uros.
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.420
diff -u -p -r1.420 builtins.c
--- builtins.c	10 Feb 2005 15:16:43 -0000	1.420
+++ builtins.c	11 Feb 2005 15:44:51 -0000
@@ -1862,6 +1862,7 @@ expand_builtin_mathfn_2 (tree exp, rtx t
 {
   optab builtin_optab;
   rtx op0, op1, insns;
+  int op1_type = REAL_TYPE;
   tree fndecl = get_callee_fndecl (exp);
   tree arglist = TREE_OPERAND (exp, 1);
   tree arg0, arg1, temp, narg;
@@ -1869,7 +1870,12 @@ expand_builtin_mathfn_2 (tree exp, rtx t
   bool errno_set = true;
   bool stable = true;
 
-  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+  if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP)
+      || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF)
+      || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
+    op1_type = INTEGER_TYPE;
+
+  if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
     return 0;
 
   arg0 = TREE_VALUE (arglist);
@@ -1885,6 +1891,10 @@ expand_builtin_mathfn_2 (tree exp, rtx t
     case BUILT_IN_ATAN2F:
     case BUILT_IN_ATAN2L:
       builtin_optab = atan2_optab; break;
+    case BUILT_IN_LDEXP:
+    case BUILT_IN_LDEXPF:
+    case BUILT_IN_LDEXPL:
+      builtin_optab = ldexp_optab; break;
     case BUILT_IN_FMOD:
     case BUILT_IN_FMODF:
     case BUILT_IN_FMODL:
@@ -5259,6 +5269,9 @@ expand_builtin (tree exp, rtx target, rt
     case BUILT_IN_ATAN2:
     case BUILT_IN_ATAN2F:
     case BUILT_IN_ATAN2L:
+    case BUILT_IN_LDEXP:
+    case BUILT_IN_LDEXPF:
+    case BUILT_IN_LDEXPL:
     case BUILT_IN_FMOD:
     case BUILT_IN_FMODF:
     case BUILT_IN_FMODL:
Index: genopinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genopinit.c,v
retrieving revision 1.86
diff -u -p -r1.86 genopinit.c
--- genopinit.c	28 Jan 2005 00:54:58 -0000	1.86
+++ genopinit.c	11 Feb 2005 15:44:52 -0000
@@ -133,6 +133,7 @@ static const char * const optabs[] =
   "exp10_optab->handlers[$A].insn_code = CODE_FOR_$(exp10$a2$)",
   "exp2_optab->handlers[$A].insn_code = CODE_FOR_$(exp2$a2$)",
   "expm1_optab->handlers[$A].insn_code = CODE_FOR_$(expm1$a2$)",
+  "ldexp_optab->handlers[$A].insn_code = CODE_FOR_$(ldexp$a3$)",
   "logb_optab->handlers[$A].insn_code = CODE_FOR_$(logb$a2$)",
   "ilogb_optab->handlers[$A].insn_code = CODE_FOR_$(ilogb$a2$)",
   "log_optab->handlers[$A].insn_code = CODE_FOR_$(log$a2$)",
Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.259
diff -u -p -r1.259 optabs.c
--- optabs.c	9 Feb 2005 20:58:02 -0000	1.259
+++ optabs.c	11 Feb 2005 15:44:53 -0000
@@ -5027,6 +5027,7 @@ init_optabs (void)
   exp10_optab = init_optab (UNKNOWN);
   exp2_optab = init_optab (UNKNOWN);
   expm1_optab = init_optab (UNKNOWN);
+  ldexp_optab = init_optab (UNKNOWN);
   logb_optab = init_optab (UNKNOWN);
   ilogb_optab = init_optab (UNKNOWN);
   log_optab = init_optab (UNKNOWN);
Index: optabs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.h,v
retrieving revision 1.48
diff -u -p -r1.48 optabs.h
--- optabs.h	9 Feb 2005 20:58:03 -0000	1.48
+++ optabs.h	11 Feb 2005 15:44:53 -0000
@@ -171,6 +171,8 @@ enum optab_index
   OTI_exp2,
   /* Exponential - 1*/
   OTI_expm1,
+  /* Load exponent of a floating point number */
+  OTI_ldexp,
   /* Radix-independent exponent */
   OTI_logb,
   OTI_ilogb,
@@ -302,6 +304,7 @@ extern GTY(()) optab optab_table[OTI_MAX
 #define exp10_optab (optab_table[OTI_exp10])
 #define exp2_optab (optab_table[OTI_exp2])
 #define expm1_optab (optab_table[OTI_expm1])
+#define ldexp_optab (optab_table[OTI_ldexp])
 #define logb_optab (optab_table[OTI_logb])
 #define ilogb_optab (optab_table[OTI_ilogb])
 #define log_optab (optab_table[OTI_log])
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.617
diff -u -p -r1.617 i386.md
--- config/i386/i386.md	31 Jan 2005 09:16:02 -0000	1.617
+++ config/i386/i386.md	11 Feb 2005 15:44:58 -0000
@@ -16176,6 +16176,71 @@
   emit_move_insn (operands[2], temp);
   emit_move_insn (operands[9], CONST1_RTX (XFmode));  /* fld1 */
 })
+
+(define_expand "ldexpdf3"
+  [(set (match_dup 3)
+	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (set (match_dup 4)
+	(float:XF (match_operand:SI 2 "register_operand" "")))
+   (parallel [(set (match_dup 5)
+		   (unspec:XF [(match_dup 3) (match_dup 4)]
+			      UNSPEC_FSCALE_FRACT))
+	      (set (match_dup 6)
+		   (unspec:XF [(match_dup 3) (match_dup 4)]
+			      UNSPEC_FSCALE_EXP))])
+   (set (match_operand:DF 0 "register_operand" "")
+	(float_truncate:DF (match_dup 5)))]
+  "TARGET_USE_FANCY_MATH_387
+   && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=3; i<7; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "ldexpsf3"
+  [(set (match_dup 3)
+	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (set (match_dup 4)
+	(float:XF (match_operand:SI 2 "register_operand" "")))
+   (parallel [(set (match_dup 5)
+		   (unspec:XF [(match_dup 3) (match_dup 4)]
+			      UNSPEC_FSCALE_FRACT))
+	      (set (match_dup 6)
+		   (unspec:XF [(match_dup 3) (match_dup 4)]
+			      UNSPEC_FSCALE_EXP))])
+   (set (match_operand:SF 0 "register_operand" "")
+	(float_truncate:SF (match_dup 5)))]
+  "TARGET_USE_FANCY_MATH_387
+   && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=3; i<7; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "ldexpxf3"
+  [(set (match_dup 3)
+	(float:XF (match_operand:SI 2 "register_operand" "")))
+   (parallel [(set (match_operand:XF 0 " register_operand" "")
+		   (unspec:XF [(match_operand:XF 1 "register_operand" "")
+			       (match_dup 3)]
+			      UNSPEC_FSCALE_FRACT))
+	      (set (match_dup 4)
+		   (unspec:XF [(match_dup 1) (match_dup 3)]
+			      UNSPEC_FSCALE_EXP))])]
+  "TARGET_USE_FANCY_MATH_387
+   && flag_unsafe_math_optimizations"
+{
+  int i;
+
+  for (i=3; i<5; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+})
 
 
 (define_insn "frndintxf2"
Index: testsuite/gcc.dg/builtins-34.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/builtins-34.c,v
retrieving revision 1.3
diff -u -p -r1.3 builtins-34.c
--- testsuite/gcc.dg/builtins-34.c	3 May 2004 05:31:45 -0000	1.3
+++ testsuite/gcc.dg/builtins-34.c	11 Feb 2005 15:45:02 -0000
@@ -12,14 +12,17 @@ extern double exp10(double);
 extern double exp2(double);
 extern double pow10(double);
 extern double expm1(double);
+extern double ldexp(double, int);
 extern float exp10f(float);
 extern float exp2f(float);
 extern float pow10f(float);
 extern float expm1f(float);
+extern float ldexpf(float, int);
 extern long double exp10l(long double);
 extern long double exp2l(long double);
 extern long double pow10l(long double);
 extern long double expm1l(long double);
+extern long double ldexpl(long double, int);
 
 
 double test1(double x)
@@ -42,6 +45,11 @@ double test4(double x)
   return expm1(x);
 }
 
+double test5(double x, int exp)
+{
+  return ldexp(x, exp);
+}
+
 float test1f(float x)
 {
   return exp10f(x);
@@ -62,6 +70,11 @@ float test4f(float x)
   return expm1f(x);
 }
 
+float test5f(float x, int exp)
+{
+  return ldexpf(x, exp);
+}
+
 long double test1l(long double x)
 {
   return exp10l(x);
@@ -82,3 +95,7 @@ long double test4l(long double x)
   return expm1l(x);
 }
 
+long double test5l(long double x, int exp)
+{
+  return ldexpl(x, exp);
+}

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