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]

Re: [PATCH, fortran, 4.5] Fix constant folding of noninteger exponents.


Hi Steve,

Generally, I confess to not taking much notice of arithmetic related
patches.  Not because I am not interested but because I do not have
the necessary expertise.  Hence, I ignored this one.

However, on seeing your remark in the new regression PR29292, reported
by Richard Guenther (thanks), I decided I should take a look-see:-)

First your patch looks fine to me - the usual sgk quality stamp everywhere.

Second, it bootstraps and regtests fine on FC9/x86_64.

Third, as you surmised, it fixes the regression.

Fourth, being a regression and given the present hiatus - OK for trunk.

Many thanks

Paul

PS The ICE occurs at a place in gfc_conv_array_initializer that I have
often eyed in the past.  I wonder if upon detecting and EXP_OP that is
a constant expression that we should not convert it?  With the best
will in the world, some things might not simplify but still be
detected if outside of the standard.  This would be a useful safety
net that would have fixed this bug.

On Mon, Jan 19, 2009 at 1:31 AM, Steve Kargl
<sgk@troutmask.apl.washington.edu> wrote:
> The attached patch has been regression tested on i386-*-freebsd
> and x86_64-*-freebsd. ?There were no regressions.
>
> This patch is not obvious. :-O
>
> The original PR fortran/388232 was for a program of the form
>
> program z
> ? x = (-2.e0)**3.e0
> end program z
>
> where the Fortran 95 (page 97) and 2003 standards have
>
> ? "Raising a negative-valued primary of type real to a real power is
> ? ?prohibited."
>
> The patch morphed into something that (partially) also addressed
> PR fortran/38822. ?I'll get back to that in a moment.
>
> Constant folding occurs before the checking of an initialization
> expression for conformance, and AFAICT there is no way to tell
> if gfortran is currently parsing an initialization expression.
> The crux of the problem comes from page 94 of the F95 standard:
>
> ? "An initialization expression is a constant expression in which
> ? ?the exponentiation operation is permitted only with an integer
> ? ?power, and ..."
>
> The "in which ..." clause has been removed in Fortran 2003. ?gfortran
> currently only enforces this checking with -std=f95.
>
> kargl[11] cat > a.f90
> program z
> ? real :: x = 2.e0**3.e0
> end program z
> kargl[12] gfc43 -o z a.f90
> kargl[13] gfc43 -o z -std=f95 a.f90
> a.f90:2.25:
>
> ? real :: x = 2.e0**3.e0
> ? ? ? ? ? ? ? ? ? ? ? ?1
> Error: Fortran 2003: Noninteger exponent in an initialization expression at (1)
>
> So, gfortran appears to be doing what one would want. ?Unfortnately, this
> isn't the case. ?Consider
>
> kargl[19] cat a.f90
> program z
> ? real :: x = transfer(2.e0**3.e0, 1)
> end program z
> kargl[20] gfc43 -o -std=f95 z a.f90
> f951: internal compiler error: in gfc_target_encode_expr, at
> fortran/target-memory.c:235
>
> There are clearly 2 problems here. ?First, there is an ICE. ?Second,
> we do not get a warning/error for the non-integer exponent. ?The cause
> of the ICE is that the gfortran frontend does not constant fold the
> above initialization express. ?It builds a runtime expression, which
> the middle-end would eventually fold if the 2.e0**3.e0 wasn't the
> argument to TRANSFER. ?The presence of the runtime expression is
> the origins of the ICE. ?arith.c(eval_intrinsics) contains
>
> ?/* Try to combine the operators. ?*/
> ?if (op == INTRINSIC_POWER && op2->ts.type != BT_INTEGER)
> ? ?goto runtime;
>
> If we remove this restriction to allow the FE to constant fold, we
> open up a Pandora's box because the F95 restrictions can only be
> detected at a lower level in arith.c(gfc_arith_power). ?Note, I've
> renamed gfc_arith_power to arith_pow. ?This function normally returns
> an error code that is used to report errors. ?None of the current
> error codes adequately describe the error. ?So, I've introduced
> ARITH_PROHIBIT. ?I've used ARITH_PROHIBIT to detect both restrictions.
>
> kargl[25] gfc4x -o z -std=f95 a.f90
> a.f90:2.34:
>
> ? real :: x = transfer(2.e0**3.e0, 1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1
> Error: Fortran 2003: Noninteger exponent in an initialization expression at (1)
> a.f90:3.8:
>
> ? y = (-2.0)**3.e0
> ? ? ? ?1
> Error: Raising a negative REAL at (1) to a REAL power is prohibited
>
> The careful reader will note that expression for y is not flagged
> as having an non-integer exponent. ?To accomplish, I've added a global
> flag init_flag that is set to true ?when gfc_match_init_expr is entered
> and cleared before returning.
>
> Now back to PR fortran/38822, a very bare bone code fragment is
>
> kargl[36] gfc4x -o z -std=f95 a.f90
> kargl[37] cat a.f90
> program z
> ? real x(0*transfer(2.e0**3.e0, 1) + 2)
> end program z
> kargl[38] gfc4x -o z -std=f95 a.f90
>
> Notice that the noninteger exponent restriction also applied to
> specification statements. ?I haven't found a patch to fix this
> yet.
>
> Enjoy.
>
> 2009-01-17 ?Steven G. Kargl ?<kargl@gcc.gnu.org>
>
> ? ? ? ?PR fortran/38823
> ? ? ? ?* gfortran.dg/power1.f90: New test.
>
> 2009-01-17 ?Steven G. Kargl ?<kargl@gcc.gnu.org>
>
> ? ? ? ?PR fortran/38823
> ? ? ? ?* gfortran.h: Add ARITH_PROHIBIT to arith enum.
> ? ? ? ?expr.c (gfc_match_init_expr): Add global variable init_flag to
> ? ? ? ?flag matching an initialization expression.
> ? ? ? ?(check_intrinsic_op): Move no longer reachable error message to ...
> ? ? ? ?* arith.c (arith_power): ... here. ?Remove gfc_ prefix in
> ? ? ? ?gfc_arith_power. ?Use init_flag. ?Allow constant folding of x**y
> ? ? ? ?when y is REAL or COMPLEX.
> ? ? ? ?(eval_intrinsic): Remove restriction that y in x**y must be INTEGER
> ? ? ? ?for constant folding.
> ? ? ? ?* gfc_power: Update gfc_arith_power to arith_power
> --
> Steve
>



-- 
The knack of flying is learning how to throw yourself at the ground and miss.
       --Hitchhikers Guide to the Galaxy


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