* 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
+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.
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:
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:
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
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"
; 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")]
"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$)",
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);
OTI_log10,
/* Base-2 Logarithm */
OTI_log2,
+ /* logarithm of 1 plus argument */
+ OTI_log1p,
/* Rounding functions */
OTI_floor,
OTI_ceil,
#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])
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));
+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
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)
return log2(x);
}
+double test3(double x)
+{
+ return log1p(x);
+}
+
float test1f(float x)
{
return log10f(x);
return log2f(x);
}
+float test3f(float x)
+{
+ return log1pf(x);
+}
+
long double test1l(long double x)
{
return log10l(x);
return log2l(x);
}
+long double test3l(long double x)
+{
+ return log1pl(x);
+}