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] Implement log1p as built-in x87 intrinsic


Hello!

Attached to this message, please find a patch that implements log1p as built-in x87 intrinsic. This patch is modelled after log1p() function in glibc's mathinline.h, however, it generates pentium-pro & co.'s fcomip instructions instead of fcompp for compare, and brings in all other RTL optimizing effects for log1p instruction. Patch was bootstrapped on i686-pc-linux-gnu, tested with builtins-33.c test and with custom torture tests to test accuracy.

OK for mainline CVS?

2004-05-06 Uros Bizjak <uros@kss-loka.si>

   * optabs.h (enum optab_index): Add new OTI_log1p.
   (log1p_optab): Define corresponding macro.
   * optabs.c (init_optabs): Initialize log1p_optab.
   * genopinit.c (optabs): Implement log1p_optab using log1p?f2
   patterns.
   * builtins.c (expand_builtin_mathfn): Handle BUILT_IN_LOG1P{,F,L}
   using log1p_optab.
   (expand_builtin): Expand BUILT_IN_LOG1P{,F,L} using
   expand_builtin_mathfn if flag_unsafe_math_optimizations is set.

* reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_FYL2XP1.

   * config/i386/i386.md (UNSPEC_FYL2XP1): New unspec to represent x87's
   fyl2xp1 instruction.
   (*fyl2x_xf3): Rename insn definition to fyl2x_xf3.
   (fyl2xp1_xf3): New pattern to implement fyl2xp1 x87 instruction.
   (log1psf2, log1pdf2, log1pxf2): New expanders to implement log1pf,
   log1p  and log1pl built-ins as inline x87 intrinsics.

testsuite:

* testsuite/gcc.dg/builtins-33.c: Also check log1p*.

Uros.
Index: gcc/builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.320
diff -u -p -r1.320 builtins.c
--- gcc/builtins.c	6 May 2004 05:19:17 -0000	1.320
+++ gcc/builtins.c	6 May 2004 09:42:25 -0000
@@ -1624,6 +1624,10 @@ expand_builtin_mathfn (tree exp, rtx tar
     case BUILT_IN_LOG2F:
     case BUILT_IN_LOG2L:
       errno_set = true; builtin_optab = log2_optab; break;
+    case BUILT_IN_LOG1P:
+    case BUILT_IN_LOG1PF:
+    case BUILT_IN_LOG1PL:
+      errno_set = true; builtin_optab = log1p_optab; break;
     case BUILT_IN_ASIN:
     case BUILT_IN_ASINF:
     case BUILT_IN_ASINL:
@@ -5322,6 +5326,9 @@ expand_builtin (tree exp, rtx target, rt
     case BUILT_IN_LOG2:
     case BUILT_IN_LOG2F:
     case BUILT_IN_LOG2L:
+    case BUILT_IN_LOG1P:
+    case BUILT_IN_LOG1PF:
+    case BUILT_IN_LOG1PL:
     case BUILT_IN_TAN:
     case BUILT_IN_TANF:
     case BUILT_IN_TANL:
Index: gcc/genopinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genopinit.c,v
retrieving revision 1.74
diff -u -p -r1.74 genopinit.c
--- gcc/genopinit.c	6 May 2004 05:19:17 -0000	1.74
+++ gcc/genopinit.c	6 May 2004 09:42:25 -0000
@@ -138,6 +138,7 @@ static const char * const optabs[] =
   "log_optab->handlers[$A].insn_code = CODE_FOR_$(log$a2$)",
   "log10_optab->handlers[$A].insn_code = CODE_FOR_$(log10$a2$)",  
   "log2_optab->handlers[$A].insn_code = CODE_FOR_$(log2$a2$)",  
+  "log1p_optab->handlers[$A].insn_code = CODE_FOR_$(log1p$a2$)",  
   "tan_optab->handlers[$A].insn_code = CODE_FOR_$(tan$a2$)",
   "atan_optab->handlers[$A].insn_code = CODE_FOR_$(atan$a2$)",
   "strlen_optab->handlers[$A].insn_code = CODE_FOR_$(strlen$a$)",
Index: gcc/optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.220
diff -u -p -r1.220 optabs.c
--- gcc/optabs.c	6 May 2004 05:19:17 -0000	1.220
+++ gcc/optabs.c	6 May 2004 09:42:25 -0000
@@ -5394,6 +5394,7 @@ init_optabs (void)
   log_optab = init_optab (UNKNOWN);
   log10_optab = init_optab (UNKNOWN);
   log2_optab = init_optab (UNKNOWN);
+  log1p_optab = init_optab (UNKNOWN);
   tan_optab = init_optab (UNKNOWN);
   atan_optab = init_optab (UNKNOWN);
   strlen_optab = init_optab (UNKNOWN);
Index: gcc/optabs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.h,v
retrieving revision 1.28
diff -u -p -r1.28 optabs.h
--- gcc/optabs.h	6 May 2004 05:19:20 -0000	1.28
+++ gcc/optabs.h	6 May 2004 09:42:25 -0000
@@ -178,6 +178,8 @@ enum optab_index
   OTI_log10,
   /* Base-2 Logarithm */
   OTI_log2,
+  /* logarithm of 1 plus argument */
+  OTI_log1p,
   /* Rounding functions */
   OTI_floor,
   OTI_ceil,
@@ -294,6 +296,7 @@ extern GTY(()) optab optab_table[OTI_MAX
 #define log_optab (optab_table[OTI_log])
 #define log10_optab (optab_table[OTI_log10])
 #define log2_optab (optab_table[OTI_log2])
+#define log1p_optab (optab_table[OTI_log1p])
 #define floor_optab (optab_table[OTI_floor])
 #define ceil_optab (optab_table[OTI_ceil])
 #define btrunc_optab (optab_table[OTI_trunc])
Index: gcc/reg-stack.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reg-stack.c,v
retrieving revision 1.152
diff -u -p -r1.152 reg-stack.c
--- gcc/reg-stack.c	6 May 2004 05:19:20 -0000	1.152
+++ gcc/reg-stack.c	6 May 2004 09:42:25 -0000
@@ -1747,6 +1747,7 @@ subst_stack_regs_pat (rtx insn, stack re
 
 	      case UNSPEC_FPATAN:
 	      case UNSPEC_FYL2X:
+	      case UNSPEC_FYL2XP1:
 		/* These insns operate on the top two stack slots.  */
 
 		src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
Index: gcc/config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.110
diff -u -p -r1.110 i386-protos.h
--- gcc/config/i386/i386-protos.h	6 May 2004 05:19:22 -0000	1.110
+++ gcc/config/i386/i386-protos.h	6 May 2004 09:42:25 -0000
@@ -184,6 +184,8 @@ extern void x86_function_profiler (FILE 
 extern void x86_emit_floatuns (rtx [2]);
 extern void ix86_emit_fp_unordered_jump (rtx);
 
+extern void ix86_emit_i387_log1p (rtx, rtx);
+
 extern enum rtx_code ix86_reverse_condition (enum rtx_code, enum machine_mode);
 
 #ifdef TREE_CODE
Index: gcc/config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.665
diff -u -p -r1.665 i386.c
--- gcc/config/i386/i386.c	6 May 2004 05:19:22 -0000	1.665
+++ gcc/config/i386/i386.c	6 May 2004 09:42:26 -0000
@@ -15949,4 +15949,34 @@ ix86_emit_fp_unordered_jump (rtx label)
   emit_jump_insn (temp);
 }
 
+/* Output code to perform a log1p XFmode calculation.  */
+
+void ix86_emit_i387_log1p (rtx op0, rtx op1)
+{
+  rtx label1 = gen_label_rtx ();
+  rtx label2 = gen_label_rtx ();
+
+  rtx tmp = gen_reg_rtx (XFmode);
+  rtx tmp2 = gen_reg_rtx (XFmode);
+
+  emit_insn (gen_absxf2 (tmp, op1));
+  emit_insn (gen_cmpxf (tmp,
+    CONST_DOUBLE_FROM_REAL_VALUE (
+       REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode),
+       XFmode)));
+  emit_jump_insn (gen_bge (label1));
+
+  emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */
+  emit_insn (gen_fyl2xp1_xf3 (op0, tmp2, op1));
+  emit_jump (label2);
+
+  emit_label (label1);
+  emit_move_insn (tmp, CONST1_RTX (XFmode));
+  emit_insn (gen_addxf3 (tmp, op1, tmp));
+  emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */
+  emit_insn (gen_fyl2x_xf3 (op0, tmp2, tmp));
+
+  emit_label (label2);
+}
+     
 #include "gt-i386.h"
Index: gcc/config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.536
diff -u -p -r1.536 i386.md
--- gcc/config/i386/i386.md	6 May 2004 06:00:03 -0000	1.536
+++ gcc/config/i386/i386.md	6 May 2004 09:42:26 -0000
@@ -117,6 +117,7 @@
    ; x87 Floating point
    (UNSPEC_FPATAN		65)
    (UNSPEC_FYL2X		66)
+   (UNSPEC_FYL2XP1		67)
    (UNSPEC_FRNDINT		68)
    (UNSPEC_F2XM1		69)
 
@@ -15628,7 +15629,7 @@
   emit_move_insn (operands[3], CONST1_RTX (XFmode));  /* fld1 */
 })
 
-(define_insn "*fyl2x_xf3"
+(define_insn "fyl2x_xf3"
   [(set (match_operand:XF 0 "register_operand" "=f")
         (unspec:XF [(match_operand:XF 2 "register_operand" "0")
 		    (match_operand:XF 1 "register_operand" "u")]
@@ -15806,6 +15807,58 @@
 {
   operands[2] = gen_reg_rtx (XFmode);
   emit_move_insn (operands[2], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_insn "fyl2xp1_xf3"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+        (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+		    (match_operand:XF 1 "register_operand" "u")]
+	           UNSPEC_FYL2XP1))
+   (clobber (match_scratch:XF 3 "=1"))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+  "fyl2xp1"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "XF")])
+
+(define_expand "log1psf2"
+  [(use (match_operand:XF 0 "register_operand" ""))
+   (use (match_operand:XF 1 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx op0 = gen_reg_rtx (XFmode);
+  rtx op1 = gen_reg_rtx (XFmode);
+
+  emit_insn (gen_extendsfxf2 (op1, operands[1]));
+  ix86_emit_i387_log1p (op0, op1);
+  emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+  DONE;
+})
+
+(define_expand "log1pdf2"
+  [(use (match_operand:XF 0 "register_operand" ""))
+   (use (match_operand:XF 1 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx op0 = gen_reg_rtx (XFmode);
+  rtx op1 = gen_reg_rtx (XFmode);
+
+  emit_insn (gen_extenddfxf2 (op1, operands[1]));
+  ix86_emit_i387_log1p (op0, op1);
+  emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+  DONE;
+})
+
+(define_expand "log1pxf2"
+  [(use (match_operand:XF 0 "register_operand" ""))
+   (use (match_operand:XF 1 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  ix86_emit_i387_log1p (operands[0], operands[1]);
+  DONE;
 })
 
 (define_insn "*fxtractxf3"
Index: gcc/testsuite/gcc.dg/builtins-33.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/builtins-33.c,v
retrieving revision 1.1
diff -u -p -r1.1 builtins-33.c
--- gcc/testsuite/gcc.dg/builtins-33.c	11 Feb 2004 23:39:41 -0000	1.1
+++ gcc/testsuite/gcc.dg/builtins-33.c	6 May 2004 09:42:27 -0000
@@ -10,10 +10,13 @@
 
 extern double log10(double);
 extern double log2(double);
+extern double log1p(double);
 extern float log10f(float);
 extern float log2f(float);
+extern float log1pf(float);
 extern long double log10l(long double);
 extern long double log2l(long double);
+extern long double log1pl(long double);
 
 
 double test1(double x)
@@ -26,6 +29,11 @@ double test2(double x)
   return log2(x);
 }
 
+double test3(double x)
+{
+  return log1p(x);
+}
+
 float test1f(float x)
 {
   return log10f(x);
@@ -36,6 +44,11 @@ float test2f(float x)
   return log2f(x);
 }
 
+float test3f(float x)
+{
+  return log1pf(x);
+}
+
 long double test1l(long double x)
 {
   return log10l(x);
@@ -46,3 +59,7 @@ long double test2l(long double x)
   return log2l(x);
 }
 
+long double test3l(long double x)
+{
+  return log1pl(x);
+}

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