builtins.c (fold_builtin_cproj): Fold more cases.
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>
Tue, 20 Apr 2010 20:12:47 +0000 (20:12 +0000)
committerKaveh Ghazi <ghazi@gcc.gnu.org>
Tue, 20 Apr 2010 20:12:47 +0000 (20:12 +0000)
        * builtins.c (fold_builtin_cproj): Fold more cases.

testsuite:
        * gcc.dg/torture/builtin-cproj-1.c: Test more cases.

From-SVN: r158574

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/builtin-cproj-1.c

index 72c4c9a43cdfb5c5067faccb0acfcbe550d8fda1..cdb7c2b8ad6bdb20f22a54e5401dd0f3b326c710 100644 (file)
@@ -1,3 +1,7 @@
+2010-04-20  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * builtins.c (fold_builtin_cproj): Fold more cases.
+
 2010-04-20  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * builtins.c (build_complex_cproj, fold_builtin_cproj): New.
index 8c3c8e0f4be21d2d89dd43eebfdcf4c91648e61a..997c13a5505f2f771af7f77078155d5d29845c93 100644 (file)
@@ -7082,6 +7082,33 @@ fold_builtin_cproj (location_t loc, tree arg, tree type)
       else
        return arg;
     }
+  else if (TREE_CODE (arg) == COMPLEX_EXPR)
+    {
+      tree real = TREE_OPERAND (arg, 0);
+      tree imag = TREE_OPERAND (arg, 1);
+
+      STRIP_NOPS (real);
+      STRIP_NOPS (imag);
+      
+      /* If the real part is inf and the imag part is known to be
+        nonnegative, return (inf + 0i).  Remember side-effects are
+        possible in the imag part.  */
+      if (TREE_CODE (real) == REAL_CST
+         && real_isinf (TREE_REAL_CST_PTR (real))
+         && tree_expr_nonnegative_p (imag))
+       return omit_one_operand_loc (loc, type,
+                                    build_complex_cproj (type, false),
+                                    arg);
+      
+      /* If the imag part is inf, return (inf+I*copysign(0,imag)).
+        Remember side-effects are possible in the real part.  */
+      if (TREE_CODE (imag) == REAL_CST
+         && real_isinf (TREE_REAL_CST_PTR (imag)))
+       return
+         omit_one_operand_loc (loc, type,
+                               build_complex_cproj (type, TREE_REAL_CST_PTR
+                                                    (imag)->sign), arg);
+    }
 
   return NULL_TREE;
 }
index c2082071b29a429236bf6d31a49e877ec39ec9af..e689381a4e5d0002385cd089310d3f1ea01efd85 100644 (file)
@@ -1,3 +1,7 @@
+2010-04-20  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * gcc.dg/torture/builtin-cproj-1.c: Test more cases.
+
 2010-04-20  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.dg/torture/builtin-cproj-1.c: New.
index 24540310b6674e345b740944d1935049a1e9a4c5..31cd5874ffba59e612a4bffe114a5db5c6240a72 100644 (file)
@@ -44,7 +44,80 @@ extern void link_error(int);
     link_error(__LINE__); \
 } while (0)
 
-void foo (void)
+/* Test that cproj(X + I*INF) -> (ZERO + INF), where ZERO is +-0i.
+   NEG is either blank or a minus sign when ZERO is negative.  */
+#define TEST_IMAG_INF(NEG,ZERO) do { \
+  if (CPROJF(f+I*NEG INF) != ZERO+INF \
+      || CKSGN_I (CPROJF(f+I*NEG INF), ZERO+INF)) \
+    link_error(__LINE__); \
+  if (CPROJ(d+I*NEG INF) != ZERO+INF \
+      || CKSGN_I (CPROJ(d+I*NEG INF), ZERO+INF)) \
+    link_error(__LINE__); \
+  if (CPROJL(ld+I*NEG INF) != ZERO+INF \
+      || CKSGN_I (CPROJL(ld+I*NEG INF), ZERO+INF)) \
+    link_error(__LINE__); \
+} while (0)
+
+/* Like TEST_IMAG_INF, but check that side effects are honored.  */
+#define TEST_IMAG_INF_SIDE_EFFECT(NEG,ZERO) do { \
+  int side = 4; \
+  if (CPROJF(++side+I*NEG INF) != ZERO+INF \
+      || CKSGN_I (CPROJF(++side+I*NEG INF), ZERO+INF)) \
+    link_error(__LINE__); \
+  if (CPROJ(++side+I*NEG INF) != ZERO+INF \
+      || CKSGN_I (CPROJ(++side+I*NEG INF), ZERO+INF)) \
+    link_error(__LINE__); \
+  if (CPROJL(++side+I*NEG INF) != ZERO+INF \
+      || CKSGN_I (CPROJL(++side+I*NEG INF), ZERO+INF)) \
+    link_error(__LINE__); \
+  if (side != 10) \
+    link_error(__LINE__); \
+} while (0)
+
+/* Test that cproj(INF, POSITIVE) -> INF+0i.  NEG is either blank or a
+   minus sign to test negative INF.  */
+#define TEST_REAL_INF(NEG) do { \
+  __real cf = NEG INF; \
+  __imag cf = (x ? 4 : 5); \
+  if (CPROJF(cf) != INF \
+      || CKSGN_I (CPROJF(cf), INF)) \
+    link_error(__LINE__); \
+  __real cd = NEG INF; \
+  __imag cd = (x ? 4 : 5); \
+  if (CPROJ(cd) != INF \
+      || CKSGN_I (CPROJ(cd), INF)) \
+    link_error(__LINE__); \
+  __real cld = NEG INF; \
+  __imag cld = (x ? 4 : 5); \
+  if (CPROJL(cld) != INF \
+      || CKSGN_I (CPROJL(cld), INF)) \
+    link_error(__LINE__); \
+} while (0)
+
+/* Like TEST_REAL_INF, but check that side effects are honored.  */
+#define TEST_REAL_INF_SIDE_EFFECT(NEG) do { \
+  int side = -9; \
+  __real cf = NEG INF; \
+  __imag cf = (x ? 4 : 5); \
+  if (CPROJF((++side,cf)) != INF \
+      || CKSGN_I (CPROJF((++side,cf)), INF)) \
+    link_error(__LINE__); \
+  __real cd = NEG INF; \
+  __imag cd = (x ? 4 : 5); \
+  if (CPROJ((++side,cd)) != INF \
+      || CKSGN_I (CPROJ((++side,cd)), INF)) \
+    link_error(__LINE__); \
+  __real cld = NEG INF; \
+  __imag cld = (x ? 4 : 5); \
+  if (CPROJL((++side,cld)) != INF \
+      || CKSGN_I (CPROJL((++side,cld)), INF)) \
+    link_error(__LINE__); \
+  if (side != -3) \
+    link_error(__LINE__); \
+} while (0)
+
+void foo (_Complex long double cld, _Complex double cd, _Complex float cf,
+         long double ld, double d, float f, int x)
 {
   TEST_CST_INF (INF+0I, 0);
   TEST_CST_INF (INF-0I, -0.FI);
@@ -79,6 +152,20 @@ void foo (void)
   TEST_CST (-22+3I);
   TEST_CST (-22-3I);
 
+  TEST_IMAG_INF (,0.FI);
+  TEST_IMAG_INF (-,-0.FI);
+
+#ifdef __OPTIMIZE__
+  TEST_REAL_INF( );
+  TEST_REAL_INF(-);
+  
+  TEST_IMAG_INF_SIDE_EFFECT (,0.FI);
+  TEST_IMAG_INF_SIDE_EFFECT (-,-0.FI);
+
+  TEST_REAL_INF_SIDE_EFFECT( );
+  TEST_REAL_INF_SIDE_EFFECT(-);
+#endif
+
   return;
 }