fold-const.c (omit_one_operand): No longer static.
authorRoger Sayle <roger@eyesopen.com>
Sat, 22 Feb 2003 04:16:18 +0000 (04:16 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sat, 22 Feb 2003 04:16:18 +0000 (04:16 +0000)
* fold-const.c (omit_one_operand): No longer static.
* tree.h (omit_one_operand): Prototype here.
(div_and_round_double): Keep fold-const.c prototypes together.
* builtins.c (builtin_mathfn_code): Handle binary built-in
funtions, such as "pow" and "atan2".
(fold_builtin): Optimize both pow(x,0.0) and pow(1.0,y) to 1.0.
Simplify optimizations using "type" the builtin's return type.

* gcc.dg/builtins-5.c: New test case.

From-SVN: r63273

gcc/ChangeLog
gcc/builtins.c
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-5.c [new file with mode: 0644]
gcc/tree.h

index 6d6a6fb5a648351ee4f47945e0186f7738eada72..5ddc7da18995c58e8266ddfa9e2161e3ec424f1d 100644 (file)
@@ -1,3 +1,13 @@
+2003-02-21  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (omit_one_operand): No longer static.
+       * tree.h (omit_one_operand): Prototype here.
+       (div_and_round_double): Keep fold-const.c prototypes together.
+       * builtins.c (builtin_mathfn_code): Handle binary built-in
+       funtions, such as "pow" and "atan2".
+       (fold_builtin): Optimize both pow(x,0.0) and pow(1.0,y) to 1.0.
+       Simplify optimizations using "type" the builtin's return type.
+
 2003-02-22  Hans-Peter Nilsson  <hp@axis.com>
 
        * config/cris/cris.c (cris_rtx_costs): Blockify dangling else.
index ebb9835a2f508d7ab251d578746aa9c9196afec5..81e38db73aacda5710efc1b8a86fa869d85d8e98 100644 (file)
@@ -4515,10 +4515,30 @@ builtin_mathfn_code (t)
 
   arglist = TREE_OPERAND (t, 1);
   if (! arglist
-      || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE
-      || TREE_CHAIN (arglist))
+      || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
     return END_BUILTINS;
 
+  arglist = TREE_CHAIN (arglist);
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+    case BUILT_IN_POW:
+    case BUILT_IN_POWF:
+    case BUILT_IN_POWL:
+    case BUILT_IN_ATAN2:
+    case BUILT_IN_ATAN2F:
+    case BUILT_IN_ATAN2L:
+      if (! arglist
+         || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE
+         || TREE_CHAIN (arglist))
+       return END_BUILTINS;
+      break;
+
+    default:
+      if (arglist)
+       return END_BUILTINS;
+      break;
+    }
+
   return DECL_FUNCTION_CODE (fndecl);
 }
 
@@ -4653,6 +4673,7 @@ fold_builtin (exp)
 {
   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
   tree arglist = TREE_OPERAND (exp, 1);
+  tree type = TREE_TYPE (TREE_TYPE (fndecl));
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
 
   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
@@ -4696,10 +4717,10 @@ fold_builtin (exp)
              REAL_VALUE_TYPE r, x;
 
              x = TREE_REAL_CST (arg);
-             mode = TYPE_MODE (TREE_TYPE (arg));
+             mode = TYPE_MODE (type);
              if (real_sqrt (&r, mode, &x)
                  || (!flag_trapping_math && !flag_errno_math))
-               return build_real (TREE_TYPE (arg), r);
+               return build_real (type, r);
            }
 
          /* Optimize sqrt(exp(x)) = exp(x/2.0).  */
@@ -4710,9 +4731,9 @@ fold_builtin (exp)
                  || fcode == BUILT_IN_EXPL))
            {
              tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
-             arg = build (RDIV_EXPR, TREE_TYPE (arg),
+             arg = build (RDIV_EXPR, type,
                           TREE_VALUE (TREE_OPERAND (arg, 1)),
-                          build_real (TREE_TYPE (arg), dconst2));
+                          build_real (type, dconst2));
              arglist = build_tree_list (NULL_TREE, arg);
              return build_function_call_expr (expfn, arglist);
            }
@@ -4729,7 +4750,7 @@ fold_builtin (exp)
 
          /* Optimize exp(0.0) = 1.0.  */
          if (real_zerop (arg))
-           return build_real (TREE_TYPE (arg), dconst1);
+           return build_real (type, dconst1);
 
          /* Optimize exp(log(x)) = x.  */
          fcode = builtin_mathfn_code (arg);
@@ -4751,7 +4772,7 @@ fold_builtin (exp)
 
          /* Optimize log(1.0) = 0.0.  */
          if (real_onep (arg))
-           return build_real (TREE_TYPE (arg), dconst0);
+           return build_real (type, dconst0);
 
          /* Optimize log(exp(x)) = x.  */
          fcode = builtin_mathfn_code (arg);
@@ -4769,31 +4790,49 @@ fold_builtin (exp)
            {
              tree logfn = build_function_call_expr (fndecl,
                                                     TREE_OPERAND (arg, 1));
-             return fold (build (RDIV_EXPR, TREE_TYPE (arg), logfn,
-                                 build_real (TREE_TYPE (arg), dconst2)));
+             return fold (build (RDIV_EXPR, type, logfn,
+                                 build_real (type, dconst2)));
            }
        }
       break;
 
+    case BUILT_IN_POW:
+    case BUILT_IN_POWF:
+    case BUILT_IN_POWL:
+      if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+       {
+         tree arg0 = TREE_VALUE (arglist);
+         tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+         /* Optimize pow(x,0.0) = 1.0.  */
+         if (real_zerop (arg1))
+           return omit_one_operand (type, build_real (type, dconst1), arg0);
+
+         /* Optimize pow(1.0,y) = 1.0.  */
+         if (real_onep (arg0))
+           return omit_one_operand (type, build_real (type, dconst1), arg1);
+       }
+      break;
+
     case BUILT_IN_INF:
     case BUILT_IN_INFF:
     case BUILT_IN_INFL:
-      return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), true);
+      return fold_builtin_inf (type, true);
 
     case BUILT_IN_HUGE_VAL:
     case BUILT_IN_HUGE_VALF:
     case BUILT_IN_HUGE_VALL:
-      return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), false);
+      return fold_builtin_inf (type, false);
 
     case BUILT_IN_NAN:
     case BUILT_IN_NANF:
     case BUILT_IN_NANL:
-      return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), true);
+      return fold_builtin_nan (arglist, type, true);
 
     case BUILT_IN_NANS:
     case BUILT_IN_NANSF:
     case BUILT_IN_NANSL:
-      return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false);
+      return fold_builtin_nan (arglist, type, false);
 
     case BUILT_IN_FLOOR:
     case BUILT_IN_FLOORF:
index 6b50a86a097b9aa907bb549fc0405f01539467f1..48c3683f8c2667de2c0967cf2aa97c61e12f6480 100644 (file)
@@ -81,7 +81,6 @@ static int truth_value_p      PARAMS ((enum tree_code));
 static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
 static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *));
 static tree eval_subst         PARAMS ((tree, tree, tree, tree, tree));
-static tree omit_one_operand   PARAMS ((tree, tree, tree));
 static tree pedantic_omit_one_operand PARAMS ((tree, tree, tree));
 static tree distribute_bit_expr PARAMS ((enum tree_code, tree, tree, tree));
 static tree make_bit_field_ref PARAMS ((tree, tree, int, int, int));
@@ -2256,7 +2255,7 @@ eval_subst (arg, old0, new0, old1, new1)
    If OMITTED has side effects, we must evaluate it.  Otherwise, just do
    the conversion of RESULT to TYPE.  */
 
-static tree
+tree
 omit_one_operand (type, result, omitted)
      tree type, result, omitted;
 {
index 72512238ca2e9ad9ed0d0bbbe8a8b8cb2506786b..f68ad3aef15262f0167a24db3a3201c283cb7891 100644 (file)
@@ -1,3 +1,7 @@
+2003-02-21  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/builtins-5.c: New test case.
+
 2003-02-22  Hans-Peter Nilsson  <hp@axis.com>
 
        * gcc.dg/asmreg-1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/builtins-5.c b/gcc/testsuite/gcc.dg/builtins-5.c
new file mode 100644 (file)
index 0000000..a056812
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (C) 2003  Free Software Foundation.
+
+   Verify that built-in math function constant folding of constant
+   arguments is correctly performed by the by the compiler.
+
+   Written by Roger Sayle, 20th February 2003.  */
+
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern void link_error(void);
+
+void test(double x)
+{
+  if (pow (x, 0.0) != 1.0)
+    link_error ();
+  if (pow (1.0, x) != 1.0)
+    link_error ();
+}
+
+void testf(float x)
+{
+  if (powf (x, 0.0f) != 1.0f)
+    link_error ();
+  if (powf (1.0f, x) != 1.0f)
+    link_error ();
+}
+
+void testl(long double x)
+{
+  if (powl (x, 0.0l) != 1.0l)
+    link_error ();
+  if (powl (1.0l, x) != 1.0l)
+    link_error ();
+}
+
+int main()
+{
+  test (0.0);
+  testf (0.0f);
+  testl (0.0l);
+
+  return 0;
+}
+
index 7b714b17aafa601e2d6e9eaea3c6a3bd7a2a66cb..6cdf2c8b01706191c12b7f3ba698ae1c69933c3f 100644 (file)
@@ -2902,7 +2902,19 @@ extern void rrotate_double       PARAMS ((unsigned HOST_WIDE_INT, HOST_WIDE_INT,
                                         HOST_WIDE_INT, unsigned int,
                                         unsigned HOST_WIDE_INT *,
                                         HOST_WIDE_INT *));
+
+extern int div_and_round_double                PARAMS ((enum tree_code, int,
+                                                unsigned HOST_WIDE_INT,
+                                                HOST_WIDE_INT,
+                                                unsigned HOST_WIDE_INT,
+                                                HOST_WIDE_INT,
+                                                unsigned HOST_WIDE_INT *,
+                                                HOST_WIDE_INT *,
+                                                unsigned HOST_WIDE_INT *,
+                                                HOST_WIDE_INT *));
+
 extern int operand_equal_p     PARAMS ((tree, tree, int));
+extern tree omit_one_operand   PARAMS ((tree, tree, tree));
 extern tree invert_truthvalue  PARAMS ((tree));
 
 /* In builtins.c */
@@ -3050,17 +3062,6 @@ extern void variable_section             PARAMS ((tree, int));
 enum tls_model decl_tls_model          PARAMS ((tree));
 enum symbol_visibility decl_visibility PARAMS ((tree));
 
-/* In fold-const.c */
-extern int div_and_round_double                PARAMS ((enum tree_code, int,
-                                                unsigned HOST_WIDE_INT,
-                                                HOST_WIDE_INT,
-                                                unsigned HOST_WIDE_INT,
-                                                HOST_WIDE_INT,
-                                                unsigned HOST_WIDE_INT *,
-                                                HOST_WIDE_INT *,
-                                                unsigned HOST_WIDE_INT *,
-                                                HOST_WIDE_INT *));
-
 /* In stmt.c */
 extern void emit_nop                   PARAMS ((void));
 extern void expand_computed_goto       PARAMS ((tree));