summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-20 13:33:51 +0000
committeruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-20 13:33:51 +0000
commit73a954a137a4ad3aff3c816a4a401887669ab5f7 (patch)
tree95fa0014104dcb6887115c27e24a726801ecd2a0
parent19636773804cc810ffb5dec03069184ff71404bc (diff)
downloadgcc-73a954a137a4ad3aff3c816a4a401887669ab5f7.tar.gz
* optabs.h (enum optab_index): Add new OTI_scalb.
(scalb_optab): Define corresponding macro. * optabs.c (init_optabs): Initialize scalb_optab. * genopinit.c (optabs): Implement scalb_optab using scalb?f3 patterns. * builtins.c (expand_builtin_mathfn_2, expand_builtin): Handle BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L} and BUILT_IN_SCALBLN{,F,L}. (expand_builtin): Expand BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L} and BUILT_IN_SCALBLN{,F,L} using expand_builtin_mathfn_2 if flag_unsafe_math_optimizations is set. * config/i386/i386.md (scalbxf3, scalb<mode>3): New expanders to implement scalbf, scalb and scalbl built-ins as inline x87 intrinsics. testsuite/ChangeLog * gcc.dg/builtins-34.c: Add scalb/scalbn/scalbln cases. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122162 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/builtins.c25
-rw-r--r--gcc/config/i386/i386.md34
-rw-r--r--gcc/genopinit.c1
-rw-r--r--gcc/optabs.c1
-rw-r--r--gcc/optabs.h3
-rw-r--r--gcc/testsuite/ChangeLog12
-rw-r--r--gcc/testsuite/gcc.dg/builtins-34.c54
8 files changed, 140 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ebceb404f1a..292bfbc1533 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2007-02-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ * optabs.h (enum optab_index): Add new OTI_scalb.
+ (scalb_optab): Define corresponding macro.
+ * optabs.c (init_optabs): Initialize scalb_optab.
+ * genopinit.c (optabs): Implement scalb_optab using scalb?f3
+ patterns.
+ * builtins.c (expand_builtin_mathfn_2, expand_builtin): Handle
+ BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L} and BUILT_IN_SCALBLN{,F,L}.
+ (expand_builtin): Expand BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L}
+ and BUILT_IN_SCALBLN{,F,L} using expand_builtin_mathfn_2 if
+ flag_unsafe_math_optimizations is set.
+
+ * config/i386/i386.md (scalbxf3, scalb<mode>3): New expanders
+ to implement scalbf, scalb and scalbl built-ins as inline x87
+ intrinsics.
+
2007-02-20 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
DJ Delorie <dj@redhat.com>
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 67d9bf63f25..e1c2deef647 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1973,10 +1973,15 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
bool errno_set = true;
bool stable = true;
- 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;
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_SCALBN):
+ CASE_FLT_FN (BUILT_IN_SCALBLN):
+ CASE_FLT_FN (BUILT_IN_LDEXP):
+ op1_type = INTEGER_TYPE;
+ default:
+ break;
+ }
if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
return NULL_RTX;
@@ -1990,6 +1995,15 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
builtin_optab = pow_optab; break;
CASE_FLT_FN (BUILT_IN_ATAN2):
builtin_optab = atan2_optab; break;
+ CASE_FLT_FN (BUILT_IN_SCALB):
+ if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
+ return 0;
+ builtin_optab = scalb_optab; break;
+ CASE_FLT_FN (BUILT_IN_SCALBN):
+ CASE_FLT_FN (BUILT_IN_SCALBLN):
+ if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
+ return 0;
+ /* Fall through... */
CASE_FLT_FN (BUILT_IN_LDEXP):
builtin_optab = ldexp_optab; break;
CASE_FLT_FN (BUILT_IN_FMOD):
@@ -5963,6 +5977,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
CASE_FLT_FN (BUILT_IN_ATAN2):
CASE_FLT_FN (BUILT_IN_LDEXP):
+ CASE_FLT_FN (BUILT_IN_SCALB):
+ CASE_FLT_FN (BUILT_IN_SCALBN):
+ CASE_FLT_FN (BUILT_IN_SCALBLN):
if (! flag_unsafe_math_optimizations)
break;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 7dae8e1e0b7..920b9dde8a1 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -17228,6 +17228,40 @@
emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
DONE;
})
+
+(define_expand "scalbxf3"
+ [(parallel [(set (match_operand:XF 0 " register_operand" "")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "")
+ (match_operand:XF 2 "register_operand" "")]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 3)
+ (unspec:XF [(match_dup 1) (match_dup 2)]
+ UNSPEC_FSCALE_EXP))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations && !optimize_size"
+{
+ operands[3] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "scalb<mode>3"
+ [(use (match_operand:X87MODEF12 0 "register_operand" ""))
+ (use (match_operand:X87MODEF12 1 "general_operand" ""))
+ (use (match_operand:X87MODEF12 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+ || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations && !optimize_size"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_extend<mode>xf2 (op2, operands[2]));
+ emit_insn (gen_scalbxf3 (op0, op1, op2));
+ emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ DONE;
+})
(define_insn "frndintxf2"
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 1e70c6d07a8..3c06639f075 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -140,6 +140,7 @@ static const char * const optabs[] =
"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$)",
+ "scalb_optab->handlers[$A].insn_code = CODE_FOR_$(scalb$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$)",
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 6a78b3785ac..51c84c82352 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5449,6 +5449,7 @@ init_optabs (void)
exp2_optab = init_optab (UNKNOWN);
expm1_optab = init_optab (UNKNOWN);
ldexp_optab = init_optab (UNKNOWN);
+ scalb_optab = init_optab (UNKNOWN);
logb_optab = init_optab (UNKNOWN);
ilogb_optab = init_optab (UNKNOWN);
log_optab = init_optab (UNKNOWN);
diff --git a/gcc/optabs.h b/gcc/optabs.h
index d3cfd742136..0f8c7966809 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -179,6 +179,8 @@ enum optab_index
OTI_expm1,
/* Load exponent of a floating point number */
OTI_ldexp,
+ /* Multiply floating-point number by integral power of radix */
+ OTI_scalb,
/* Radix-independent exponent */
OTI_logb,
OTI_ilogb,
@@ -357,6 +359,7 @@ extern GTY(()) optab optab_table[OTI_MAX];
#define exp2_optab (optab_table[OTI_exp2])
#define expm1_optab (optab_table[OTI_expm1])
#define ldexp_optab (optab_table[OTI_ldexp])
+#define scalb_optab (optab_table[OTI_scalb])
#define logb_optab (optab_table[OTI_logb])
#define ilogb_optab (optab_table[OTI_ilogb])
#define log_optab (optab_table[OTI_log])
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b5f91c5e7dd..80c712cb454 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2007-02-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.dg/builtins-34.c: Add scalb/scalbn/scalbln cases.
+
2007-02-20 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
DJ Delorie <dj@redhat.com>
@@ -76,7 +80,7 @@
2007-02-18 Roger Sayle <roger@eyesopen.com>
- * gfortran.dg/forall_10.f90: New test case.
+ * gfortran.dg/forall_10.f90: New test case.
2007-02-18 Eric Botcazou <ebotcazou@adacore.com>
@@ -1199,9 +1203,9 @@
2007-01-06 Lee Millward <lee.millward@codesourcery.com>
- PR c++/19439
- * g++.dg/template/duplicate1.C: New test
- * g++.dg/template/memfriend6.C: Adjust error markers.
+ PR c++/19439
+ * g++.dg/template/duplicate1.C: New test
+ * g++.dg/template/memfriend6.C: Adjust error markers.
2007-01-05 Andrew Pinski <Andrew_Pinski@playstation.sony.com>
diff --git a/gcc/testsuite/gcc.dg/builtins-34.c b/gcc/testsuite/gcc.dg/builtins-34.c
index f2625d5ef59..ee8d7513f91 100644
--- a/gcc/testsuite/gcc.dg/builtins-34.c
+++ b/gcc/testsuite/gcc.dg/builtins-34.c
@@ -13,16 +13,25 @@ extern double exp2(double);
extern double pow10(double);
extern double expm1(double);
extern double ldexp(double, int);
+extern double scalb(double, double);
+extern double scalbn(double, int);
+extern double scalbln(double, long);
extern float exp10f(float);
extern float exp2f(float);
extern float pow10f(float);
extern float expm1f(float);
extern float ldexpf(float, int);
+extern float scalbf(float, float);
+extern float scalbnf(float, int);
+extern float scalblnf(float, long);
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);
+extern long double scalbl(long double, long double);
+extern long double scalbnl(long double, int);
+extern long double scalblnl(long double, long);
double test1(double x)
@@ -50,6 +59,21 @@ double test5(double x, int exp)
return ldexp(x, exp);
}
+double test6(double x, double exp)
+{
+ return scalb(x, exp);
+}
+
+double test7(double x, int exp)
+{
+ return scalbn(x, exp);
+}
+
+double test8(double x, long exp)
+{
+ return scalbln(x, exp);
+}
+
float test1f(float x)
{
return exp10f(x);
@@ -75,6 +99,21 @@ float test5f(float x, int exp)
return ldexpf(x, exp);
}
+float test6f(float x, float exp)
+{
+ return scalbf(x, exp);
+}
+
+float test7f(float x, int exp)
+{
+ return scalbnf(x, exp);
+}
+
+float test8f(float x, long exp)
+{
+ return scalblnf(x, exp);
+}
+
long double test1l(long double x)
{
return exp10l(x);
@@ -99,3 +138,18 @@ long double test5l(long double x, int exp)
{
return ldexpl(x, exp);
}
+
+long double test6l(long double x, long double exp)
+{
+ return scalbl(x, exp);
+}
+
+long double test7l(long double x, int exp)
+{
+ return scalbnl(x, exp);
+}
+
+long double test8l(long double x, long exp)
+{
+ return scalblnl(x, exp);
+}