[PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]
Hi! On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits static real(kind=4) a[0] = {[0 ... -1]=2.0e+0}; That is an invalid RANGE_EXPR where the maximum is smaller than the minimum. The following patch fixes that. If TYPE_MAX_VALUE is smaller than TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer, if the two are equal, we don't need to bother with a RANGE_EXPR and can just use that INTEGER_CST as the index and finally for the 2+ values in the range it uses a RANGE_EXPR as before. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2022-03-25 Jakub Jelinek PR fortran/103691 * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is smaller than TYPE_MIN_VALUE (i.e. empty array), throw the initializer on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just the TYPE_MIN_VALUE as index instead of RANGE_EXPR. --- gcc/fortran/trans-array.cc.jj 2022-02-04 14:36:55.113603791 +0100 +++ gcc/fortran/trans-array.cc 2022-03-24 16:14:58.334498775 +0100 @@ -6267,10 +6267,17 @@ gfc_conv_array_initializer (tree type, g else gfc_conv_structure (&se, expr, 1); - CONSTRUCTOR_APPEND_ELT (v, build2 (RANGE_EXPR, gfc_array_index_type, -TYPE_MIN_VALUE (TYPE_DOMAIN (type)), -TYPE_MAX_VALUE (TYPE_DOMAIN (type))), - se.expr); + if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), + TYPE_MIN_VALUE (TYPE_DOMAIN (type + break; + else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), + TYPE_MAX_VALUE (TYPE_DOMAIN (type + range = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); + else + range = build2 (RANGE_EXPR, gfc_array_index_type, + TYPE_MIN_VALUE (TYPE_DOMAIN (type)), + TYPE_MAX_VALUE (TYPE_DOMAIN (type))); + CONSTRUCTOR_APPEND_ELT (v, range, se.expr); break; case EXPR_ARRAY: Jakub
Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]
On 25.03.22 09:57, Jakub Jelinek via Fortran wrote: On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits static real(kind=4) a[0] = {[0 ... -1]=2.0e+0}; That is an invalid RANGE_EXPR where the maximum is smaller than the minimum. The following patch fixes that. If TYPE_MAX_VALUE is smaller than TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer, if the two are equal, we don't need to bother with a RANGE_EXPR and can just use that INTEGER_CST as the index and finally for the 2+ values in the range it uses a RANGE_EXPR as before. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? LGTM – thanks for taking care of Fortran patches and regressions. 2022-03-25 Jakub Jelinek PR fortran/103691 * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is smaller than TYPE_MIN_VALUE (i.e. empty array), throw the initializer on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just the TYPE_MIN_VALUE as index instead of RANGE_EXPR. I am not sure whether "throw the initializer on the floor" is the best wording for a changelog. I think I prefer a wording like "ignore the initializer" or another less idiomatic expression. And I think a ';' before the second 'if' also increases readability. Tobias --- gcc/fortran/trans-array.cc.jj 2022-02-04 14:36:55.113603791 +0100 +++ gcc/fortran/trans-array.cc2022-03-24 16:14:58.334498775 +0100 @@ -6267,10 +6267,17 @@ gfc_conv_array_initializer (tree type, g else gfc_conv_structure (&se, expr, 1); - CONSTRUCTOR_APPEND_ELT (v, build2 (RANGE_EXPR, gfc_array_index_type, - TYPE_MIN_VALUE (TYPE_DOMAIN (type)), - TYPE_MAX_VALUE (TYPE_DOMAIN (type))), - se.expr); + if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), +TYPE_MIN_VALUE (TYPE_DOMAIN (type + break; + else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), +TYPE_MAX_VALUE (TYPE_DOMAIN (type + range = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); + else + range = build2 (RANGE_EXPR, gfc_array_index_type, + TYPE_MIN_VALUE (TYPE_DOMAIN (type)), + TYPE_MAX_VALUE (TYPE_DOMAIN (type))); + CONSTRUCTOR_APPEND_ELT (v, range, se.expr); break; case EXPR_ARRAY: Jakub - Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]
On Fri, Mar 25, 2022 at 11:13 AM Tobias Burnus wrote: > > On 25.03.22 09:57, Jakub Jelinek via Fortran wrote: > > On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits > >static real(kind=4) a[0] = {[0 ... -1]=2.0e+0}; > > That is an invalid RANGE_EXPR where the maximum is smaller than the minimum. > > > > The following patch fixes that. If TYPE_MAX_VALUE is smaller than > > TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer, > > if the two are equal, we don't need to bother with a RANGE_EXPR and > > can just use that INTEGER_CST as the index and finally for the 2+ values > > in the range it uses a RANGE_EXPR as before. > > > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > LGTM – thanks for taking care of Fortran patches and regressions. > > > 2022-03-25 Jakub Jelinek > > > > PR fortran/103691 > > * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is > > smaller than TYPE_MIN_VALUE (i.e. empty array), throw the initializer > > on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just > > the TYPE_MIN_VALUE as index instead of RANGE_EXPR. > > I am not sure whether "throw the initializer on the floor" is the best wording > for a changelog. I think I prefer a wording like "ignore the initializer" or > another less idiomatic expression. And I think a ';' before the second 'if' > also increases readability. Can there be side-effects in those initializer elements in Fortran? Richard. > Tobias > > > --- gcc/fortran/trans-array.cc.jj 2022-02-04 14:36:55.113603791 +0100 > > +++ gcc/fortran/trans-array.cc2022-03-24 16:14:58.334498775 +0100 > > @@ -6267,10 +6267,17 @@ gfc_conv_array_initializer (tree type, g > > else > > gfc_conv_structure (&se, expr, 1); > > > > - CONSTRUCTOR_APPEND_ELT (v, build2 (RANGE_EXPR, gfc_array_index_type, > > - TYPE_MIN_VALUE (TYPE_DOMAIN (type)), > > - TYPE_MAX_VALUE (TYPE_DOMAIN (type))), > > - se.expr); > > + if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), > > +TYPE_MIN_VALUE (TYPE_DOMAIN (type > > + break; > > + else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), > > +TYPE_MAX_VALUE (TYPE_DOMAIN (type > > + range = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); > > + else > > + range = build2 (RANGE_EXPR, gfc_array_index_type, > > + TYPE_MIN_VALUE (TYPE_DOMAIN (type)), > > + TYPE_MAX_VALUE (TYPE_DOMAIN (type))); > > + CONSTRUCTOR_APPEND_ELT (v, range, se.expr); > > break; > > > > case EXPR_ARRAY: > > > > Jakub > > > - > Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 > München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas > Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht > München, HRB 106955
Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]
On Fri, Mar 25, 2022 at 12:16:40PM +0100, Richard Biener wrote: > On Fri, Mar 25, 2022 at 11:13 AM Tobias Burnus > wrote: > > > > On 25.03.22 09:57, Jakub Jelinek via Fortran wrote: > > > On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits > > >static real(kind=4) a[0] = {[0 ... -1]=2.0e+0}; > > > That is an invalid RANGE_EXPR where the maximum is smaller than the > > > minimum. > > > > > > The following patch fixes that. If TYPE_MAX_VALUE is smaller than > > > TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer, > > > if the two are equal, we don't need to bother with a RANGE_EXPR and > > > can just use that INTEGER_CST as the index and finally for the 2+ values > > > in the range it uses a RANGE_EXPR as before. > > > > > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > > > LGTM – thanks for taking care of Fortran patches and regressions. > > > > > 2022-03-25 Jakub Jelinek > > > > > > PR fortran/103691 > > > * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is > > > smaller than TYPE_MIN_VALUE (i.e. empty array), throw the > > > initializer > > > on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just > > > the TYPE_MIN_VALUE as index instead of RANGE_EXPR. > > > > I am not sure whether "throw the initializer on the floor" is the best > > wording > > for a changelog. I think I prefer a wording like "ignore the initializer" or > > another less idiomatic expression. And I think a ';' before the second 'if' > > also increases readability. > > Can there be side-effects in those initializer elements in Fortran? For PARAMETERs certainly not, those need to be constant. Even otherwise, this is in a routine that does /* Create a constructor from the list of elements. */ tmp = build_constructor (type, v); TREE_CONSTANT (tmp) = 1; return tmp; at the end so I wouldn't expect side-effects anywhere. Also, I think typically in the Fortran FE side-effects would go into se.pre and se.post sequences, not into se.expr, and this routine doesn't emit those se.pre/se.post sequences anywhere, so presumably it assumes they don't exist. What is the behavior with a RANGE_EXPR when one has { [0..10] = ++i; }, is that applying the side-effects 11 times or once ? Jakub
Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]
On Fri, Mar 25, 2022 at 12:34 PM Jakub Jelinek wrote: > > On Fri, Mar 25, 2022 at 12:16:40PM +0100, Richard Biener wrote: > > On Fri, Mar 25, 2022 at 11:13 AM Tobias Burnus > > wrote: > > > > > > On 25.03.22 09:57, Jakub Jelinek via Fortran wrote: > > > > On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits > > > >static real(kind=4) a[0] = {[0 ... -1]=2.0e+0}; > > > > That is an invalid RANGE_EXPR where the maximum is smaller than the > > > > minimum. > > > > > > > > The following patch fixes that. If TYPE_MAX_VALUE is smaller than > > > > TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer, > > > > if the two are equal, we don't need to bother with a RANGE_EXPR and > > > > can just use that INTEGER_CST as the index and finally for the 2+ values > > > > in the range it uses a RANGE_EXPR as before. > > > > > > > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > > > > > LGTM – thanks for taking care of Fortran patches and regressions. > > > > > > > 2022-03-25 Jakub Jelinek > > > > > > > > PR fortran/103691 > > > > * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE > > > > is > > > > smaller than TYPE_MIN_VALUE (i.e. empty array), throw the > > > > initializer > > > > on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use > > > > just > > > > the TYPE_MIN_VALUE as index instead of RANGE_EXPR. > > > > > > I am not sure whether "throw the initializer on the floor" is the best > > > wording > > > for a changelog. I think I prefer a wording like "ignore the initializer" > > > or > > > another less idiomatic expression. And I think a ';' before the second > > > 'if' > > > also increases readability. > > > > Can there be side-effects in those initializer elements in Fortran? > > For PARAMETERs certainly not, those need to be constant. > Even otherwise, this is in a routine that does > /* Create a constructor from the list of elements. */ > tmp = build_constructor (type, v); > TREE_CONSTANT (tmp) = 1; > return tmp; > at the end so I wouldn't expect side-effects anywhere. Ah, didn't see that. > Also, I think typically in the Fortran FE side-effects would go into > se.pre and se.post sequences, not into se.expr, and this routine > doesn't emit those se.pre/se.post sequences anywhere, so presumably it > assumes they don't exist. > > What is the behavior with a RANGE_EXPR when one has { [0..10] = ++i; }, > is that applying the side-effects 11 times or once ? 11 times is what is documented. Richard. > > > Jakub >
Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]
On Fri, Mar 25, 2022 at 01:13:06PM +0100, Richard Biener wrote: > > Also, I think typically in the Fortran FE side-effects would go into > > se.pre and se.post sequences, not into se.expr, and this routine > > doesn't emit those se.pre/se.post sequences anywhere, so presumably it > > assumes they don't exist. > > > > What is the behavior with a RANGE_EXPR when one has { [0..10] = ++i; }, > > is that applying the side-effects 11 times or once ? > > 11 times is what is documented. Then [0..-1] = ++i should be 0 times the side-effect. Jakub
[PATCH] Fortran: Fix clause splitting for OMP masked taskloop directive
I ran into this bug in the handling of clauses on the combined "masked taskloop" OMP directive when I was working on something else. The fix turned out to be a 1-liner. OK for trunk? -Sandracommit 17c4fa0bd97c070945004095a06fb7d9e91869e3 Author: Sandra Loosemore Date: Wed Mar 23 18:45:25 2022 -0700 Fortran: Fix clause splitting for OMP masked taskloop directive This patch fixes an obvious coding goof that caused all clauses for the combined OMP masked taskloop directive to be discarded. gcc/fortran/ * trans-openmp.cc (gfc_split_omp_clauses): Fix mask for EXEC_OMP_MASKED_TASKLOOP. gcc/testsuite/ * gfortran.dg/gomp/masked-taskloop.f90: New. diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 101924f..25dde82 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -5998,7 +5998,7 @@ gfc_split_omp_clauses (gfc_code *code, innermost = GFC_OMP_SPLIT_DO; break; case EXEC_OMP_MASKED_TASKLOOP: - mask = GFC_OMP_SPLIT_MASKED | GFC_OMP_SPLIT_TASKLOOP; + mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP; innermost = GFC_OMP_SPLIT_TASKLOOP; break; case EXEC_OMP_MASTER_TASKLOOP: diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-taskloop.f90 b/gcc/testsuite/gfortran.dg/gomp/masked-taskloop.f90 new file mode 100644 index 000..6fb7111 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/masked-taskloop.f90 @@ -0,0 +1,19 @@ +! { dg-do compile } +! { dg-additional-options "-fopenmp -fdump-tree-original" } + +! There was a bug in the clause splitting for the "masked taskloop" +! combined directive that caused it to lose all the clauses. + +subroutine s1 (a1, a2) + integer :: a1, a2 + integer :: i, j + + !$omp masked taskloop collapse(2) grainsize(4) + do i = 1, a1 +do j = 1, a2 +end do + end do + +end subroutine + +! { dg-final { scan-tree-dump "omp taskloop collapse\\(2\\) grainsize\\(4\\)" "original" } }
[PATCH] Fortran: Add location info to OpenMP tree nodes
I've got another patch forthcoming (stage 1 material) that adds some new diagnostics for non-rectangular loops during gimplification of OMP nodes. When I was working on that, I discovered that the Fortran front end wasn't attaching location information to the tree nodes corresponding to the various OMP directives, so the new errors weren't coming out with location info either. I went through trans-openmp.cc and fixed all the places where make_node was being called to explicitly set the location. I don't have a test case specifically for this change, but my test cases for the new diagnostics in the non-rectangular loops patch do exercise it. Is this OK for trunk now, or for stage 1 when we get there? -Sandracommit 4c745003d0b39d0e92032b62421df4920753783a Author: Sandra Loosemore Date: Thu Mar 24 21:02:34 2022 -0700 Fortran: Add location info to OpenMP tree nodes gcc/fortran/ * trans-openmp.cc (gfc_trans_omp_critical): Set location on OMP tree node. (gfc_trans_omp_do): Likewise. (gfc_trans_omp_masked): Likewise. (gfc_trans_omp_do_simd): Likewise. (gfc_trans_omp_scope): Likewise. (gfc_trans_omp_taskgroup): Likewise. (gfc_trans_omp_taskwait): Likewise. (gfc_trans_omp_distribute): Likewise. (gfc_trans_omp_taskloop): Likewise. (gfc_trans_omp_master_masked_taskloop): Likewise. diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 25dde82..ba3ff71 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -5012,6 +5012,7 @@ gfc_trans_omp_critical (gfc_code *code) name = get_identifier (code->ext.omp_clauses->critical_name); gfc_start_block (&block); stmt = make_node (OMP_CRITICAL); + SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); TREE_TYPE (stmt) = void_type_node; OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next); OMP_CRITICAL_NAME (stmt) = name; @@ -5044,6 +5045,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, unsigned ix; vec *saved_doacross_steps = doacross_steps; gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list; + gfc_code *orig_code = code; /* Both collapsed and tiled loops are lowered the same way. In OpenACC, those clauses are not compatible, so prioritize the tile @@ -5398,6 +5400,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, default: gcc_unreachable (); } + SET_EXPR_LOCATION (stmt, gfc_get_location (&orig_code->loc)); TREE_TYPE (stmt) = void_type_node; OMP_FOR_BODY (stmt) = gfc_finish_block (&body); OMP_FOR_CLAUSES (stmt) = omp_clauses; @@ -5670,6 +5673,7 @@ gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses) gfc_start_block (&block); tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc); tree stmt = make_node (OMP_MASKED); + SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); TREE_TYPE (stmt) = void_type_node; OMP_MASKED_BODY (stmt) = body; OMP_MASKED_CLAUSES (stmt) = omp_clauses; @@ -6444,6 +6448,7 @@ gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock, if (flag_openmp) { stmt = make_node (OMP_FOR); + SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); TREE_TYPE (stmt) = void_type_node; OMP_FOR_BODY (stmt) = body; OMP_FOR_CLAUSES (stmt) = omp_do_clauses; @@ -6616,6 +6621,7 @@ gfc_trans_omp_scope (gfc_code *code) tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, code->loc); tree stmt = make_node (OMP_SCOPE); + SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); TREE_TYPE (stmt) = void_type_node; OMP_SCOPE_BODY (stmt) = body; OMP_SCOPE_CLAUSES (stmt) = omp_clauses; @@ -6691,6 +6697,7 @@ gfc_trans_omp_taskgroup (gfc_code *code) gfc_start_block (&block); tree body = gfc_trans_code (code->block->next); tree stmt = make_node (OMP_TASKGROUP); + SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); TREE_TYPE (stmt) = void_type_node; OMP_TASKGROUP_BODY (stmt) = body; OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, @@ -6711,6 +6718,7 @@ gfc_trans_omp_taskwait (gfc_code *code) stmtblock_t block; gfc_start_block (&block); tree stmt = make_node (OMP_TASK); + SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); TREE_TYPE (stmt) = void_type_node; OMP_TASK_BODY (stmt) = NULL_TREE; OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, @@ -6788,6 +6796,7 @@ gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa) if (flag_openmp) { tree distribute = make_node (OMP_DISTRIBUTE); + SET_EXPR_LOCATION (distribute, gfc_get_location (&code->loc)); TREE_TYPE (distribute) = void_type_node; OMP_FOR_BODY (distribute) = stmt; OMP_FOR_CLAUSES (distribute) = omp_clauses; @@ -7008,6 +7017,7 @@ gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op) if (
[PATCH, stage 1] Fortran: Add support for OMP non-rectangular loops
This patch adds Fortran support for OMP 5.1 "canonical loop nest form" and non-rectangular loops. The C/C++ and middle-end support is already present except for some missing constraint checks in the gimplifier, which I've added here. There's still a TODO with respect to the not-yet-implemented TILE construct. Is this OK for stage 1 when the time comes? -Sandracommit c46a79a9841b90fb0cde564e4147932290d91832 Author: Sandra Loosemore Date: Fri Mar 25 14:14:37 2022 -0700 Fortran: Add support for OMP non-rectangular loops. This patch adds support for OMP 5.1 "canonical loop nest form" to the Fortran front end, marks non-rectangular loops for processing by the middle end, and implements missing checks in the gimplifier for additional prohibitions on non-rectangular loops. Note that the OMP spec also prohibits non-rectangular loops with the TILE construct; that construct hasn't been implemented yet, so that error will need to be filled in later. gcc/fortran/ * gfortran.h (struct gfc_omp_clauses): Add non_rectangular bit. * openmp.cc (is_outer_iteration_variable): New function. (expr_is_invariant): New function. (bound_expr_is_canonical): New function. (resolve_omp_do): Replace existing non-rectangularity error with check for canonical form and setting non_rectangular bit. * trans-openmp.cc (gfc_trans_omp_do): Transfer non_rectangular flag to generated tree structure. gcc/ * gimplify.cc (gimplify_omp_for): Update messages for SCHEDULED and ORDERED clause conflict errors. Add check for GRAINSIZE and NUM_TASKS on TASKLOOP. gcc/testsuite/ * c-c++-common/gomp/loop-6.c (f3): New function to test TASKLOOP diagnostics. * gfortran.dg/gomp/collapse1.f90: Update expected messages. * gfortran.dg/gomp/pr85313.f90: Remove dg-error on non-rectangular loops that are now accepted. * gfortran.dg/gomp/non-rectangular-loop.f90: New file. * gfortran.dg/gomp/canonical-loop-1.f90: New file. * gfortran.dg/gomp/canonical-loop-2.f90: New file. diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 7bf1d5a..1bce283 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1533,6 +1533,7 @@ typedef struct gfc_omp_clauses unsigned simd:1, threads:1, depend_source:1, destroy:1, order_concurrent:1; unsigned order_unconstrained:1, order_reproducible:1, capture:1; unsigned grainsize_strict:1, num_tasks_strict:1, compare:1, weak:1; + unsigned non_rectangular:1; ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3; ENUM_BITFIELD (gfc_omp_device_type) device_type:2; ENUM_BITFIELD (gfc_omp_memorder) memorder:3; diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 7141481..4d3fcc8 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -8446,6 +8446,105 @@ gfc_resolve_omp_local_vars (gfc_namespace *ns) gfc_traverse_ns (ns, handle_local_var); } +/* CODE is an OMP loop construct. Return true if VAR matches an iteration + variable outer to level DEPTH. */ +static bool +is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var) +{ + int i; + gfc_code *do_code = code->block->next; + + for (i = 1; i < depth; i++) +{ + gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym; + if (var == ivar) + return true; + do_code = do_code->block->next; +} + return false; +} + +/* CODE is an OMP loop construct. Return true if EXPR does not reference + any iteration variables outer to level DEPTH. */ +static bool +expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr) +{ + int i; + gfc_code *do_code = code->block->next; + + for (i = 1; i < depth; i++) +{ + gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym; + if (gfc_find_sym_in_expr (ivar, expr)) + return false; + do_code = do_code->block->next; +} + return true; +} + +/* CODE is an OMP loop construct. Return true if EXPR matches one of the + canonical forms for a bound expression. It may include references to + an iteration variable outer to level DEPTH; set OUTER_VARP if so. */ +static bool +bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr, + gfc_symbol **outer_varp) +{ + gfc_expr *expr2 = NULL; + + /* Rectangular case. */ + if (depth == 0 || expr_is_invariant (code, depth, expr)) +return true; + + /* Any simple variable that didn't pass expr_is_invariant must be + an outer_var. */ + if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0) +{ + *outer_varp = expr->symtree->n.sym; + return true; +} + + /* All other permitted forms are binary operators. */ + if (expr->expr_type != EXPR_OP) +return false; + + /* Check for plus/minus a loop invariant expr. */ + if (expr->value.op.op == INTRINSIC_PLUS + || expr->value.op.op == INTRINSIC_MINUS) +{ + if (expr_is_invariant (code, depth, expr->value.