This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH,i386]: Implement hypot{,f,l} functions as built-in x87 intrinsics
- From: Uros Bizjak <uros at kss-loka dot si>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 12 Feb 2005 13:34:17 +0100
- Subject: [PATCH,i386]: Implement hypot{,f,l} functions as built-in x87 intrinsics
Hello!
This patch implements hypot{f,l} functions 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.
As with ldexp builtints, these intrinsics are guarded with
flag_unsafe_math_optimizations.
2005-02-12 Uros Bizjak <uros@kss-loka.si>
* optabs.h (enum optab_index): Add new OTI_hypot.
(hypot_optab): Define corresponding macro.
* optabs.c (init_optabs): Initialize hypot_optab.
* genopinit.c (optabs): Implement hypot_optab using hypot?f3
patterns.
* builtins.c (expand_builtin_mathfn_2): Handle BUILT_IN_HYPOT{,F,L}
using hypot_optab.
(expand_builtin): Expand BUILT_IN_HYPOT{,F,L} using
expand_builtin_mathfn_2 if flag_unsafe_math_optimizations is set.
* config/i386/i386.md (hypotsf3, hypotdf3, hypotxf3): New expanders
to implement hypotf, hypot and hypotl built-ins as inline x87
intrinsics.
testsuite:
* gcc.dg/builtins-34.c: Also check hypot*.
Uros.
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.422
diff -u -p -r1.422 builtins.c
--- builtins.c 12 Feb 2005 11:34:20 -0000 1.422
+++ builtins.c 12 Feb 2005 12:28:16 -0000
@@ -1887,6 +1887,10 @@ expand_builtin_mathfn_2 (tree exp, rtx t
case BUILT_IN_POWF:
case BUILT_IN_POWL:
builtin_optab = pow_optab; break;
+ case BUILT_IN_HYPOT:
+ case BUILT_IN_HYPOTF:
+ case BUILT_IN_HYPOTL:
+ builtin_optab = hypot_optab; break;
case BUILT_IN_ATAN2:
case BUILT_IN_ATAN2F:
case BUILT_IN_ATAN2L:
@@ -5266,6 +5270,9 @@ expand_builtin (tree exp, rtx target, rt
return target;
break;
+ case BUILT_IN_HYPOT:
+ case BUILT_IN_HYPOTF:
+ case BUILT_IN_HYPOTL:
case BUILT_IN_ATAN2:
case BUILT_IN_ATAN2F:
case BUILT_IN_ATAN2L:
Index: genopinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genopinit.c,v
retrieving revision 1.87
diff -u -p -r1.87 genopinit.c
--- genopinit.c 12 Feb 2005 11:34:21 -0000 1.87
+++ genopinit.c 12 Feb 2005 12:28:16 -0000
@@ -118,6 +118,7 @@ static const char * const optabs[] =
"absv_optab->handlers[$A].insn_code = CODE_FOR_$(absv$I$a2$)",
"copysign_optab->handlers[$A].insn_code = CODE_FOR_$(copysign$F$a3$)",
"sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)",
+ "hypot_optab->handlers[$A].insn_code = CODE_FOR_$(hypot$a3$)",
"floor_optab->handlers[$A].insn_code = CODE_FOR_$(floor$a2$)",
"ceil_optab->handlers[$A].insn_code = CODE_FOR_$(ceil$a2$)",
"round_optab->handlers[$A].insn_code = CODE_FOR_$(round$a2$)",
Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.260
diff -u -p -r1.260 optabs.c
--- optabs.c 12 Feb 2005 11:34:21 -0000 1.260
+++ optabs.c 12 Feb 2005 12:28:17 -0000
@@ -5012,6 +5012,7 @@ init_optabs (void)
popcount_optab = init_optab (POPCOUNT);
parity_optab = init_optab (PARITY);
sqrt_optab = init_optab (SQRT);
+ hypot_optab = init_optab (UNKNOWN);
floor_optab = init_optab (UNKNOWN);
ceil_optab = init_optab (UNKNOWN);
round_optab = init_optab (UNKNOWN);
Index: optabs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.h,v
retrieving revision 1.49
diff -u -p -r1.49 optabs.h
--- optabs.h 12 Feb 2005 11:34:21 -0000 1.49
+++ optabs.h 12 Feb 2005 12:28:17 -0000
@@ -153,6 +153,8 @@ enum optab_index
OTI_parity,
/* Square root */
OTI_sqrt,
+ /* Euclidean distance */
+ OTI_hypot,
/* Sine-Cosine */
OTI_sincos,
/* Sine */
@@ -295,6 +297,7 @@ extern GTY(()) optab optab_table[OTI_MAX
#define popcount_optab (optab_table[OTI_popcount])
#define parity_optab (optab_table[OTI_parity])
#define sqrt_optab (optab_table[OTI_sqrt])
+#define hypot_optab (optab_table[OTI_hypot])
#define sincos_optab (optab_table[OTI_sincos])
#define sin_optab (optab_table[OTI_sin])
#define asin_optab (optab_table[OTI_asin])
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.618
diff -u -p -r1.618 i386.md
--- config/i386/i386.md 12 Feb 2005 11:34:22 -0000 1.618
+++ config/i386/i386.md 12 Feb 2005 12:28:20 -0000
@@ -14689,6 +14689,64 @@
(set_attr "mode" "XF")
(set_attr "athlon_decode" "direct")])
+(define_expand "hypotxf3"
+ [(set (match_dup 3)
+ (mult:XF (match_operand:XF 1 "register_operand" "") (match_dup 1)))
+ (set (match_dup 4)
+ (mult:XF (match_operand:XF 2 "register_operand" "") (match_dup 2)))
+ (set (match_dup 5)
+ (plus:XF (match_dup 3) (match_dup 4)))
+ (set (match_operand:XF 0 "register_operand" "")
+ (sqrt:XF (match_dup 5)))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=3; i<6; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "hypotdf3"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))
+ (use (match_operand:DF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_extenddfxf2 (op2, operands[2]));
+ emit_insn (gen_hypotxf3 (op0, op1, op2));
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "hypotsf3"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))
+ (use (match_operand:SF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_extendsfxf2 (op2, operands[2]));
+ emit_insn (gen_hypotxf3 (op0, op1, op2));
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
(define_insn "fpremxf4"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 2 "register_operand" "0")
Index: testsuite/gcc.dg/builtins-34.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/builtins-34.c,v
retrieving revision 1.4
diff -u -p -r1.4 builtins-34.c
--- testsuite/gcc.dg/builtins-34.c 12 Feb 2005 11:34:24 -0000 1.4
+++ testsuite/gcc.dg/builtins-34.c 12 Feb 2005 12:28:23 -0000
@@ -13,16 +13,19 @@ extern double exp2(double);
extern double pow10(double);
extern double expm1(double);
extern double ldexp(double, int);
+extern double hypot(double, double);
extern float exp10f(float);
extern float exp2f(float);
extern float pow10f(float);
extern float expm1f(float);
extern float ldexpf(float, int);
+extern float hypotf(float, float);
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 hypotl(long double, long double);
double test1(double x)
@@ -50,6 +53,11 @@ double test5(double x, int exp)
return ldexp(x, exp);
}
+double test6(double x, double y)
+{
+ return hypot(x, y);
+}
+
float test1f(float x)
{
return exp10f(x);
@@ -75,6 +83,11 @@ float test5f(float x, int exp)
return ldexpf(x, exp);
}
+float test6f(float x, float y)
+{
+ return hypotf(x, y);
+}
+
long double test1l(long double x)
{
return exp10l(x);
@@ -99,3 +112,8 @@ long double test5l(long double x, int ex
{
return ldexpl(x, exp);
}
+
+long double test6l(long double x, long double y)
+{
+ return hypotl(x, y);
+}