builtins.c (fold_builtin_powi): New function.
authorRichard Guenther <rguenth@gcc.gnu.org>
Thu, 10 Feb 2005 15:16:51 +0000 (15:16 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 10 Feb 2005 15:16:51 +0000 (15:16 +0000)
2005-02-10  Richard Guenther  <rguenth@gcc.gnu.org>

* builtins.c (fold_builtin_powi): New function.
(fold_builtin_1): Call it.

* gcc.dg/builtins-52.c: New testcase.

From-SVN: r94831

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-52.c [new file with mode: 0644]

index e2c251a5a5d9e3cf18217f69c6e4a70a799aef53..199bd29edf042f9740a7712cb7178b0cb7f5b89c 100644 (file)
@@ -1,3 +1,8 @@
+2005-02-10  Richard Guenther  <rguenth@gcc.gnu.org>
+
+       * builtins.c (fold_builtin_powi): New function.
+       (fold_builtin_1): Call it.
+
 2005-02-10  Steven Bosscher  <stevenb@suse.de>
 
        PR documentation/19309
index 432ecc64b7f28c4178a146b962d342b0c5caf7ca..a20624015368e5ba88404c7a394871c0de983c31 100644 (file)
@@ -152,6 +152,7 @@ static tree fold_builtin_cabs (tree, tree);
 static tree fold_builtin_sqrt (tree, tree);
 static tree fold_builtin_cbrt (tree, tree);
 static tree fold_builtin_pow (tree, tree, tree);
+static tree fold_builtin_powi (tree, tree, tree);
 static tree fold_builtin_sin (tree);
 static tree fold_builtin_cos (tree, tree, tree);
 static tree fold_builtin_tan (tree);
@@ -6948,6 +6949,53 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
   return NULL_TREE;
 }
 
+/* Fold a builtin function call to powi, powif, or powil.  Return
+   NULL_TREE if no simplification can be made.  */
+static tree
+fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
+{
+  tree arg0 = TREE_VALUE (arglist);
+  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+  if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
+    return NULL_TREE;
+
+  /* Optimize pow(1.0,y) = 1.0.  */
+  if (real_onep (arg0))
+    return omit_one_operand (type, build_real (type, dconst1), arg1);
+
+  if (host_integerp (arg1, 0))
+    {
+      HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
+
+      /* Evaluate powi at compile-time.  */
+      if (TREE_CODE (arg0) == REAL_CST
+         && ! TREE_CONSTANT_OVERFLOW (arg0))
+       {
+         REAL_VALUE_TYPE x;
+         x = TREE_REAL_CST (arg0);
+         real_powi (&x, TYPE_MODE (type), &x, c);
+         return build_real (type, x);
+       }
+
+      /* Optimize pow(x,0) = 1.0.  */
+      if (c == 0)
+       return omit_one_operand (type, build_real (type, dconst1),
+                                arg0);
+
+      /* Optimize pow(x,1) = x.  */
+      if (c == 1)
+       return arg0;
+
+      /* Optimize pow(x,-1) = 1.0/x.  */
+      if (c == -1)
+       return fold (build2 (RDIV_EXPR, type,
+                            build_real (type, dconst1), arg0));
+    }
+
+  return NULL_TREE;
+}
+
 /* A subroutine of fold_builtin to fold the various exponent
    functions.  EXP is the CALL_EXPR of a call to a builtin function.
    VALUE is the value which will be raised to a power.  */
@@ -7969,6 +8017,11 @@ fold_builtin_1 (tree exp, bool ignore)
     case BUILT_IN_POWL:
       return fold_builtin_pow (fndecl, arglist, type);
 
+    case BUILT_IN_POWI:
+    case BUILT_IN_POWIF:
+    case BUILT_IN_POWIL:
+      return fold_builtin_powi (fndecl, arglist, type);
+
     case BUILT_IN_INF:
     case BUILT_IN_INFF:
     case BUILT_IN_INFL:
index b73d9472a8d433fa221a0142c067e6bdc14110ac..6e7dc97e434194bead0651281642d4dce51aa61e 100644 (file)
@@ -1,3 +1,7 @@
+2005-02-10  Richard Guenther  <rguenth@gcc.gnu.org>
+
+       * gcc.dg/builtins-52.c: New testcase.
+
 2005-02-10  Jakub Jelinek  <jakub@redhat.com>
 
        PR c/19342
diff --git a/gcc/testsuite/gcc.dg/builtins-52.c b/gcc/testsuite/gcc.dg/builtins-52.c
new file mode 100644 (file)
index 0000000..684fd66
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do link } */
+/* { dg-options "-ffast-math" } */
+
+extern void link_error(void);
+
+void test(double x, int n)
+{
+  if (__builtin_powi(x,-1.0) != 1.0/x)
+    link_error ();
+  if (__builtin_powi(x,0.0) != 1.0)
+    link_error ();
+  if (__builtin_powi(x,1.0) != x)
+    link_error ();
+  if (__builtin_powi(1.0,n) != 1.0)
+    link_error ();
+}
+
+int main()
+{
+  test(7.3, 2);
+  return 0;
+}
+