From: Thomas Koenig Date: Sat, 22 Dec 2018 20:16:22 +0000 (+0000) Subject: backport: re PR fortran/85544 (ICE in gfc_conv_scalarized_array_ref, at fortran/trans... X-Git-Tag: releases/gcc-7.5.0~706 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e5003db5f1ecf35719831fb5fe2869790c01d08;p=thirdparty%2Fgcc.git backport: re PR fortran/85544 (ICE in gfc_conv_scalarized_array_ref, at fortran/trans-array.c:3385) 2018-12-22 Thomas Koenig Backport from trunk PR fortran/85544 * frontend-passes.c (optimize_power): Remove. (optimize_op): Remove call to optimize_power. * trans-expr.c (gfc_conv_power_op): Handle cases of 1**integer, (2|4|8|16) ** integer and (-1) ** integer. 2018-12-22 Thomas Koenig Backport from trunk PR fortran/85544 * gfortran.dg/power_7.f90: New test. From-SVN: r267360 --- diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 42e4ca02adee..3d391b0680ea 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2018-12-22 Thomas Koenig + + Backport from trunk + PR fortran/85544 + * frontend-passes.c (optimize_power): Remove. + (optimize_op): Remove call to optimize_power. + * trans-expr.c (gfc_conv_power_op): Handle cases of 1**integer, + (2|4|8|16) ** integer and (-1) ** integer. + 2018-12-21 Steven G. Kargl PR fortran/88169 @@ -9,7 +18,7 @@ PR fortran/88138 * decl.c (variable_decl): Check that a derived isn't being assigned an incompatible entity in an initialization. - + 2018-12-11 Steven G. Kargl PR fortran/88155 diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index 7c83a882ecc1..ec2e999f12b2 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -1422,84 +1422,6 @@ combine_array_constructor (gfc_expr *e) return true; } -/* Change (-1)**k into 1-ishift(iand(k,1),1) and - 2**k into ishift(1,k) */ - -static bool -optimize_power (gfc_expr *e) -{ - gfc_expr *op1, *op2; - gfc_expr *iand, *ishft; - - if (e->ts.type != BT_INTEGER) - return false; - - op1 = e->value.op.op1; - - if (op1 == NULL || op1->expr_type != EXPR_CONSTANT) - return false; - - if (mpz_cmp_si (op1->value.integer, -1L) == 0) - { - gfc_free_expr (op1); - - op2 = e->value.op.op2; - - if (op2 == NULL) - return false; - - iand = gfc_build_intrinsic_call (current_ns, GFC_ISYM_IAND, - "_internal_iand", e->where, 2, op2, - gfc_get_int_expr (e->ts.kind, - &e->where, 1)); - - ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT, - "_internal_ishft", e->where, 2, iand, - gfc_get_int_expr (e->ts.kind, - &e->where, 1)); - - e->value.op.op = INTRINSIC_MINUS; - e->value.op.op1 = gfc_get_int_expr (e->ts.kind, &e->where, 1); - e->value.op.op2 = ishft; - return true; - } - else if (mpz_cmp_si (op1->value.integer, 2L) == 0) - { - gfc_free_expr (op1); - - op2 = e->value.op.op2; - if (op2 == NULL) - return false; - - ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT, - "_internal_ishft", e->where, 2, - gfc_get_int_expr (e->ts.kind, - &e->where, 1), - op2); - *e = *ishft; - return true; - } - - else if (mpz_cmp_si (op1->value.integer, 1L) == 0) - { - op2 = e->value.op.op2; - if (op2 == NULL) - return false; - - gfc_free_expr (op1); - gfc_free_expr (op2); - - e->expr_type = EXPR_CONSTANT; - e->value.op.op1 = NULL; - e->value.op.op2 = NULL; - mpz_init_set_si (e->value.integer, 1); - /* Typespec and location are still OK. */ - return true; - } - - return false; -} - /* Recursive optimization of operators. */ static bool @@ -1560,9 +1482,6 @@ optimize_op (gfc_expr *e) case INTRINSIC_DIVIDE: return combine_array_constructor (e) || changed; - case INTRINSIC_POWER: - return optimize_power (e); - default: break; } diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 134f8ea50677..55cd3bb6c3f5 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -2987,6 +2987,83 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr) if (gfc_conv_cst_int_power (se, lse.expr, rse.expr)) return; + if (INTEGER_CST_P (lse.expr) + && TREE_CODE (TREE_TYPE (rse.expr)) == INTEGER_TYPE) + { + wide_int wlhs = lse.expr; + HOST_WIDE_INT v; + v = wlhs.to_shwi (); + if (v == 1) + { + /* 1**something is always 1. */ + se->expr = build_int_cst (TREE_TYPE (lse.expr), 1); + return; + } + else if (v == 2 || v == 4 || v == 8 || v == 16) + { + /* 2**n = 1<expr = fold_build3_loc (input_location, COND_EXPR, type, cond2, + build_int_cst (type, 0), cond); + return; + } + else if (v == -1) + { + /* (-1)**n is 1 - ((n & 1) << 1) */ + tree type; + tree tmp; + + type = TREE_TYPE (lse.expr); + tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, + rse.expr, build_int_cst (type, 1)); + tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type, + tmp, build_int_cst (type, 1)); + tmp = fold_build2_loc (input_location, MINUS_EXPR, type, + build_int_cst (type, 1), tmp); + se->expr = tmp; + return; + } + } + gfc_int4_type_node = gfc_get_int_type (4); /* In case of integer operands with kinds 1 or 2, we call the integer kind 4 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c0c3a5ffdf77..fd74e371c437 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-12-22 Thomas Koenig + + Backport from trunk + PR fortran/85544 + * gfortran.dg/power_7.f90: New test. + 2018-12-21 Steven G. Kargl PR fortran/88169 diff --git a/gcc/testsuite/gfortran.dg/power_7.f90 b/gcc/testsuite/gfortran.dg/power_7.f90 new file mode 100644 index 000000000000..5b6b291b561d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/power_7.f90 @@ -0,0 +1,27 @@ +! { dg-do run } +! { dg-additional-options "-fdump-tree-original" } +! PR 85544 - this used to ICE. +program p + integer, parameter :: na = -3, ne = 10 + integer :: i, a(na:ne), b(na:ne) + integer :: v + a = [(i, i=na, ne)] + b = [2**a] + if (any (b /= [0,0,0,1,2,4,8,16,32,64,128,256,512,1024])) stop 1 + b = [1**a] + if (any (b /= 1)) stop 2 + b = [(-1)**a] + if (any (b /= [-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1]) )stop 3 + b = [8**a] + if (any (b /= [0,0,0,1,8,64,512,4096,32768,262144,2097152,16777216,& + 134217728,1073741824])) stop 4 + b = [4**a] + if (any (b /= [0,0,0,1,4,16,64,256,1024,4096,16384,65536,262144,1048576])) stop 5 + + v = 1 + do i=1,6 + v = v * 16 + if (v /= 16**i) stop 6 + end do + end program p +! { dg-final { scan-tree-dump-not "_gfortran_pow" "original" } }