diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 9cc95ab3ee376628dbef2485b84e6008210fa8fc..99cf2e8bd1c05537c198470f1aaa0a5a9da4e576 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -87,6 +87,7 @@ enum pragma_kind { PRAGMA_GCC_PCH_PREPROCESS, PRAGMA_IVDEP, PRAGMA_UNROLL, + PRAGMA_NOVECTOR, PRAGMA_FIRST_EXTERNAL }; diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc index 0d2b333cebbed32423d5dc6fd2a3ac0ce0bf8b94..848a850b8e123ff1c6ae1ec4b7f8ccbd599b1a88 100644 --- a/gcc/c-family/c-pragma.cc +++ b/gcc/c-family/c-pragma.cc @@ -1862,6 +1862,10 @@ init_pragma (void) cpp_register_deferred_pragma (parse_in, "GCC", "unroll", PRAGMA_UNROLL, false, false); + if (!flag_preprocess_only) + cpp_register_deferred_pragma (parse_in, "GCC", "novector", PRAGMA_NOVECTOR, + false, false); + #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION c_register_pragma_with_expansion (0, "pack", handle_pragma_pack); #else diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 24a6eb6e4596f32c477e3f1c3f98b9792f7bc92c..4c64d898cddac437958ce20c5603b88a05a99093 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1572,9 +1572,11 @@ static tree c_parser_c99_block_statement (c_parser *, bool *, location_t * = NULL); static void c_parser_if_statement (c_parser *, bool *, vec *); static void c_parser_switch_statement (c_parser *, bool *); -static void c_parser_while_statement (c_parser *, bool, unsigned short, bool *); -static void c_parser_do_statement (c_parser *, bool, unsigned short); -static void c_parser_for_statement (c_parser *, bool, unsigned short, bool *); +static void c_parser_while_statement (c_parser *, bool, unsigned short, bool, + bool *); +static void c_parser_do_statement (c_parser *, bool, unsigned short, bool); +static void c_parser_for_statement (c_parser *, bool, unsigned short, bool, + bool *); static tree c_parser_asm_statement (c_parser *); static tree c_parser_asm_operands (c_parser *); static tree c_parser_asm_goto_operands (c_parser *); @@ -6644,13 +6646,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, c_parser_switch_statement (parser, if_p); break; case RID_WHILE: - c_parser_while_statement (parser, false, 0, if_p); + c_parser_while_statement (parser, false, 0, false, if_p); break; case RID_DO: - c_parser_do_statement (parser, false, 0); + c_parser_do_statement (parser, false, 0, false); break; case RID_FOR: - c_parser_for_statement (parser, false, 0, if_p); + c_parser_for_statement (parser, false, 0, false, if_p); break; case RID_GOTO: c_parser_consume_token (parser); @@ -7146,7 +7148,7 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) static void c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, - bool *if_p) + bool novector, bool *if_p) { tree block, cond, body; unsigned char save_in_statement; @@ -7168,6 +7170,11 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); save_in_statement = in_statement; in_statement = IN_ITERATION_STMT; @@ -7199,7 +7206,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, */ static void -c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) +c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll, + bool novector) { tree block, cond, body; unsigned char save_in_statement; @@ -7228,6 +7236,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); @@ -7296,7 +7309,7 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) static void c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, - bool *if_p) + bool novector, bool *if_p) { tree block, cond, incr, body; unsigned char save_in_statement; @@ -7430,6 +7443,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, "with % pragma"); cond = error_mark_node; } + else if (novector) + { + c_parser_error (parser, "missing loop condition in loop " + "with % pragma"); + cond = error_mark_node; + } else { c_parser_consume_token (parser); @@ -7452,6 +7471,11 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); } /* Parse the increment expression (the third expression in a for-statement). In the case of a foreach-statement, this is @@ -13037,6 +13061,16 @@ c_parse_pragma_ivdep (c_parser *parser) return true; } +/* Parse a pragma GCC novector. */ + +static bool +c_parse_pragma_novector (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + return true; +} + /* Parse a pragma GCC unroll. */ static unsigned short @@ -13261,38 +13295,50 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_ORDERED: return c_parser_omp_ordered (parser, context, if_p); + case PRAGMA_NOVECTOR: + case PRAGMA_UNROLL: case PRAGMA_IVDEP: { - const bool ivdep = c_parse_pragma_ivdep (parser); - unsigned short unroll; - if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_UNROLL) - unroll = c_parser_pragma_unroll (parser); - else - unroll = 0; - if (!c_parser_next_token_is_keyword (parser, RID_FOR) - && !c_parser_next_token_is_keyword (parser, RID_WHILE) - && !c_parser_next_token_is_keyword (parser, RID_DO)) + bool novector = false; + unsigned short unroll = 0; + bool ivdep = false; + + switch (id) { - c_parser_error (parser, "for, while or do statement expected"); - return false; + case PRAGMA_NOVECTOR: + novector = c_parse_pragma_novector (parser); + break; + case PRAGMA_UNROLL: + unroll = c_parser_pragma_unroll (parser); + break; + case PRAGMA_IVDEP: + ivdep = c_parse_pragma_ivdep (parser); + break; + default: + gcc_unreachable (); } - if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, ivdep, unroll, if_p); - else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, ivdep, unroll, if_p); - else - c_parser_do_statement (parser, ivdep, unroll); - } - return true; - case PRAGMA_UNROLL: - { - unsigned short unroll = c_parser_pragma_unroll (parser); - bool ivdep; - if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_IVDEP) - ivdep = c_parse_pragma_ivdep (parser); - else - ivdep = false; + c_token *tok = c_parser_peek_token (parser); + while (tok->type == CPP_PRAGMA) + { + switch (tok->pragma_kind) + { + case PRAGMA_IVDEP: + ivdep = c_parse_pragma_ivdep (parser); + tok = c_parser_peek_token (parser); + break; + case PRAGMA_UNROLL: + unroll = c_parser_pragma_unroll (parser); + tok = c_parser_peek_token (parser); + break; + case PRAGMA_NOVECTOR: + novector = c_parse_pragma_novector (parser); + tok = c_parser_peek_token (parser); + break; + default: + gcc_unreachable (); + } + } if (!c_parser_next_token_is_keyword (parser, RID_FOR) && !c_parser_next_token_is_keyword (parser, RID_WHILE) && !c_parser_next_token_is_keyword (parser, RID_DO)) @@ -13301,11 +13347,11 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) return false; } if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, ivdep, unroll, if_p); + c_parser_for_statement (parser, ivdep, unroll, novector, if_p); else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, ivdep, unroll, if_p); + c_parser_while_statement (parser, ivdep, unroll, novector, if_p); else - c_parser_do_statement (parser, ivdep, unroll); + c_parser_do_statement (parser, ivdep, unroll, novector); } return true; diff --git a/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c b/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c new file mode 100644 index 0000000000000000000000000000000000000000..3c0b8f5d2acbd276280785e8d0cbe1f7cd650266 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +void f1 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC novector + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f2 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC novector +#pragma GCC ivdep +#pragma GCC unroll 2 + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f3 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC ivdep +#pragma GCC novector +#pragma GCC unroll 2 + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f4 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC ivdep +#pragma GCC unroll 2 +#pragma GCC novector + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f5 (int * restrict a, int * restrict b, int n) +{ + int i = 0; +#pragma GCC novector + do + { + a[i] += b[i]; + i++; + } + while (i < (n & -8)); +} + +void f6 (int * restrict a, int * restrict b, int n) +{ + int i = 0; +#pragma GCC novector + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */