diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-06-05 19:10:26 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-06-05 19:10:26 +0200 |
commit | 804c0f35a6b1d75bafc550b4b42155744d77f990 (patch) | |
tree | a0f68633aa578a16cc13798077cad9d32148a70f /gcc/testsuite/c-c++-common/gomp | |
parent | d7cbcfe7c33645eaf95f175f19884d443817857b (diff) | |
download | gcc-804c0f35a6b1d75bafc550b4b42155744d77f990.zip gcc-804c0f35a6b1d75bafc550b4b42155744d77f990.tar.gz gcc-804c0f35a6b1d75bafc550b4b42155744d77f990.tar.bz2 |
openmp: OpenMP loop transformation support
This patch is largely rewritten version of the
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/631764.html
patch set which I've promissed to adjust the way I'd like it but didn't
get to it until now.
The previous series together in diffstat was
176 files changed, 12107 insertions(+), 298 deletions(-)
This patch is
197 files changed, 10843 insertions(+), 212 deletions(-)
and diff between the old series and new patch is
268 files changed, 8053 insertions(+), 9231 deletions(-)
Only the 5.1/5.2 tile/unroll constructs are supported, in various
places some preparations for the other 6.0 loop transformations
constructs (interchange/reverse/fuse) are done, but certainly
not complete and not everywhere. The important difference is that
because tile/unroll partial map 1:1 the original loops to generated
canonical loops and add another set of generated loops without canonical
form inside of it, the tile/unroll partial constructs are terminal
for the generated loop, one can't have some loops from the tile or
unroll partial and some further loops from inside the body of that
construct.
The GENERIC representation attempts to match what the standard specifies,
so there are separate OMP_TILE and OMP_UNROLL trees. If for a particular
loop in a loop nest of some OpenMP loop it awaits a generated loop from a
nested loop, or if in OMP_LOOPXFORM_LOWERED OMP_TILE/UNROLL construct
a generated loop has been moved to some surrounding construct, that
particular loop is represented by all NULL_TREEs in the
OMP_FOR_{INIT,COND,INCR,ORIG_DECLS} vector.
The lowering of the loop transforming constructs is done at gimplification
time, at the start of gimplify_omp_for.
I think this way it is more maintainable over magic clauses with various
loop depths on the other looping constructs or the magic OMP_LOOP_TRANS
construct.
Though, I admit I'm still undecided how to represent the OpenMP 6.0
loop transformation case of say:
#pragma omp for collapse (4)
for (int i = 0; i < 32; ++i)
#pragma omp interchange permutation (2, 1)
#pragma omp reverse
for (int j = 0; j < 32; ++j)
#pragma omp reverse
for (int k = 0; k < 32; ++k)
for (int l = 0; l < 32; ++l)
;
Surely the i loop would go to first vector elements of OMP_FOR_*
of the work-sharing loop, then 2 loops are expecting generated loops
from interchange which would be inside of the body. But the innermost
l loop isn't part of the interchange, so the question is where to
put it. One possibility is to have it in the 4th loop of the OMP_FOR,
another possibility would be to add some artificial construct inside
of the OMP_INTERCHANGE and 2 OMP_REVERSE bodies which would contain
the inner loop(s), e.g. it could be OMP_INTERCHANGE without permutation
clause or some artificial ones or whatever.
I've recently raised various unclear things in the 5.1/5.2/TRs versions
regarding loop transformations, in particular
https://github.com/OpenMP/spec/issues/3908
https://github.com/OpenMP/spec/issues/3909
(sorry, private links unless you have OpenMP membership). Until those
are resolved, I have a sorry on trying to mix generated loops with
non-rectangular loops (way too many questions need to be answered before
that can be done) and similarly for mixing non-perfectly nested loops
with generated loops (again, it can be implemented somehow, but is way
too unclear). The second issue is mostly about data sharing, which is
ambiguous, the patch makes the artificial iterators of the loops effectively
private in the associated constructs (more like local), but for user
iterators doesn't do anything in particular, so for now one needs to use
explicit data sharing clauses on the non-loop transformation OpenMP looping
constructs or surrounding parallel/task/target etc.
2024-06-05 Jakub Jelinek <jakub@redhat.com>
Frederik Harwath <frederik@codesourcery.com>
Sandra Loosemore <sandra@codesourcery.com>
gcc/
* tree.def (OMP_TILE, OMP_UNROLL): New tree codes.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_PARTIAL,
OMP_CLAUSE_FULL and OMP_CLAUSE_SIZES.
* tree.h (OMP_LOOPXFORM_CHECK): Define.
(OMP_LOOPXFORM_LOWERED): Define.
(OMP_CLAUSE_PARTIAL_EXPR): Define.
(OMP_CLAUSE_SIZES_LIST): Define.
* tree.cc (omp_clause_num_ops, omp_clause_code_name): Add entries
for OMP_CLAUSE_{PARTIAL,FULL,SIZES}.
* tree-pretty-print.cc (dump_omp_clause): Handle
OMP_CLAUSE_{PARTIAL,FULL,SIZES}.
(dump_generic_node): Handle OMP_TILE and OMP_UNROLL. Skip printing
loops with NULL OMP_FOR_INIT (node) vector element.
* gimplify.cc (is_gimple_stmt): Handle OMP_TILE and OMP_UNROLL.
(gimplify_omp_taskloop_expr): For SAVE_EXPR use gimplify_save_expr.
(gimplify_omp_loop_xform): New function.
(gimplify_omp_for): Call omp_maybe_apply_loop_xforms and if that
reshuffles what the passed pointer points to, retry or return GS_OK.
Handle OMP_TILE and OMP_UNROLL.
(gimplify_omp_loop): Call omp_maybe_apply_loop_xforms and if that
reshuffles what the passed pointer points to, return GS_OK.
(gimplify_expr): Handle OMP_TILE and OMP_UNROLL.
* omp-general.h (omp_loop_number_of_iterations,
omp_maybe_apply_loop_xforms): Declare.
* omp-general.cc (omp_adjust_for_condition): For LE_EXPR and GE_EXPR
with pointers, don't add/subtract one, but the size of what the
pointer points to.
(omp_loop_number_of_iterations, omp_apply_tile,
find_nested_loop_xform, omp_maybe_apply_loop_xforms): New functions.
gcc/c-family/
* c-common.h (c_omp_find_generated_loop): Declare.
* c-gimplify.cc (c_genericize_control_stmt): Handle OMP_TILE and
OMP_UNROLL.
* c-omp.cc (c_finish_omp_for): Handle generated loops.
(c_omp_is_loop_iterator): Likewise.
(c_find_nested_loop_xform_r, c_omp_find_generated_loop): New
functions.
(c_omp_check_loop_iv): Handle generated loops. For now sorry
on mixing non-rectangular loop with generated loops.
(c_omp_check_loop_binding_exprs): For now sorry on mixing
imperfect loops with generated loops.
(c_omp_directives): Uncomment tile and unroll entries.
* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_TILE and
PRAGMA_OMP_UNROLL, change PRAGMA_OMP__LAST_ to the latter.
(enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FULL and
PRAGMA_OMP_CLAUSE_PARTIAL.
* c-pragma.cc (omp_pragmas_simd): Add tile and unroll omp pragmas.
gcc/c/
* c-parser.cc (c_parser_skip_std_attribute_spec_seq): New function.
(check_omp_intervening_code): Reject imperfectly nested tile.
(c_parser_compound_statement_nostart): If want_nested_loop, use
c_parser_omp_next_tokens_can_be_canon_loop instead of just checking
for RID_FOR keyword.
(c_parser_omp_clause_name): Handle full and partial clause names.
(c_parser_omp_clause_allocate): Remove spurious semicolon.
(c_parser_omp_clause_full, c_parser_omp_clause_partial): New
functions.
(c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FULL and
PRAGMA_OMP_CLAUSE_PARTIAL.
(c_parser_omp_next_tokens_can_be_canon_loop): New function.
(c_parser_omp_loop_nest): Parse C23 attributes. Handle tile/unroll
constructs. Use c_parser_omp_next_tokens_can_be_canon_loop instead
of just checking for RID_FOR keyword. Only add_stmt (body) if it is
non-NULL.
(c_parser_omp_for_loop): Rename tiling variable to oacc_tiling. For
OMP_CLAUSE_SIZES set collapse to list length of OMP_CLAUSE_SIZES_LIST.
Use c_parser_omp_next_tokens_can_be_canon_loop instead of just
checking for RID_FOR keyword. Remove spurious semicolon. Don't call
c_omp_check_loop_binding_exprs if stmt is NULL. Skip generated loops.
(c_parser_omp_tile_sizes, c_parser_omp_tile): New functions.
(OMP_UNROLL_CLAUSE_MASK): Define.
(c_parser_omp_unroll): New function.
(c_parser_omp_construct): Handle PRAGMA_OMP_TILE and
PRAGMA_OMP_UNROLL.
* c-typeck.cc (c_finish_omp_clauses): Adjust wording of some of the
conflicting clause diagnostic messages to include word clause.
Handle OMP_CLAUSE_{FULL,PARTIAL,SIZES} and diagnose full vs. partial
conflict.
gcc/cp/
* cp-tree.h (dependent_omp_for_p): Add another tree argument.
* parser.cc (check_omp_intervening_code): Reject imperfectly nested
tile.
(cp_parser_statement_seq_opt): If want_nested_loop, use
cp_parser_next_tokens_can_be_canon_loop instead of just checking
for RID_FOR keyword.
(cp_parser_omp_clause_name): Handle full and partial clause names.
(cp_parser_omp_clause_full, cp_parser_omp_clause_partial): New
functions.
(cp_parser_omp_all_clauses): Formatting fix. Handle
PRAGMA_OMP_CLAUSE_PARTIAL and PRAGMA_OMP_CLAUSE_FULL.
(cp_parser_next_tokens_can_be_canon_loop): New function.
(cp_parser_omp_loop_nest): Parse C++11 attributes. Handle tile/unroll
constructs. Use cp_parser_next_tokens_can_be_canon_loop instead
of just checking for RID_FOR keyword. Only add_stmt
cp_parser_omp_loop_nest result if it is non-NULL.
(cp_parser_omp_for_loop): Rename tiling variable to oacc_tiling. For
OMP_CLAUSE_SIZES set collapse to list length of OMP_CLAUSE_SIZES_LIST.
Use cp_parser_next_tokens_can_be_canon_loop instead of just
checking for RID_FOR keyword. Remove spurious semicolon. Don't call
c_omp_check_loop_binding_exprs if stmt is NULL. Skip and/or handle
generated loops. Remove spurious ()s around & operands.
(cp_parser_omp_tile_sizes, cp_parser_omp_tile): New functions.
(OMP_UNROLL_CLAUSE_MASK): Define.
(cp_parser_omp_unroll): New function.
(cp_parser_omp_construct): Handle PRAGMA_OMP_TILE and
PRAGMA_OMP_UNROLL.
(cp_parser_pragma): Likewise.
* semantics.cc (finish_omp_clauses): Don't call
fold_build_cleanup_point_expr for cases which obviously won't need it,
like checked INTEGER_CSTs. Handle OMP_CLAUSE_{FULL,PARTIAL,SIZES}
and diagnose full vs. partial conflict. Adjust wording of some of the
conflicting clause diagnostic messages to include word clause.
(finish_omp_for): Use decl equal to global_namespace as a marker for
generated loop. Pass also body to dependent_omp_for_p. Skip
generated loops.
(finish_omp_for_block): Skip generated loops.
* pt.cc (tsubst_omp_clauses): Handle OMP_CLAUSE_{FULL,PARTIAL,SIZES}.
(tsubst_stmt): Handle OMP_TILE and OMP_UNROLL. Handle or skip
generated loops.
(dependent_omp_for_p): Add body argument. If declv vector element
is NULL, find generated loop.
* cp-gimplify.cc (cp_gimplify_expr): Handle OMP_TILE and OMP_UNROLL.
(cp_fold_r): Likewise.
(cp_genericize_r): Likewise. Skip generated loops.
gcc/fortran/
* gfortran.h (enum gfc_statement): Add ST_OMP_UNROLL,
ST_OMP_END_UNROLL, ST_OMP_TILE and ST_OMP_END_TILE.
(struct gfc_omp_clauses): Add sizes_list, partial, full and erroneous
members.
(enum gfc_exec_op): Add EXEC_OMP_UNROLL and EXEC_OMP_TILE.
(gfc_expr_list_len): Declare.
* match.h (gfc_match_omp_tile, gfc_match_omp_unroll): Declare.
* openmp.cc (gfc_get_location): Declare.
(gfc_free_omp_clauses): Free sizes_list.
(match_oacc_expr_list): Rename to ...
(match_omp_oacc_expr_list): ... this. Add is_omp argument and
change diagnostic wording if it is true.
(enum omp_mask2): Add OMP_CLAUSE_{FULL,PARTIAL,SIZES}.
(gfc_match_omp_clauses): Parse full, partial and sizes clauses.
(gfc_match_oacc_wait): Use match_omp_oacc_expr_list instead of
match_oacc_expr_list.
(OMP_UNROLL_CLAUSES, OMP_TILE_CLAUSES): Define.
(gfc_match_omp_tile, gfc_match_omp_unroll): New functions.
(resolve_omp_clauses): Diagnose full vs. partial clause conflict.
Resolve sizes clause arguments.
(find_nested_loop_in_chain): Use switch instead of series of ifs.
Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL.
(gfc_resolve_omp_do_blocks): Set omp_current_do_collapse to
list length of sizes_list if present.
(gfc_resolve_do_iterator): Return for EXEC_OMP_TILE or
EXEC_OMP_UNROLL.
(restructure_intervening_code): Remove spurious ()s around & operands.
(is_outer_iteration_variable): Handle EXEC_OMP_TILE and
EXEC_OMP_UNROLL.
(check_nested_loop_in_chain): Likewise.
(expr_is_invariant): Likewise.
(resolve_omp_do): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL. Diagnose
tile without sizes clause. Use sizes_list length for count if
non-NULL. Set code->ext.omp_clauses->erroneous on loops where we've
reported diagnostics. Sorry for mixing non-rectangular loops with
generated loops.
(omp_code_to_statement): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL.
(gfc_resolve_omp_directive): Likewise.
* parse.cc (decode_omp_directive): Parse end tile, end unroll, tile
and unroll. Move nothing entry alphabetically.
(case_exec_markers): Add ST_OMP_TILE and ST_OMP_UNROLL.
(gfc_ascii_statement): Handle ST_OMP_END_TILE, ST_OMP_END_UNROLL,
ST_OMP_TILE and ST_OMP_UNROLL.
(parse_omp_do): Add nested argument. Handle ST_OMP_TILE and
ST_OMP_UNROLL.
(parse_omp_structured_block): Adjust parse_omp_do caller.
(parse_executable): Likewise. Handle ST_OMP_TILE and ST_OMP_UNROLL.
* resolve.cc (gfc_resolve_blocks): Handle EXEC_OMP_TILE and
EXEC_OMP_UNROLL.
(gfc_resolve_code): Likewise.
* st.cc (gfc_free_statement): Likewise.
* trans.cc (trans_code): Likewise.
* trans-openmp.cc (gfc_trans_omp_clauses): Handle full, partial and
sizes clauses. Use tree_cons + nreverse instead of
temporary vector and build_tree_list_vec for tile_list handling.
(gfc_expr_list_len): New function.
(gfc_trans_omp_do): Rename tile to oacc_tile. Handle sizes clause.
Don't assert code->op is EXEC_DO. Handle EXEC_OMP_TILE and
EXEC_OMP_UNROLL.
(gfc_trans_omp_directive): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL.
* dump-parse-tree.cc (show_omp_clauses): Dump full, partial and
sizes clauses.
(show_omp_node): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL.
(show_code_node): Likewise.
gcc/testsuite/
* c-c++-common/gomp/attrs-tile-1.c: New test.
* c-c++-common/gomp/attrs-tile-2.c: New test.
* c-c++-common/gomp/attrs-tile-3.c: New test.
* c-c++-common/gomp/attrs-tile-4.c: New test.
* c-c++-common/gomp/attrs-tile-5.c: New test.
* c-c++-common/gomp/attrs-tile-6.c: New test.
* c-c++-common/gomp/attrs-unroll-1.c: New test.
* c-c++-common/gomp/attrs-unroll-2.c: New test.
* c-c++-common/gomp/attrs-unroll-3.c: New test.
* c-c++-common/gomp/attrs-unroll-inner-1.c: New test.
* c-c++-common/gomp/attrs-unroll-inner-2.c: New test.
* c-c++-common/gomp/attrs-unroll-inner-3.c: New test.
* c-c++-common/gomp/attrs-unroll-inner-4.c: New test.
* c-c++-common/gomp/attrs-unroll-inner-5.c: New test.
* c-c++-common/gomp/imperfect-attributes.c: Adjust expected
diagnostics.
* c-c++-common/gomp/imperfect-loop-nest.c: New test.
* c-c++-common/gomp/ordered-5.c: New test.
* c-c++-common/gomp/scan-7.c: New test.
* c-c++-common/gomp/tile-1.c: New test.
* c-c++-common/gomp/tile-2.c: New test.
* c-c++-common/gomp/tile-3.c: New test.
* c-c++-common/gomp/tile-4.c: New test.
* c-c++-common/gomp/tile-5.c: New test.
* c-c++-common/gomp/tile-6.c: New test.
* c-c++-common/gomp/tile-7.c: New test.
* c-c++-common/gomp/tile-8.c: New test.
* c-c++-common/gomp/tile-9.c: New test.
* c-c++-common/gomp/tile-10.c: New test.
* c-c++-common/gomp/tile-11.c: New test.
* c-c++-common/gomp/tile-12.c: New test.
* c-c++-common/gomp/tile-13.c: New test.
* c-c++-common/gomp/tile-14.c: New test.
* c-c++-common/gomp/tile-15.c: New test.
* c-c++-common/gomp/unroll-1.c: New test.
* c-c++-common/gomp/unroll-2.c: New test.
* c-c++-common/gomp/unroll-3.c: New test.
* c-c++-common/gomp/unroll-4.c: New test.
* c-c++-common/gomp/unroll-5.c: New test.
* c-c++-common/gomp/unroll-6.c: New test.
* c-c++-common/gomp/unroll-7.c: New test.
* c-c++-common/gomp/unroll-8.c: New test.
* c-c++-common/gomp/unroll-9.c: New test.
* c-c++-common/gomp/unroll-inner-1.c: New test.
* c-c++-common/gomp/unroll-inner-2.c: New test.
* c-c++-common/gomp/unroll-inner-3.c: New test.
* c-c++-common/gomp/unroll-non-rect-1.c: New test.
* c-c++-common/gomp/unroll-non-rect-2.c: New test.
* c-c++-common/gomp/unroll-non-rect-3.c: New test.
* c-c++-common/gomp/unroll-simd-1.c: New test.
* gcc.dg/gomp/attrs-4.c: Adjust expected diagnostics.
* gcc.dg/gomp/for-1.c: Likewise.
* gcc.dg/gomp/for-11.c: Likewise.
* g++.dg/gomp/attrs-4.C: Likewise.
* g++.dg/gomp/for-1.C: Likewise.
* g++.dg/gomp/pr94512.C: Likewise.
* g++.dg/gomp/tile-1.C: New test.
* g++.dg/gomp/tile-2.C: New test.
* g++.dg/gomp/unroll-1.C: New test.
* g++.dg/gomp/unroll-2.C: New test.
* g++.dg/gomp/unroll-3.C: New test.
* gfortran.dg/gomp/inner-loops-1.f90: New test.
* gfortran.dg/gomp/inner-loops-2.f90: New test.
* gfortran.dg/gomp/pure-1.f90: Add tests for !$omp unroll
and !$omp tile.
* gfortran.dg/gomp/pure-2.f90: Remove those tests from here.
* gfortran.dg/gomp/scan-9.f90: New test.
* gfortran.dg/gomp/tile-1.f90: New test.
* gfortran.dg/gomp/tile-2.f90: New test.
* gfortran.dg/gomp/tile-3.f90: New test.
* gfortran.dg/gomp/tile-4.f90: New test.
* gfortran.dg/gomp/tile-5.f90: New test.
* gfortran.dg/gomp/tile-6.f90: New test.
* gfortran.dg/gomp/tile-7.f90: New test.
* gfortran.dg/gomp/tile-8.f90: New test.
* gfortran.dg/gomp/tile-9.f90: New test.
* gfortran.dg/gomp/tile-10.f90: New test.
* gfortran.dg/gomp/tile-imperfect-nest-1.f90: New test.
* gfortran.dg/gomp/tile-imperfect-nest-2.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-1.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-2.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-3.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-4.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-5.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-6.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-7.f90: New test.
* gfortran.dg/gomp/tile-inner-loops-8.f90: New test.
* gfortran.dg/gomp/tile-non-rectangular-1.f90: New test.
* gfortran.dg/gomp/tile-non-rectangular-2.f90: New test.
* gfortran.dg/gomp/tile-non-rectangular-3.f90: New test.
* gfortran.dg/gomp/tile-unroll-1.f90: New test.
* gfortran.dg/gomp/tile-unroll-2.f90: New test.
* gfortran.dg/gomp/unroll-1.f90: New test.
* gfortran.dg/gomp/unroll-2.f90: New test.
* gfortran.dg/gomp/unroll-3.f90: New test.
* gfortran.dg/gomp/unroll-4.f90: New test.
* gfortran.dg/gomp/unroll-5.f90: New test.
* gfortran.dg/gomp/unroll-6.f90: New test.
* gfortran.dg/gomp/unroll-7.f90: New test.
* gfortran.dg/gomp/unroll-8.f90: New test.
* gfortran.dg/gomp/unroll-9.f90: New test.
* gfortran.dg/gomp/unroll-10.f90: New test.
* gfortran.dg/gomp/unroll-11.f90: New test.
* gfortran.dg/gomp/unroll-12.f90: New test.
* gfortran.dg/gomp/unroll-13.f90: New test.
* gfortran.dg/gomp/unroll-inner-loop-1.f90: New test.
* gfortran.dg/gomp/unroll-inner-loop-2.f90: New test.
* gfortran.dg/gomp/unroll-no-clause-1.f90: New test.
* gfortran.dg/gomp/unroll-non-rect-1.f90: New test.
* gfortran.dg/gomp/unroll-non-rect-2.f90: New test.
* gfortran.dg/gomp/unroll-simd-1.f90: New test.
* gfortran.dg/gomp/unroll-simd-2.f90: New test.
* gfortran.dg/gomp/unroll-simd-3.f90: New test.
* gfortran.dg/gomp/unroll-tile-1.f90: New test.
* gfortran.dg/gomp/unroll-tile-2.f90: New test.
* gfortran.dg/gomp/unroll-tile-inner-1.f90: New test.
libgomp/
* testsuite/libgomp.c-c++-common/imperfect-transform-1.c: New test.
* testsuite/libgomp.c-c++-common/imperfect-transform-2.c: New test.
* testsuite/libgomp.c-c++-common/matrix-1.h: New test.
* testsuite/libgomp.c-c++-common/matrix-constant-iter.h: New test.
* testsuite/libgomp.c-c++-common/matrix-helper.h: New test.
* testsuite/libgomp.c-c++-common/matrix-no-directive-1.c: New test.
* testsuite/libgomp.c-c++-common/matrix-no-directive-unroll-full-1.c:
New test.
* testsuite/libgomp.c-c++-common/matrix-omp-distribute-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/matrix-omp-for-1.c: New test.
* testsuite/libgomp.c-c++-common/matrix-omp-parallel-for-1.c: New test.
* testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-1.c:
New test.
* testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-simd-1.c:
New test.
* testsuite/libgomp.c-c++-common/matrix-omp-target-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/matrix-omp-target-teams-distribute-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/matrix-omp-taskloop-1.c: New test.
* testsuite/libgomp.c-c++-common/matrix-omp-teams-distribute-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/matrix-simd-1.c: New test.
* testsuite/libgomp.c-c++-common/matrix-transform-variants-1.h:
New test.
* testsuite/libgomp.c-c++-common/target-imperfect-transform-1.c:
New test.
* testsuite/libgomp.c-c++-common/target-imperfect-transform-2.c:
New test.
* testsuite/libgomp.c-c++-common/unroll-1.c: New test.
* testsuite/libgomp.c-c++-common/unroll-non-rect-1.c: New test.
* testsuite/libgomp.c++/matrix-no-directive-unroll-full-1.C: New test.
* testsuite/libgomp.c++/tile-2.C: New test.
* testsuite/libgomp.c++/tile-3.C: New test.
* testsuite/libgomp.c++/unroll-1.C: New test.
* testsuite/libgomp.c++/unroll-2.C: New test.
* testsuite/libgomp.c++/unroll-full-tile.C: New test.
* testsuite/libgomp.fortran/imperfect-transform-1.f90: New test.
* testsuite/libgomp.fortran/imperfect-transform-2.f90: New test.
* testsuite/libgomp.fortran/inner-1.f90: New test.
* testsuite/libgomp.fortran/nested-fn.f90: New test.
* testsuite/libgomp.fortran/target-imperfect-transform-1.f90: New test.
* testsuite/libgomp.fortran/target-imperfect-transform-2.f90: New test.
* testsuite/libgomp.fortran/tile-1.f90: New test.
* testsuite/libgomp.fortran/tile-2.f90: New test.
* testsuite/libgomp.fortran/tile-unroll-1.f90: New test.
* testsuite/libgomp.fortran/tile-unroll-2.f90: New test.
* testsuite/libgomp.fortran/tile-unroll-3.f90: New test.
* testsuite/libgomp.fortran/tile-unroll-4.f90: New test.
* testsuite/libgomp.fortran/unroll-1.f90: New test.
* testsuite/libgomp.fortran/unroll-2.f90: New test.
* testsuite/libgomp.fortran/unroll-3.f90: New test.
* testsuite/libgomp.fortran/unroll-4.f90: New test.
* testsuite/libgomp.fortran/unroll-5.f90: New test.
* testsuite/libgomp.fortran/unroll-6.f90: New test.
* testsuite/libgomp.fortran/unroll-7a.f90: New test.
* testsuite/libgomp.fortran/unroll-7b.f90: New test.
* testsuite/libgomp.fortran/unroll-7c.f90: New test.
* testsuite/libgomp.fortran/unroll-7.f90: New test.
* testsuite/libgomp.fortran/unroll-8.f90: New test.
* testsuite/libgomp.fortran/unroll-simd-1.f90: New test.
* testsuite/libgomp.fortran/unroll-tile-1.f90: New test.
* testsuite/libgomp.fortran/unroll-tile-2.f90: New test.
Diffstat (limited to 'gcc/testsuite/c-c++-common/gomp')
49 files changed, 3072 insertions, 8 deletions
diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-1.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-1.c new file mode 100644 index 0000000..e9c9bd3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-1.c @@ -0,0 +1,57 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll partial), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-2.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-2.c new file mode 100644 index 0000000..d6d0499 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-2.c @@ -0,0 +1,70 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll partial), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-3.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-3.c new file mode 100644 index 0000000..32348ec --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-3.c @@ -0,0 +1,47 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-4.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-4.c new file mode 100644 index 0000000..6645c79 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-4.c @@ -0,0 +1,106 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (tile sizes(0))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(-1))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes())]] /* { dg-error "expected expression before" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + dummy (i); + + [[omp::directive (tile sizes)]] /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1) sizes(1))]] /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile, sizes(1), sizes(1))]] /* { dg-error "expected end of line before ','" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll partia), /* { dg-error "expected an OpenMP clause before 'partia'" } */ + directive (tile sizes(1)))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(8,8)), + directive (unroll partial), /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(8,8)), + directive (unroll partial))]] /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = 2; j < i; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2, 3))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + int s; + [[omp::directive (tile sizes(s))]] /* { dg-error "'sizes' argument needs positive integral constant" "" { target { ! c++98_only } } } */ + /* { dg-error "the value of 's' is not usable in a constant expression" "" { target { c++ && { ! c++98_only } } } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(42.0))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-5.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-5.c new file mode 100644 index 0000000..d9b2dd9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-5.c @@ -0,0 +1,113 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (parallel for), + directive (tile sizes(0)))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(-1)))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), /* { dg-error "expected primary-expression before" "" { target c++ } .+1 } */ + directive (tile sizes()))]] /* { dg-error "expected expression before" "" { target c } } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), /* { dg-error "expected primary-expression before" "" { target c++ } .+1 } */ + directive (tile sizes(,)))]] /* { dg-error "expected expression before" "" { target c } } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes))]] /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1) sizes(1)))]] /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll partia), /* { dg-error "expected an OpenMP clause before 'partia'" } */ + directive (tile sizes(1)))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(8,8)), + directive (unroll partial), /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(8,8)), + directive (unroll partial))]] /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 2; j < i; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-6.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-6.c new file mode 100644 index 0000000..7ac40fb --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-6.c @@ -0,0 +1,72 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 0; j < i; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(1, 2)))]] /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(1, 2)), /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(5, 6)), /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-1.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-1.c new file mode 100644 index 0000000..be3340a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-1.c @@ -0,0 +1,135 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test1 (void) +{ + [[omp::directive (unroll partial)]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test2 (void) +{ + [[omp::directive (unroll partial(10))]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test3 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test4 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 0; i > 100; ++i) + dummy (i); +} + +void +test5 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 1; i <= 100; ++i) + dummy (i); +} + +void +test6 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 200; i >= 100; i--) + dummy (i); +} + +void +test7 (void) +{ + [[omp::directive (unroll full)]] + for (int i = -100; i > 100; ++i) + dummy (i); +} + +void +test8 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 100; i > -200; --i) + dummy (i); +} + +void +test9 (void) +{ + [[omp::directive (unroll full)]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test10 (void) +{ + [[omp::directive (unroll full)]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test12 (void) +{ + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test13 (void) +{ + for (int i = 0; i < 100; ++i) + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test14 (void) +{ + [[omp::directive (for)]] + for (int i = 0; i < 100; ++i) + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test15 (void) +{ + [[omp::directive (for)]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (j); + + dummy (i); + } + } diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-2.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-2.c new file mode 100644 index 0000000..89170bc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-2.c @@ -0,0 +1,81 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ +/* { dg-prune-output "error: invalid controlling predicate" } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (unroll partial), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll full), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + directive (unroll partial))]] + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll full), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll partial partial))]] /* { dg-error "too many 'partial' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::directive (unroll full full)]] /* { dg-error "too many 'full' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (unroll partial), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int i; + + [[omp::sequence (directive (for), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + directive (unroll foo))]] /* { dg-error "expected an OpenMP clause before 'foo'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::directive (unroll partial(i))]] + /* { dg-error "the value of 'i' is not usable in a constant expression" "" { target c++ } .-1 } */ + /* { dg-error "'partial' argument needs positive constant integer expression" "" { target *-*-* } .-2 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::directive (unroll parti)]] /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll partial(1)), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + directive (unroll parti))]] /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll partial(1)), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + directive (unroll parti))]] /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int sum = 0; + [[omp::sequence (directive (parallel for reduction(+ : sum) collapse(2)), + directive (unroll partial(1)))]] /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 3; i < 10; ++i) + for (int j = -2; j < 7; ++j) + sum++; +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-3.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-3.c new file mode 100644 index 0000000..35dbf4f --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ +/* { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple -fdump-tree-cunroll" } */ + +extern void dummy (int); + +void +test1 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 0; i < 10; i++) + dummy (i); +} + +/* Loop should be removed with 10 copies of the body remaining */ +/* { dg-final { scan-tree-dump-times "dummy" 10 "cunroll" } } */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-1.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-1.c new file mode 100644 index 0000000..5cec780 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-2.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-2.c new file mode 100644 index 0000000..680fca4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + [[omp::directive (tile sizes (2))]] + for (int j = 0; j != 100; ++j) + dummy (i); + + [[omp::directive (target parallel for, collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (tile, sizes(2, 3))]] + for (int j = 0; j != 100; ++j) + for (int k = 0; k != 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-3.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-3.c new file mode 100644 index 0000000..f91d4dd --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +/* Test that omp::sequence is handled properly in a loop nest, but that + invalid attribute specifiers are rejected. */ + +extern void dummy (int); + +void +test1 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (unroll, partial))]] + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-4.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-4.c new file mode 100644 index 0000000..c08985f --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (tile sizes(2, 3))]] + for (int j = 0; j != 100; ++j) /* { dg-error "not enough nested loops" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-5.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-5.c new file mode 100644 index 0000000..04614f8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-5.c @@ -0,0 +1,61 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +/* Test that omp::sequence is handled properly in a loop nest, but that + invalid attribute specifiers are rejected. */ + +extern void dummy (int); + +void +test2 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (masked)]] /* { dg-error "expected 'for' loop or OpenMP loop transformation construct" } */ + for (int j = 0; j != 100; ++j) /* { dg-error "loop not permitted" } */ + dummy (i); +} + +void +test3 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial)]] /* { dg-error "attributes on the same statement" } */ + [[omp::directive (masked)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test4 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (unroll, partial), + directive (masked))]] /* { dg-error "loop nest expected" } */ + for (int j = 0; j != 100; ++j) + dummy (i); /* { dg-error "declared" } */ +} + +void +test5 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (masked), /* { dg-error "expected 'for' loop or OpenMP loop transformation construct" } */ + directive (unroll, partial))]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test6 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial), /* { dg-error "attributes on the same statement" } */ + omp::directive (masked)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c b/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c index 776295c..3c35e7c 100644 --- a/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c @@ -1,17 +1,20 @@ /* { dg-do compile { target { c || c++11 } } } */ /* Check that a nested FOR loop with standard c/c++ attributes on it - is treated as intervening code, since it doesn't match the grammar - for canonical loop nest form. */ + (not the C++ attribute syntax for OpenMP directives) + gives an error. */ extern void do_something (void); + +/* This one should be OK, an empty attribute list is ignored in both C + and C++. */ void imperfect1 (int x, int y) { #pragma omp for collapse (2) - for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + for (int i = 0; i < x; i++) { - [[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + [[]] for (int j = 0; j < y; j++) do_something (); } } @@ -19,16 +22,15 @@ void imperfect1 (int x, int y) void perfect1 (int x, int y) { #pragma omp for ordered (2) - for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ - /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + for (int i = 0; i < x; i++) { - [[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + [[]] for (int j = 0; j < y; j++) do_something (); } } /* Similar, but put the attributes on a block wrapping the nested loop - instead. */ + instead. This is not allowed by the grammar. */ void imperfect2 (int x, int y) { diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-loop-nest.c b/gcc/testsuite/c-c++-common/gomp/imperfect-loop-nest.c new file mode 100644 index 0000000..e03350b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-loop-nest.c @@ -0,0 +1,12 @@ +void +test (void) +{ +#pragma omp tile sizes (2,4,6) + for (unsigned i = 0; i < 10; i++) /* { dg-error "inner loops must be perfectly nested" } */ + for (unsigned j = 0; j < 10; j++) + { + float intervening_decl = 0; +#pragma omp unroll partial(2) + for (unsigned k = 0; k < 10; k++); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-5.c b/gcc/testsuite/c-c++-common/gomp/ordered-5.c new file mode 100644 index 0000000..ee798f4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/ordered-5.c @@ -0,0 +1,140 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +void +foo (void) +{ + int i; + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered + ; + } + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads + ; + } + #pragma omp for simd ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads, simd + ; + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } +} + +void +bar (void) +{ + int i; + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered + ; + } + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads + ; + } + #pragma omp for simd ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads, simd + ; + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/scan-7.c b/gcc/testsuite/c-c++-common/gomp/scan-7.c new file mode 100644 index 0000000..412c98d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-7.c @@ -0,0 +1,55 @@ +int a; + +void +foo (int *c, int *d) +{ + #pragma omp for reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + #pragma omp tile sizes (2) + for (int i = 0; i < 64; ++i) + { + a = a + c[i]; + #pragma omp scan inclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + d[i] = a; + } +} + +void +bar (int **c, int **d) +{ + #pragma omp for collapse (2) reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + for (int i = 0; i < 64; ++i) + #pragma omp tile sizes (3) + for (int j = 0; j < 64; ++j) + { + d[i][j] = a; + #pragma omp scan exclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + a = a + c[i][j]; + } +} + +void +baz (int *c, int *d) +{ + #pragma omp for reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + #pragma omp unroll partial (2) + for (int i = 0; i < 64; ++i) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + a = a + c[i]; + } +} + +void +qux (int **c, int **d) +{ + #pragma omp for collapse (2) reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + for (int i = 0; i < 64; ++i) + #pragma omp unroll partial (3) + for (int j = 0; j < 64; ++j) + { + a = a + c[i][j]; + #pragma omp scan inclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + d[i][j] = a; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-1.c b/gcc/testsuite/c-c++-common/gomp/tile-1.c new file mode 100644 index 0000000..12d7331 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-1.c @@ -0,0 +1,54 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll partial + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-10.c b/gcc/testsuite/c-c++-common/gomp/tile-10.c new file mode 100644 index 0000000..3d1c5a9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-10.c @@ -0,0 +1,90 @@ +void +test1 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) /* { dg-error "the same loop iteration variables 'i' used in multiple associated loops" "" { target c } } */ + for (i = 0; i < 1024; ++i) /* { dg-error "the same loop iteration variables 'i' used in multiple associated loops" "" { target c++ } } */ + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (i = 0; i < 1024; ++i) + ; +} + +void +test2 (void) +{ + long long i; + int j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) /* { dg-error "outer iteration variable 'i' used in initializer expression has type other than 'int'" "" { target c } } */ + for (i = 0; i < 1024; ++i) /* { dg-error "outer iteration variable 'i' used in initializer expression has type other than 'int'" "" { target c++ } } */ + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = i; l < 1024; ++l) + ; +} + +void +test3 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = 0; l < 7 * i * i; ++l) /* { dg-error "condition expression refers to iteration variable 'i'" } */ + ; +} + +void +test4 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = i * i; l < 1024; ++l) /* { dg-error "initializer expression refers to iteration variable 'i'" } */ + ; +} + +void +test5 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) /* { dg-error "increment expression refers to iteration variable 'j'" "" { target c } } */ + for (j = 0; j < 1024; ++j) /* { dg-error "increment expression refers to iteration variable 'j'" "" { target c++ } } */ + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = 0; l < 1024; l += j) + ; +} + +void +test6 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = 0; l < i - 2; ++l) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-11.c b/gcc/testsuite/c-c++-common/gomp/tile-11.c new file mode 100644 index 0000000..7659fc5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-11.c @@ -0,0 +1,110 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp tile sizes(0) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(-1) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes() /* { dg-error "expected expression before" "" { target c} } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(,) /* { dg-error "expected expression before" "" { target c } } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1,2 /* { dg-error "expected ',' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) sizes(1) /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll partia /* { dg-error "expected an OpenMP clause before 'partia'" } */ + #pragma omp tile sizes(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = i; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = 2; j < i; ++j) + dummy (i); + + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + int s; + #pragma omp tile sizes(s) /* { dg-error "'sizes' argument needs positive integral constant" "" { target { ! c++98_only } } } */ + /* { dg-error "the value of 's' is not usable in a constant expression" "" { target { c++ && { ! c++98_only } } } .-1 } */ + /* { dg-error "'s' cannot appear in a constant-expression" "" { target c++98_only } .-2 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(42.0) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-12.c b/gcc/testsuite/c-c++-common/gomp/tile-12.c new file mode 100644 index 0000000..8408d53 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-12.c @@ -0,0 +1,134 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp parallel for + #pragma omp tile sizes(0) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(-1) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(5, -42) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(0.5f) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes() /* { dg-error "expected expression before" "" { target c} } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(,) /* { dg-error "expected expression before" "" { target c } } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1,2 /* { dg-error "expected ',' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) sizes(1) /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll partia /* { dg-error "expected an OpenMP clause before 'partia'" } */ + #pragma omp tile sizes(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 2; j < i; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + #pragma omp tile /* { dg-error "expected 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes (1) sizes (1) /* { dg-error "expected end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-13.c b/gcc/testsuite/c-c++-common/gomp/tile-13.c new file mode 100644 index 0000000..6948a44 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-13.c @@ -0,0 +1,70 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + #pragma omp for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 0; j < i; ++j) + dummy (i); + + + #pragma omp for collapse(2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(3) + #pragma omp tile sizes(1, 2) /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(3) + #pragma omp tile sizes(1, 2) /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(3) + #pragma omp tile sizes(5, 6) /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-14.c b/gcc/testsuite/c-c++-common/gomp/tile-14.c new file mode 100644 index 0000000..1b3f6fc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-14.c @@ -0,0 +1,53 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp for + #pragma omp tile sizes(2, 3) + #pragma omp tile sizes(3, 4, 5) + #pragma omp tile sizes(6, 7, 8, 9) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + for (int l = 0; l < 100; ++l) + dummy (i); + + #pragma omp for + #pragma omp tile sizes(2, 3) + for (int i = 0; i < 100; ++i) + #pragma omp tile sizes(3, 4, 5) + for (int j = 0; j < 100; ++j) + #pragma omp tile sizes(6, 7, 8, 9) + for (int k = 0; k < 100; ++k) + for (int l = 0; l < 100; ++l) + for (int m = 0; m < 100; ++m) + #pragma omp unroll partial(2) + for (int n = 0; n < 100; ++n) + dummy (i); + + #pragma omp for collapse(2) + for (int i = 0; i < 100; ++i) + #pragma omp tile sizes(2, 3) + #pragma omp tile sizes(3, 4, 5) + #pragma omp tile sizes(6, 7, 8, 9) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + for (int l = 0; l < 100; ++l) + for (int m = 0; m < 100; ++m) + dummy (i); + + #pragma omp for collapse(2) + for (int i = 0; i < 100; ++i) + #pragma omp tile sizes(2, 3) + for (int j = 0; j < 100; ++j) + #pragma omp tile sizes(3, 4, 5) + for (int k = 0; k < 100; ++k) + #pragma omp tile sizes(6, 7, 8, 9) + for (int l = 0; l < 100; ++l) + for (int m = 0; m < 100; ++m) + for (int n = 0; n < 100; ++n) + #pragma omp unroll partial(2) + for (int o = 0; o < 100; ++o) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-15.c b/gcc/testsuite/c-c++-common/gomp/tile-15.c new file mode 100644 index 0000000..0308a1f --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-15.c @@ -0,0 +1,68 @@ +/* It isn't really clear what is supposed to be valid and what isn't when mixing + imperfectly nested loops with generated loops. Sorry for now until that is + clarified. */ +void foo (int, int); + +void +bar (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + foo (i, -1); + #pragma omp tile sizes (2) + for (int j = 0; j < 32; ++j) + foo (i, j); + foo (i, -2); + } +} + +void +baz (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + foo (i, -1); + #pragma omp tile sizes (2, 2) + for (int j = 0; j < 32; ++j) + #pragma omp tile sizes (2, 2) + for (int k = 0; k < 32; ++k) + for (int l = 0; l < 32; ++l) + foo (i + k, j + l); + foo (i, -2); + } +} + +void +qux (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + int m = i + 6; + foo (i, -1); + #pragma omp tile sizes (2) + for (int j = m; j < 32; ++j) + foo (i, j); + foo (i, -2); + } +} + +void +freddy (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + int m = i + 6; + foo (i, -1); + #pragma omp tile sizes (2, 2) + for (int j = 0; j < 32; ++j) + #pragma omp tile sizes (2, 2) + for (int k = 0; k < 32; ++k) + for (int l = m; l < 32; ++l) + foo (i + k, j + l); + foo (i, -2); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-2.c b/gcc/testsuite/c-c++-common/gomp/tile-2.c new file mode 100644 index 0000000..5ca692c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-2.c @@ -0,0 +1,67 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll partial + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-3.c b/gcc/testsuite/c-c++-common/gomp/tile-3.c new file mode 100644 index 0000000..4ba9d87 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-3.c @@ -0,0 +1,44 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp for collapse(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(1) + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp for collapse(1) + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-4.c b/gcc/testsuite/c-c++-common/gomp/tile-4.c new file mode 100644 index 0000000..bcffbcc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-4.c @@ -0,0 +1,320 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include <stdio.h> + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +test1 (void) +{ + int iter = 0; + int i; +#pragma omp tile sizes(3) + for (i = 0; i < 10; i = i + 2) + { + ASSERT_EQ (i, iter); + iter = iter + 2; + } + + ASSERT_EQ (i, 10); + return iter; +} + +int +test2 (void) +{ + int iter = 0; + int i; +#pragma omp tile sizes(3) + for (i = 0; i < 10; i = i + 2) + { + ASSERT_EQ (i, iter); + iter = iter + 2; + } + + ASSERT_EQ (i, 10); + return iter; +} + +int +test3 (void) +{ + int iter = 0; + int i; +#pragma omp tile sizes(8) + for (i = 0; i < 10; i = i + 2) + { + ASSERT_EQ (i, iter); + iter = iter + 2; + } + + ASSERT_EQ (i, 10); + return iter; +} + +int +test4 (void) +{ + int iter = 10; + int i; +#pragma omp tile sizes(8) + for (i = 10; i > 0; i = i - 2) + { + ASSERT_EQ (i, iter); + iter = iter - 2; + } + ASSERT_EQ (i, 0); + return iter; +} + +int +test5 (void) +{ + int iter = 10; + int i; +#pragma omp tile sizes(71) + for (i = 10; i > 0; i = i - 2) + { + ASSERT_EQ (i, iter); + iter = iter - 2; + } + + ASSERT_EQ (i, 0); + return iter; +} + +int +test6 (void) +{ + int iter = 10; + int i; +#pragma omp tile sizes(1) + for (i = 10; i > 0; i = i - 2) + { + ASSERT_EQ (i, iter); + iter = iter - 2; + } + ASSERT_EQ (i, 0); + return iter; +} + +int +test7 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(2) + for (i = 5; i < -5; i = i - 3) + { + fprintf (stderr, "%d\n", i); + __builtin_abort (); + iter = iter - 3; + } + + /* No iteration expected */ + return iter; +} + +int +test8 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(2) + for (i = 5; i > -5; i = i - 3) + { + ASSERT_EQ (i, iter); + /* Expect only first iteration of the last tile to execute */ + if (iter != -4) + iter = iter - 3; + } + + ASSERT_EQ (i, -7); + return iter; +} + + +int +test9 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(5) + for (i = 5; i >= -5; i = i - 4) + { + ASSERT_EQ (i, iter); + /* Expect only first iteration of the last tile to execute */ + if (iter != - 3) + iter = iter - 4; + } + + ASSERT_EQ (i, -7); + return iter; +} + +int +test10 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(5) + for (i = 5; i >= -5; i--) + { + ASSERT_EQ (i, iter); + iter--; + } + + ASSERT_EQ (i, -6); + return iter; +} + +int +test11 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(15) + for (i = 5; i != -5; i--) + { + ASSERT_EQ (i, iter); + iter--; + } + ASSERT_EQ (i, -5); + return iter; +} + +int +test12 (void) +{ + int iter = 0; + unsigned i; +#pragma omp tile sizes(3) + for (i = 0; i != 5; i++) + { + ASSERT_EQ (i, iter); + iter++; + } + + ASSERT_EQ (i, 5); + return iter; +} + +int +test13 (void) +{ + int iter = -5; + long long unsigned int i = 42; +#pragma omp tile sizes(15) + for (int i = -5; i < 5; i = i + 3) + { + ASSERT_EQ (i, iter); + iter += 3; + } + + ASSERT_EQ (i, 42); + return iter; +} + +int +test14 (unsigned init, int step) +{ + int iter = init; + long long unsigned int i; +#pragma omp tile sizes(8) + for (i = init; i < 2 * init; i = i + step) + iter++; + + if (init) + ASSERT_EQ (i, 2 * init + (init == 5)); + return iter; +} + +int +test15 (unsigned init, int step) +{ + int iter = init; + int i; +#pragma omp tile sizes(8) + for (unsigned i = init; i > 2 * init; i = i + step) + iter++; + + return iter; +} + +int +main () +{ + int last_iter; + + last_iter = test1 (); + ASSERT_EQ (last_iter, 10); + + last_iter = test2 (); + ASSERT_EQ (last_iter, 10); + + last_iter = test3 (); + ASSERT_EQ (last_iter, 10); + + last_iter = test4 (); + ASSERT_EQ (last_iter, 0); + + last_iter = test5 (); + ASSERT_EQ (last_iter, 0); + + last_iter = test6 (); + ASSERT_EQ (last_iter, 0); + + last_iter = test7 (); + ASSERT_EQ (last_iter, 5); + + last_iter = test8 (); + ASSERT_EQ (last_iter, -4); + + last_iter = test9 (); + ASSERT_EQ (last_iter, -3); + + last_iter = test10 (); + ASSERT_EQ (last_iter, -6); + + last_iter = test11 (); + ASSERT_EQ (last_iter, -5); + + last_iter = test12 (); + ASSERT_EQ (last_iter, 5); + + last_iter = test13 (); + ASSERT_EQ (last_iter, 7); + + last_iter = test14 (0, 1); + ASSERT_EQ (last_iter, 0); + + last_iter = test14 (0, -1); + ASSERT_EQ (last_iter, 0); + + last_iter = test14 (8, 2); + ASSERT_EQ (last_iter, 12); + + last_iter = test14 (5, 3); + ASSERT_EQ (last_iter, 7); + + last_iter = test15 (8, -1); + ASSERT_EQ (last_iter, 8); + + last_iter = test15 (8, -2); + ASSERT_EQ (last_iter, 8); + + last_iter = test15 (5, -3); + ASSERT_EQ (last_iter, 5); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-5.c b/gcc/testsuite/c-c++-common/gomp/tile-5.c new file mode 100644 index 0000000..45b40a4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-5.c @@ -0,0 +1,169 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include <stdio.h> + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +#define ASSERT_EQ_PTR(var, ptr) \ + do \ + { \ + if ((var) != (ptr)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %p, expected %p\n", \ + __FILE__, __LINE__, (var), (ptr)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +test1 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i < data + 10; i++) + { + ASSERT_EQ (*i, data[iter]); + ASSERT_EQ_PTR (i, data + iter); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test2 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i < data + 10; i = i + 2) + { + ASSERT_EQ_PTR (i, data + 2 * iter); + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test3 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i <= data + 9; i = i + 2) + { + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test4 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i != data + 10; i = i + 1) + { + ASSERT_EQ (*i, data[iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test5 (int data[15]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(3) + for (i = data + 14; i >= data + 5; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 4); + return iter; +} + +int +test6 (int data[15]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(3) + for (i = data + 14; i > data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 4); + return iter; +} + +int +test7 (int data[15]) +{ + int iter = 0; + #pragma omp tile sizes(1) + for (int *i = data + 14; i != data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +main () +{ + int iter_count; + int data[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int data2[15] = { -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + iter_count = test1 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test2 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test3 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test4 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test5 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test6 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test7 (data2); + ASSERT_EQ (iter_count, 10); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-6.c b/gcc/testsuite/c-c++-common/gomp/tile-6.c new file mode 100644 index 0000000..9fcab42 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-6.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +int +test1 (void) +{ + int sum = 0; + for (int k = 0; k < 10; k++) + { + #pragma omp tile sizes(5,7) + for (int i = 0; i < 10; i++) + for (int j = 0; j < 10; j = j + 2) + sum = sum + 1; + } + + return sum; +} + +int +main () +{ + int result = test1 (); + + if (result != 500) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-7.c b/gcc/testsuite/c-c++-common/gomp/tile-7.c new file mode 100644 index 0000000..2c78b18 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-7.c @@ -0,0 +1,51 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include <stdio.h> + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +#define ASSERT_EQ_PTR(var, ptr) \ + do \ + { \ + if ((var) != (ptr)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %p, expected %p\n", \ + __FILE__, __LINE__, (var), (ptr)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +main () +{ + int iter_count; + int data[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int iter = 0; + int *i; + + #pragma omp tile sizes(1) + for (i = data; i < data + 10; i = i + 2) + { + ASSERT_EQ_PTR (i, data + 2 * iter); + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + unsigned long real_iter_count + = ((unsigned long)i - (unsigned long)data) / (sizeof (int) * 2); + ASSERT_EQ (real_iter_count, 5); + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-8.c b/gcc/testsuite/c-c++-common/gomp/tile-8.c new file mode 100644 index 0000000..65b083b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-8.c @@ -0,0 +1,50 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include <stdio.h> + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +main () +{ + int iter_j = 0, iter_k = 0; + unsigned i, j, k; + + #pragma omp tile sizes(3,5,8) + for (i = 0; i < 2; i=i+2) + for (j = 0; j < 3; j=j+1) + for (k = 0; k < 5; k=k+3) + { + /* fprintf (stderr, "i=%d j=%d k=%d\n", i, j, k); + fprintf (stderr, "iter_j=%d iter_k=%d\n", iter_j, iter_k); */ + ASSERT_EQ (i, 0); + if (k == 0) + { + ASSERT_EQ (j, iter_j); + iter_k = 0; + } + + ASSERT_EQ (k, iter_k); + + iter_k = iter_k + 3; + if (k == 3) + iter_j++; + } + + ASSERT_EQ (i, 2); + ASSERT_EQ (j, 3); + ASSERT_EQ (k, 6); + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-9.c b/gcc/testsuite/c-c++-common/gomp/tile-9.c new file mode 100644 index 0000000..0276751 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-9.c @@ -0,0 +1,19 @@ +/* { dg-additional-options "-O2" } */ + +int foo (int); + +void +mult (float *matrix1, float *matrix2, float *result, + unsigned dim0, unsigned dim1, unsigned dim2, unsigned dim3) +{ + #pragma omp taskloop collapse(3) + for (unsigned i = 0; i < dim0; i++) + #pragma omp tile sizes(2, 2) + #pragma omp tile sizes(2, 2) + #pragma omp tile sizes(2, 2) + for (unsigned j = 0; j < dim1; j += dim2 * foo (0)) + #pragma omp unroll partial(2) + #pragma omp unroll partial(2) + for (unsigned k = 0; k < dim1; k += dim3 * foo (1)) + result[i * dim1 + j] += matrix1[i * dim1 + k] * matrix2[k * dim0 + j]; +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-1.c new file mode 100644 index 0000000..514a9f8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-1.c @@ -0,0 +1,132 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp unroll partial + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test2 (void) +{ + #pragma omp unroll partial(10) + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test3 (void) +{ + #pragma omp unroll full + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test4 (void) +{ + #pragma omp unroll full + for (int i = 0; i > 100; ++i) + dummy (i); +} + +void +test5 (void) +{ + #pragma omp unroll full + for (int i = 1; i <= 100; ++i) + dummy (i); +} + +void +test6 (void) +{ + #pragma omp unroll full + for (int i = 200; i >= 100; i--) + dummy (i); +} + +void +test7 (void) +{ + #pragma omp unroll full + for (int i = -100; i > 100; ++i) + dummy (i); +} + +void +test8 (void) +{ + #pragma omp unroll full + for (int i = 100; i > -200; --i) + dummy (i); +} + +void +test9 (void) +{ + #pragma omp unroll full + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test10 (void) +{ + #pragma omp unroll full + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test12 (void) +{ + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test13 (void) +{ + for (int i = 0; i < 100; ++i) + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test14 (void) +{ + #pragma omp for + for (int i = 0; i < 100; ++i) + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test15 (void) +{ + #pragma omp for + for (int i = 0; i < 100; ++i) + { + dummy (i); + + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int j = -300; j != 100; ++j) + dummy (j); + + dummy (i); + } + } diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-2.c b/gcc/testsuite/c-c++-common/gomp/unroll-2.c new file mode 100644 index 0000000..41dc81f --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-2.c @@ -0,0 +1,122 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-prune-output "error: invalid controlling predicate" } */ + +extern void dummy (int); + +void +test (void) +{ + #pragma omp unroll partial + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + #pragma omp unroll partial + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll full + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll partial partial /* { dg-error "too many 'partial' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll full full /* { dg-error "too many 'full' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int i; + #pragma omp for /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll( /* { dg-error "expected an OpenMP clause before '\\\(' token" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll foo /* { dg-error "expected an OpenMP clause before 'foo'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial( /* { dg-error "expected expression before end of line" "" { target c } } */ + /* { dg-error "expected primary-expression before end of line" "" { target c++ } .-1 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial() /* { dg-error "expected expression before '\\\)' token" "" { target c } } */ + /* { dg-error "expected primary-expression before '\\\)' token" "" { target c++ } .-1 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial(i) + /* { dg-error "the value of 'i' is not usable in a constant expression" "" { target c++ } .-1 } */ + /* { dg-error "'partial' argument needs positive constant integer expression" "" { target *-*-* } .-2 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll parti /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll partial(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll parti /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll partial(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll parti /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int sum = 0; + #pragma omp parallel for reduction(+ : sum) collapse(2) + #pragma omp unroll partial(1) /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 3; i < 10; ++i) + for (int j = -2; j < 7; ++j) + sum++; + + #pragma omp unroll partial full /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll full partial /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(7) full /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll full partial(28) /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(0.5) /* { dg-error "'partial' argument needs positive constant integer expression" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(0) /* { dg-error "'partial' argument needs positive constant integer expression" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(-42) /* { dg-error "'partial' argument needs positive constant integer expression" } */ + for (int i = 0; i < 42; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-3.c b/gcc/testsuite/c-c++-common/gomp/unroll-3.c new file mode 100644 index 0000000..81cc385 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-3.c @@ -0,0 +1,16 @@ +/* { dg-additional-options "-O2 -fdump-tree-cunroll -fdump-tree-original -fdump-tree-gimple" } */ + +extern void dummy (int); + +void +test1 (void) +{ +#pragma omp unroll full + for (int i = 0; i < 10; i++) + dummy (i); +} + +/* Loop should be removed with 10 copies of the body remaining */ +/* { dg-final { scan-tree-dump-times "dummy" 10 "cunroll" } } */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-4.c b/gcc/testsuite/c-c++-common/gomp/unroll-4.c new file mode 100644 index 0000000..65c51cc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-4.c @@ -0,0 +1,18 @@ +/* { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } */ + +extern void dummy (int); + +void +test1 (void) +{ + int i; +#pragma omp unroll + for (int i = 0; i < 96; i++) + dummy (i); +} + +/* GCC unrolls the loop 8 times, but only during RTL optimizations. */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ +/* { dg-final { scan-tree-dump-times "dummy" 1 "gimple" } } */ +/* { dg-final { scan-assembler-times "dummy" 8 } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-5.c b/gcc/testsuite/c-c++-common/gomp/unroll-5.c new file mode 100644 index 0000000..415d421 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-5.c @@ -0,0 +1,18 @@ +/* { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } */ + +extern void dummy (int); + +void +test1 (void) +{ + int i; +#pragma omp unroll partial + for (int i = 0; i < 96; i++) + dummy (i); +} + +/* GCC uses partial(8) for this case. */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ +/* { dg-final { scan-tree-dump-times "dummy" 1 "gimple" } } */ +/* { dg-final { scan-assembler-times "dummy" 8 } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-6.c b/gcc/testsuite/c-c++-common/gomp/unroll-6.c new file mode 100644 index 0000000..840124d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-6.c @@ -0,0 +1,168 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include <stdio.h> + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +#define ASSERT_EQ_PTR(var, ptr) \ + do \ + { \ + if ((var) != (ptr)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %p, expected %p\n", \ + __FILE__, __LINE__, (var), (ptr)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +test1 (int data[10]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(8) + for (i = data; i < data + 10; i++) + { + ASSERT_EQ (*i, data[iter]); + ASSERT_EQ_PTR (i, data + iter); + iter++; + } + + return iter; +} + +int +test2 (int data[10]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(8) + for (i = data; i < data + 10; i = i + 2) + { + ASSERT_EQ_PTR (i, data + 2 * iter); + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + return iter; +} + +int +test3 (int data[10]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(8) + for (i = data; i <= data + 9; i = i + 2) + { + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + return iter; +} + +int +test4 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp unroll partial(8) + for (i = data; i != data + 10; i = i + 1) + { + ASSERT_EQ (*i, data[iter]); + iter++; + } + + return iter; +} + +int +test5 (int data[15]) +{ + int iter = 0; + int *i; + #pragma omp unroll partial(7) + for (i = data + 14; i >= data + 5; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +test6 (int data[15]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(7) + for (i = data + 14; i > data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +test7 (int data[10]) +{ + int iter = 0; + + #pragma omp unroll partial(7) + for (int *i = data + 14; i != data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +main () +{ + int iter_count; + int data[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int data2[15] = { -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + iter_count = test1 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test2 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test3 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test4 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test5 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test6 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test7 (data2); + ASSERT_EQ (iter_count, 10); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-7.c b/gcc/testsuite/c-c++-common/gomp/unroll-7.c new file mode 100644 index 0000000..b748061 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-7.c @@ -0,0 +1,18 @@ +extern void dummy (int); +int a[100]; + +void +test1 (void) +{ +#pragma omp unroll full + for (int i = -20; i < 20; i += 6) + dummy (i); +} + +void +test2 (void) +{ +#pragma omp unroll full + for (int *i = &a[6]; i < &a[78]; i += 4) + dummy (*i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-8.c b/gcc/testsuite/c-c++-common/gomp/unroll-8.c new file mode 100644 index 0000000..8cf0500 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-8.c @@ -0,0 +1,25 @@ +extern void dummy (int); + +void +test3 (int x) +{ +#pragma omp unroll full /* { dg-error "non-constant iteration count of 'unroll full' loop" } */ + for (int i = x; i < 20; i += 3) + dummy (i); +} + +void +test4 (int x) +{ +#pragma omp unroll full /* { dg-error "non-constant iteration count of 'unroll full' loop" } */ + for (int i = 5; i < x + 6; ++i) + dummy (i); +} + +void +test5 (int x) +{ +#pragma omp unroll full /* { dg-error "non-constant iteration count of 'unroll full' loop" } */ + for (int i = 5; i < 142; i += x) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-9.c b/gcc/testsuite/c-c++-common/gomp/unroll-9.c new file mode 100644 index 0000000..0930a3c06 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-9.c @@ -0,0 +1,13 @@ +/* { dg-additional-options "-O2 -fdump-tree-gimple" } */ + +void bar (int); + +void +foo (void) +{ + #pragma omp unroll full + for (int i = 1; i <= 100; i += 6) + bar (i); +} + +/* { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r]*, 1, 17\\\);" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-inner-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-inner-1.c new file mode 100644 index 0000000..5af2e29 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-inner-1.c @@ -0,0 +1,11 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp unroll partial + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-inner-2.c b/gcc/testsuite/c-c++-common/gomp/unroll-inner-2.c new file mode 100644 index 0000000..b28de6e --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-inner-2.c @@ -0,0 +1,18 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp tile sizes(2) + for (int j = 0; j != 100; ++j) + dummy (i); + + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp tile sizes(2, 3) + for (int j = 0; j != 100; ++j) + for (int k = 0; k != 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-inner-3.c b/gcc/testsuite/c-c++-common/gomp/unroll-inner-3.c new file mode 100644 index 0000000..cde8549 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-inner-3.c @@ -0,0 +1,11 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp tile sizes(2, 3) + for (int j = 0; j != 100; ++j) /* { dg-error "not enough nested loops" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-1.c new file mode 100644 index 0000000..fa39261 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-1.c @@ -0,0 +1,30 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp target parallel for collapse(3) + for (int i = -300; i != 100; ++i) + for (int j = i; j != i * 2; ++j) + #pragma omp unroll partial + for (int k = 2; k != 100; ++k) + dummy (i); + + #pragma omp unroll full + for (int i = -300; i != 100; ++i) + for (int j = i; j != i * 2; ++j) + for (int k = 2; k != 100; ++k) + dummy (i); + + for (int i = -300; i != 100; ++i) + #pragma omp unroll full + for (int j = i; j != i + 10; ++j) + for (int k = 2; k != 100; ++k) + dummy (i); + + for (int i = -300; i != 100; ++i) + #pragma omp unroll full + for (int j = i; j != i + 10; ++j) + for (int k = j; k != 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-2.c b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-2.c new file mode 100644 index 0000000..c4043f5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-2.c @@ -0,0 +1,22 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp unroll partial + for (int j = 2; j != i; ++j) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + dummy (i); +} + +void +test2 (void) +{ + int i,j; + #pragma omp target parallel for collapse(2) + for (i = -300; i != 100; ++i) + #pragma omp unroll partial + for (j = 2; j != i; ++j) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-3.c b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-3.c new file mode 100644 index 0000000..c371fca --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-3.c @@ -0,0 +1,11 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp unroll partial(2) + for (int j = i * 2; j <= i * 4 + 1; ++j) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-simd-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-simd-1.c new file mode 100644 index 0000000..aaef63c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-simd-1.c @@ -0,0 +1,70 @@ +/* { dg-do run } */ +/* { dg-options "-fno-openmp -fopenmp-simd -fdump-tree-original -fdump-tree-gimple" } */ + +int +compute_sum1 (void) +{ + int sum = 0; + int i, j; + + #pragma omp simd reduction(+:sum) + for (i = 3; i < 10; ++i) + #pragma omp unroll full + for (j = -2; j < 7; ++j) + sum++; + + if (i != 10 || j != 7) + __builtin_abort (); + + return sum; +} + +int +compute_sum2 (void) +{ + int sum = 0; + int i, j; + + #pragma omp simd reduction(+:sum) + #pragma omp unroll partial(5) + for (i = 3; i < 10; ++i) + for (j = -2; j < 7; ++j) + sum++; + + if (i != 10 || j != 7) + __builtin_abort (); + + return sum; +} + +int +compute_sum3 (void) +{ + int sum = 0; + int i, j; + + #pragma omp simd reduction(+:sum) + #pragma omp unroll partial(1) + for (i = 3; i < 10; ++i) + for (j = -2; j < 7; ++j) + sum++; + + if (i != 10 || j != 7) + __builtin_abort (); + + return sum; +} + +int +main () +{ + if (compute_sum1 () != 7 * 9 + || compute_sum2 () != 7 * 9 + || compute_sum3 () != 7 * 9) + __builtin_abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump {omp unroll} "original" } } */ +/* { dg-final { scan-tree-dump-not {omp unroll} "gimple" } } */ |