i386.md (expsf2, [...]): New patterns to implement exp, expf and expl built-ins as...
authorRoger Sayle <roger@eyesopen.com>
Sun, 15 Jun 2003 13:32:31 +0000 (13:32 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sun, 15 Jun 2003 13:32:31 +0000 (13:32 +0000)
* config/i386/i386.md (expsf2, expdf2, expxf2): New patterns to
implement exp, expf and expl built-ins as inline x87 intrinsics.
(UNSPEC_FSCALE, UNSPEC_FRNDINT, UNSPEC_F2XM1): New unspecs to
represent x87's fscale, frndint and f2xm1 insns respectively.
(*fscale_sfxf3, *fscale_dfxf3, *fscale_xf3): New insn patterns
to encode x87's "fscale" instruction followed by a pop.
(*frndintxf2): New insn pattern for "frndint".
(*f2xm1xf2): New insn pattern for "f2xm1".

* reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_FRNDINT and
UNSPEC_F2XM1 like UNSPEC_{SIN,COS} and handle UNSPEC_FSCALE like
UNSPEC_FPATAN.

* gcc.dg/builtins-22.c: New test case.
* gcc.dg/i386-387-1.c: Update to test exp.
* gcc.dg/i386-387-2.c: Likewise.

From-SVN: r67973

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/reg-stack.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-22.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/i386-387-1.c
gcc/testsuite/gcc.dg/i386-387-2.c

index e9ab9457cacb29a4d33763172abe9402f2d93ef1..74fad5bc6cf4210747e8613848d5d0d662e0bcb4 100644 (file)
@@ -1,3 +1,18 @@
+2003-06-15  Roger Sayle  <roger@eyesopen.com>
+
+       * config/i386/i386.md (expsf2, expdf2, expxf2): New patterns to
+       implement exp, expf and expl built-ins as inline x87 intrinsics.
+       (UNSPEC_FSCALE, UNSPEC_FRNDINT, UNSPEC_F2XM1): New unspecs to
+       represent x87's fscale, frndint and f2xm1 insns respectively.
+       (*fscale_sfxf3, *fscale_dfxf3, *fscale_xf3): New insn patterns
+       to encode x87's "fscale" instruction followed by a pop.
+       (*frndintxf2): New insn pattern for "frndint".
+       (*f2xm1xf2): New insn pattern for "f2xm1".
+
+       * reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_FRNDINT and
+       UNSPEC_F2XM1 like UNSPEC_{SIN,COS} and handle UNSPEC_FSCALE like
+       UNSPEC_FPATAN.
+
 2003-06-15  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * Makefile.in (stagefeedback-start): Use $(SUBDIRS) instead of
index faf0e5a5b98b0ea9c38861c8c6f2c9b6e1c4d488..7ea02a7a7f973b17f398760d4cdd7cc4eb2bcda1 100644 (file)
    ; x87 Floating point
    (UNSPEC_FPATAN              65)
    (UNSPEC_FYL2X               66)
+   (UNSPEC_FSCALE              67)
+   (UNSPEC_FRNDINT             68)
+   (UNSPEC_F2XM1               69)
 
    ; REP instruction
-   (UNSPEC_REP                 67)
+   (UNSPEC_REP                 75)
   ])
 
 (define_constants
   temp = standard_80387_constant_rtx (4); /* fldln2 */
   emit_move_insn (operands[2], temp);
 })
+
+(define_insn "*fscale_sfxf3"
+  [(parallel [(set (match_operand:SF 0 "register_operand" "=f")
+                  (unspec:SF [(match_operand:XF 2 "register_operand" "0")
+                              (match_operand:XF 1 "register_operand" "u")]
+                   UNSPEC_FSCALE))
+             (clobber (match_dup 1))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+  "fscale\;fstp\t%y1"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "SF")])
+
+(define_insn "*fscale_dfxf3"
+  [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
+                  (unspec:DF [(match_operand:XF 2 "register_operand" "0")
+                              (match_operand:XF 1 "register_operand" "u")]
+                   UNSPEC_FSCALE))
+             (clobber (match_dup 1))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+  "fscale\;fstp\t%y1"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "DF")])
+
+(define_insn "*fscale_xf3"
+  [(parallel [(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_FSCALE))
+             (clobber (match_dup 1))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+  "fscale\;fstp\t%y1"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "XF")])
+
+(define_insn "*frndintxf2"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+       (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+        UNSPEC_FRNDINT))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+  "frndint"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "XF")])
+
+(define_insn "*f2xm1xf2"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+       (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+        UNSPEC_F2XM1))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+  "f2xm1"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "XF")])
+
+(define_expand "expsf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
+   (parallel [(set (match_operand:SF 0 "register_operand" "")
+                  (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
+             (clobber (match_dup 5))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx temp;
+  int i;
+
+  for (i=2; i<10; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+  temp = standard_80387_constant_rtx (5); /* fldl2e */
+  emit_move_insn (operands[3], temp);
+  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_expand "expdf2"
+  [(set (match_dup 2)
+       (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+   (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+   (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+   (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+   (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+   (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
+   (parallel [(set (match_operand:DF 0 "register_operand" "")
+                  (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
+             (clobber (match_dup 5))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx temp;
+  int i;
+
+  for (i=2; i<10; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+  temp = standard_80387_constant_rtx (5); /* fldl2e */
+  emit_move_insn (operands[3], temp);
+  emit_move_insn (operands[8], CONST1_RTX (XFmode));  /* fld1 */
+})
+
+(define_expand "expxf2"
+  [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
+                              (match_dup 2)))
+   (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
+   (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
+   (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
+   (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
+   (parallel [(set (match_operand:XF 0 "register_operand" "")
+                  (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE))
+             (clobber (match_dup 4))])]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx temp;
+  int i;
+
+  for (i=2; i<9; i++)
+    operands[i] = gen_reg_rtx (XFmode);
+  temp = standard_80387_constant_rtx (5); /* fldl2e */
+  emit_move_insn (operands[2], temp);
+  emit_move_insn (operands[7], CONST1_RTX (XFmode));  /* fld1 */
+})
 \f
 ;; Block operation instructions
 
index 6efea36d6dc9fbb53bcdde63c1048c53289c6b60..5b3a359d606f139b6f259a533bb94b323814a385 100644 (file)
@@ -1711,6 +1711,8 @@ subst_stack_regs_pat (insn, regstack, pat)
              {
              case UNSPEC_SIN:
              case UNSPEC_COS:
+             case UNSPEC_FRNDINT:
+             case UNSPEC_F2XM1:
                /* These insns only operate on the top of the stack.  */
 
                src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
@@ -1734,6 +1736,7 @@ subst_stack_regs_pat (insn, regstack, pat)
 
              case UNSPEC_FPATAN:
              case UNSPEC_FYL2X:
+             case UNSPEC_FSCALE:
                /* These insns operate on the top two stack slots.  */
 
                src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
index 5c2b747b71969b23be11ca6d6a4e673598eb1d9d..4371663f1a55ff95b43a755e75451b487823bcbd 100644 (file)
@@ -1,3 +1,9 @@
+2003-06-15  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/builtins-22.c: New test case.
+       * gcc.dg/i386-387-1.c: Update to test exp.
+       * gcc.dg/i386-387-2.c: Likewise.
+
 2003-06-13  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.dg/format/asm_fprintf-1.c: Update width/precision checks.
diff --git a/gcc/testsuite/gcc.dg/builtins-22.c b/gcc/testsuite/gcc.dg/builtins-22.c
new file mode 100644 (file)
index 0000000..916890b
--- /dev/null
@@ -0,0 +1,12 @@
+/* Related to PR optimization/10764  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+double exp(double x);
+
+double foo(double x)
+{
+  return exp(exp(x));
+}
+
index 07389106f506034a7121132963033811e00019e4..79d25e2432eb730e5b64b17e87ec7895d71c2976 100644 (file)
@@ -6,9 +6,11 @@
 /* { dg-final { scan-assembler "call\t_?sqrt" } } */
 /* { dg-final { scan-assembler "call\t_?atan2" } } */
 /* { dg-final { scan-assembler "call\t_?log" } } */
+/* { dg-final { scan-assembler "call\t_?exp" } } */
 
 double f1(double x) { return __builtin_sin(x); }
 double f2(double x) { return __builtin_cos(x); }
 double f3(double x) { return __builtin_sqrt(x); }
 double f4(double x, double y) { return __builtin_atan2(x,y); }
 double f5(double x) { return __builtin_log(x); }
+double f6(double x) { return __builtin_exp(x); }
index 3bebc758f2a30bbc05716c54aa4fed768e391e39..bfda85bc17107c956a415dade8daac13956ed347 100644 (file)
@@ -6,9 +6,11 @@
 /* { dg-final { scan-assembler "fsqrt" } } */
 /* { dg-final { scan-assembler "fpatan" } } */
 /* { dg-final { scan-assembler "fyl2x" } } */
+/* { dg-final { scan-assembler "f2xm1" } } */
 
 double f1(double x) { return __builtin_sin(x); }
 double f2(double x) { return __builtin_cos(x); }
 double f3(double x) { return __builtin_sqrt(x); }
 double f4(double x, double y) { return __builtin_atan2(x,y); }
 double f5(double x) { return __builtin_log(x); }
+double f6(double x) { return __builtin_exp(x); }