This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran 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]

[gfortran] Compute x**(-n) as (1/x)**n


The following change, which I bootstrapped on powerpc-unknown-linux-gnu (C and f95) without regressions, leads the Fortran front-end to generate expressions x**(-n) with n constant as if they were written (1/x)**n.

This will enable more opportunities for CSE in case multiple powers of the same base are needed in an expression. E.g., the following:

function force(d)
force = d**(-2) + d**(-6) + d**(-8) + d**(-12)
end

will lead to the following floating point operations (when using -ffast-math, whereas the current method needs four divisions and uses no fused multiply-add.

        fdivs 1,1,13
        fmuls 0,1,1
        fmuls 1,1,0
        fmuls 13,0,0
        fmuls 1,1,1
        fadds 0,0,1
        fmadds 13,13,13,0
        fmadds 1,1,1,13

Paul, is this OK ?

--
Toon Moene - mailto:toon@moene.indiv.nluug.nl - phoneto: +31 346 214290
Saturnushof 14, 3738 XG  Maartensdijk, The Netherlands
Maintainer, GNU Fortran 77: http://gcc.gnu.org/onlinedocs/g77_news.html
GNU Fortran 95: http://gcc.gnu.org/fortran/ (under construction)
2004-06-08  Toon Moene  <toon@moene.indiv.nluug.nl>

	* trans-expr.c (gfc_conv_cst_int_power): Compute
	x**(-n) by converting it to (1/x)**n instead of
	1/x**n.

*** trans-expr.c.orig	Sat Jun  5 13:45:07 2004
--- trans-expr.c	Sat Jun  5 13:48:38 2004
*************** gfc_conv_cst_int_power (gfc_se * se, tre
*** 526,538 ****
  
    memset (vartmp, 0, sizeof (vartmp));
    vartmp[1] = lhs;
- 
-   se->expr = gfc_conv_powi (se, n, vartmp);
    if (sgn == -1)
      {
        tmp = gfc_build_const (type, integer_one_node);
!       se->expr = build (RDIV_EXPR, type, tmp, se->expr);
      }
    return 1;
  }
  
--- 526,539 ----
  
    memset (vartmp, 0, sizeof (vartmp));
    vartmp[1] = lhs;
    if (sgn == -1)
      {
        tmp = gfc_build_const (type, integer_one_node);
!       vartmp[1] = build (RDIV_EXPR, type, tmp, vartmp[1]);
      }
+ 
+   se->expr = gfc_conv_powi (se, n, vartmp);
+ 
    return 1;
  }
  

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