This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch, fortran] Simplify (-1.0)**i


Hello world,

the attached patch replaces (-1.0)**i with (in C language)
(i & 1) == 0 ? 1.0 : 1.0, see PR 57073.

I tried doing it in the middle end, see the PR of where these
approaches failed.  So, rather than not doing the optimization
at all, I would rather do it in the Fortran front end.

If somebody jumps in with a middle-end solution that works, I
would withdraw this patch.

Regression-tested on trunk.  OK?

	Thomas

2013-05-19  Thomas Koenig  <tkoenig@gcc.gnu.org>

        PR fortran/57073
        * trans-expr.c:  Simplify (-1.0)**i to (i & 1) == 0 ? 1.0 : -1.0.

2013-05-19  Thomas Koenig  <tkoenig@gcc.gnu.org>

        PR fortran/57073
        * gfortran.dg/power_6.f90:  New test.
Index: trans-expr.c
===================================================================
--- trans-expr.c	(Revision 199050)
+++ trans-expr.c	(Arbeitskopie)
@@ -2110,18 +2110,41 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
   gfc_se lse;
   gfc_se rse;
   tree fndecl = NULL;
+  gfc_expr *op1, *op2;
 
+  op1 = expr->value.op.op1;
+  op2 = expr->value.op.op2;
+
   gfc_init_se (&lse, se);
-  gfc_conv_expr_val (&lse, expr->value.op.op1);
+  gfc_conv_expr_val (&lse, op1);
   lse.expr = gfc_evaluate_now (lse.expr, &lse.pre);
   gfc_add_block_to_block (&se->pre, &lse.pre);
 
   gfc_init_se (&rse, se);
-  gfc_conv_expr_val (&rse, expr->value.op.op2);
+  gfc_conv_expr_val (&rse, op2);
   gfc_add_block_to_block (&se->pre, &rse.pre);
 
-  if (expr->value.op.op2->ts.type == BT_INTEGER
-      && expr->value.op.op2->expr_type == EXPR_CONSTANT)
+  if (op1->ts.type == BT_REAL && op1->expr_type == EXPR_CONSTANT
+      && op2->expr_type != EXPR_CONSTANT
+      && mpfr_cmp_si (op1->value.real, -1L) == 0)
+    {
+      tree tmp, type_op1, type_op2;
+
+      type_op1 = TREE_TYPE (lse.expr);
+      type_op2 = TREE_TYPE (rse.expr);
+
+      tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type_op2,
+			     rse.expr, build_int_cst (type_op2, 1));
+      tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+			     tmp, build_int_cst (type_op2, 0));
+      se->expr = fold_build3_loc (input_location, COND_EXPR, type_op1, tmp,
+				  build_real (type_op1, dconst1),
+				  build_real (type_op1, dconstm1));
+      return;
+    }
+
+  if (op2->ts.type == BT_INTEGER
+      && op2->expr_type == EXPR_CONSTANT)
     if (gfc_conv_cst_int_power (se, lse.expr, rse.expr))
       return;
 
@@ -2134,11 +2157,11 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
   res_ikind_1 = -1;
   res_ikind_2 = -1;
 
-  kind = expr->value.op.op1->ts.kind;
-  switch (expr->value.op.op2->ts.type)
+  kind = op1->ts.kind;
+  switch (op2->ts.type)
     {
     case BT_INTEGER:
-      ikind = expr->value.op.op2->ts.kind;
+      ikind = op2->ts.kind;
       switch (ikind)
 	{
 	case 1:
@@ -2166,7 +2189,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
 	{
 	case 1:
 	case 2:
-	  if (expr->value.op.op1->ts.type == BT_INTEGER)
+	  if (op1->ts.type == BT_INTEGER)
 	    {
 	      lse.expr = convert (gfc_int4_type_node, lse.expr);
 	      res_ikind_1 = kind;
@@ -2195,7 +2218,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
 	  gcc_unreachable ();
 	}
 
-      switch (expr->value.op.op1->ts.type)
+      switch (op1->ts.type)
 	{
 	case BT_INTEGER:
 	  if (kind == 3) /* Case 16 was not handled properly above.  */
! { dg-do run }
! { dg-options "-fdump-tree-original" }
! PR 57073 - test that (-1.0)**n is transormed into n & 1 == 0 ? 1.0 : -1.0
program main
  integer :: i
  character(len=10) :: c
  real(8) :: a
  c = '-1.0'
  read (unit=c,fmt=*) a
  do i=-3,3
     if ((-1.0_8)**i /= a**i) call abort
  end do
end program main
! { dg-final { scan-tree-dump-times "__builtin_powi" 1 "original" } }
! { dg-final { scan-tree-dump-times "i & 1" 1 "original" } }
! { dg-final { cleanup-tree-dump "original" } }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]