optabs.h (enum optab_index): Add new OTI_log1p.
authorUros Bizjak <uros@kss-loka.si>
Fri, 7 May 2004 05:38:21 +0000 (07:38 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Fri, 7 May 2004 05:38:21 +0000 (07:38 +0200)
* 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.c (ix86_emit_i387_log1p): New function.
* config/i386/i386-protos.h (ix86_emit_i387_log1p):
Prototype here.
* 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/gcc.dg/builtins-33.c:  Also check log1p*.

From-SVN: r81606

gcc/ChangeLog
gcc/builtins.c
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h
gcc/reg-stack.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-33.c

index 329108b1c15d7e34d2de8ba7fe1038371352e1df..fd7949157cee752ffe3d33f66267386e6d77a974 100644 (file)
@@ -1,3 +1,27 @@
+2004-05-07  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.c (ix86_emit_i387_log1p): New function.
+       * config/i386/i386-protos.h (ix86_emit_i387_log1p):
+       Prototype here.
+       * 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.
+
 2004-05-07  Loren James Rittle  <ljrittle@acm.org>
 
        * config/alpha/freebsd.h (SUBTARGET_EXTRA_SPECS): Pass -Werror.
index 612684262b563a650c5a4b55bce96512513abdf4..33fca2ab32eaa56ebc6674b86c676863811b3ecd 100644 (file)
@@ -1624,6 +1624,10 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
     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, rtx subtarget, enum machine_mode mode,
     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 636d50b20e179db95915b265fabe8c7345571e1b..42771f95051a7e688f5c38124908fae4584e4ad9 100644 (file)
@@ -184,6 +184,8 @@ extern void x86_function_profiler (FILE *, int);
 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 a561d4fe0e1d06b32b918e3103bc53e4fedee78e..0a45e3e95d5453093b165b241129f512e18070b9 100644 (file)
@@ -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 ea61cc796a1f7beead883497de258431a7688469..b1366799ba301c665dfdd81e4b19a346a90fa584 100644 (file)
    ; x87 Floating point
    (UNSPEC_FPATAN              65)
    (UNSPEC_FYL2X               66)
+   (UNSPEC_FYL2XP1             67)
    (UNSPEC_FRNDINT             68)
    (UNSPEC_F2XM1               69)
 
   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")]
   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"
   [(set (match_operand:XF 0 "register_operand" "=f")
        (unspec:XF [(match_operand:XF 2 "register_operand" "0")]
index 307849adcdf0a4b35de27f011eb6fa23d1f2766b..a7c9f7e56283b6af5a9f2e7e1999bc77703e318b 100644 (file)
@@ -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 719fbb434c65f5f56f097763b597e7b76eef8ccc..f89e053c456d975341d86b06942cd98baa94fad8 100644 (file)
@@ -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 84d8957f22dfe381e92320a416c02dc28d3141a5..6fc6c1779e180e5b75511ae87871f957a44a82bc 100644 (file)
@@ -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 bab401ff0bd0ca22c0fc94e8baa4530845c5efe7..8314b21ce3570814091e38d6e4a6b4d34246e288 100644 (file)
@@ -1747,6 +1747,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 
              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 f36b6822494b874205cd1f4adb577329fb231d76..c94bb5442cd2d4f316bdc0dd1f23611f8e85fd92 100644 (file)
@@ -1,3 +1,7 @@
+2004-05-07  Uros Bizjak  <uros@kss-loka.si>
+
+       * gcc.dg/builtins-33.c:  Also check log1p*.
+
 2004-05-07  Hans-Peter Nilsson  <hp@axis.com>
 
        PR optimization/15296
index 758978f0600ab97f4a556c5c0ad2a029ee8d4695..11393e30089ba95619502f8b7681fb0c45f8e99b 100644 (file)
 
 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);
+}