From 21dfb22920ce32fcf336eac4513fa44de28819e0 Mon Sep 17 00:00:00 2001 From: Stefan Schulze Frielinghaus Date: Tue, 11 May 2021 19:33:37 +0200 Subject: testsuite: Fix input operands of gcc.dg/guality/pr43077-1.c The type of the output operands *p and *q of the extended asm statement of function foo is unsigned long whereas the type of the corresponding input operands is int. This results, e.g. on IBM Z, in the case that the immediates 2 and 3 are written into registers in SI mode and read in DI mode resulting in wrong values. Fixed by lifting the input operands to type long. gcc/testsuite/ChangeLog: * gcc.dg/guality/pr43077-1.c: Align types of output and input operands by lifting immediates to type long. --- gcc/testsuite/gcc.dg/guality/pr43077-1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/guality/pr43077-1.c b/gcc/testsuite/gcc.dg/guality/pr43077-1.c index 39bd26a..2d93762 100644 --- a/gcc/testsuite/gcc.dg/guality/pr43077-1.c +++ b/gcc/testsuite/gcc.dg/guality/pr43077-1.c @@ -24,7 +24,7 @@ int __attribute__((noinline)) foo (unsigned long *p, unsigned long *q) { int ret; - asm volatile ("" : "=r" (ret), "=r" (*p), "=r" (*q) : "0" (1), "1" (2), "2" (3)); + asm volatile ("" : "=r" (ret), "=r" (*p), "=r" (*q) : "0" (1), "1" (2l), "2" (3l)); return ret; } -- cgit v1.1 From 3e3fdf3d5217e5a2d075ca399b557b2e886dcd18 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 11 May 2021 18:54:32 +0000 Subject: preprocessor: Fix cpp_avoid_paste for digit separators The libcpp function cpp_avoid_paste is used to insert whitespace in preprocessed output where needed to avoid two consecutive preprocessing tokens, that logically (e.g. when stringized) do not have whitespace between them, from being incorrectly lexed as one when the preprocessed input is reread by a compiler. This fails to allow for digit separators, so meaning that invalid code, that has a CPP_NUMBER (from a macro expansion) followed by a character literal, can result in preprocessed output with a valid use of digit separators, so that required syntax errors do not occur when compiling with -save-temps. Fix this by handling that case in cpp_avoid_paste (as with other cases in cpp_avoid_paste, this doesn't try to check whether the language version in use supports digit separators; it's always OK to have unnecessary whitespace in preprocessed output). Note: there are other cases, with various kinds of wide character or string literal following a CPP_NUMBER, where spurious pasting of preprocessing tokens can occur but the sequence of tokens remains invalid both before and after that pasting. Maybe cpp_avoid_paste should also handle those cases (and similar cases after a CPP_NAME), to ensure the sequence of preprocessing tokens in preprocessed output is exactly right, whether or not it affects whether syntax errors occur. This patch only addresses the case with digit separators where invalid code can fail to be diagnosed without the space inserted. Bootstrapped with no regressions for x86_64-pc-linux-gnu. libcpp/ * lex.c (cpp_avoid_paste): Do not allow pasting CPP_NUMBER with CPP_CHAR. gcc/testsuite/ * g++.dg/cpp1y/digit-sep-paste.C, gcc.dg/c2x-digit-separators-3.c: New tests. --- gcc/testsuite/g++.dg/cpp1y/digit-sep-paste.C | 11 +++++++++++ gcc/testsuite/gcc.dg/c2x-digit-separators-3.c | 12 ++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/digit-sep-paste.C create mode 100644 gcc/testsuite/gcc.dg/c2x-digit-separators-3.c (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-paste.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-paste.C new file mode 100644 index 0000000..41fb967 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep-paste.C @@ -0,0 +1,11 @@ +// Test token pasting with digit separators avoided for preprocessed output. +// { dg-do compile { target c++14 } } +// { dg-options "-save-temps" } + +#define ZERO 0 + +int +f () +{ + return ZERO'0'0; /* { dg-error "expected" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-digit-separators-3.c b/gcc/testsuite/gcc.dg/c2x-digit-separators-3.c new file mode 100644 index 0000000..cddb88f --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-digit-separators-3.c @@ -0,0 +1,12 @@ +/* Test C2x digit separators. Test token pasting avoided for preprocessed + output. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -save-temps" } */ + +#define ZERO 0 + +int +f (void) +{ + return ZERO'0'0; /* { dg-error "expected" } */ +} -- cgit v1.1 From de09c0ddb81e2dc0e35c2e362532e93ca417200c Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 11 May 2021 13:58:48 -0600 Subject: Replace unreachable code with an assert. Resolves: PR middle-end/21433 - The COMPONENT_REF case of expand_expr_real_1 is probably wrong gcc/ChangeLog: PR middle-end/21433 * expr.c (expand_expr_real_1): Replace unreachable code with an assert. --- gcc/expr.c | 57 ++------------------------------------------------------- 1 file changed, 2 insertions(+), 55 deletions(-) (limited to 'gcc') diff --git a/gcc/expr.c b/gcc/expr.c index 1b65f6b..d09ee42 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -10949,61 +10949,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, goto normal_inner_ref; case COMPONENT_REF: - /* If the operand is a CONSTRUCTOR, we can just extract the - appropriate field if it is present. */ - if (TREE_CODE (treeop0) == CONSTRUCTOR) - { - unsigned HOST_WIDE_INT idx; - tree field, value; - scalar_int_mode field_mode; - - FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (treeop0), - idx, field, value) - if (field == treeop1 - /* We can normally use the value of the field in the - CONSTRUCTOR. However, if this is a bitfield in - an integral mode that we can fit in a HOST_WIDE_INT, - we must mask only the number of bits in the bitfield, - since this is done implicitly by the constructor. If - the bitfield does not meet either of those conditions, - we can't do this optimization. */ - && (! DECL_BIT_FIELD (field) - || (is_int_mode (DECL_MODE (field), &field_mode) - && (GET_MODE_PRECISION (field_mode) - <= HOST_BITS_PER_WIDE_INT)))) - { - if (DECL_BIT_FIELD (field) - && modifier == EXPAND_STACK_PARM) - target = 0; - op0 = expand_expr (value, target, tmode, modifier); - if (DECL_BIT_FIELD (field)) - { - HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)); - scalar_int_mode imode - = SCALAR_INT_TYPE_MODE (TREE_TYPE (field)); - - if (TYPE_UNSIGNED (TREE_TYPE (field))) - { - op1 = gen_int_mode ((HOST_WIDE_INT_1 << bitsize) - 1, - imode); - op0 = expand_and (imode, op0, op1, target); - } - else - { - int count = GET_MODE_PRECISION (imode) - bitsize; - - op0 = expand_shift (LSHIFT_EXPR, imode, op0, count, - target, 0); - op0 = expand_shift (RSHIFT_EXPR, imode, op0, count, - target, 0); - } - } - - return op0; - } - } - goto normal_inner_ref; - + gcc_assert (TREE_CODE (treeop0) != CONSTRUCTOR); + /* Fall through. */ case BIT_FIELD_REF: case ARRAY_RANGE_REF: normal_inner_ref: -- cgit v1.1 From 415bcabf134b90794a134ca5dadfaf44496645d5 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 11 May 2021 21:06:33 +0000 Subject: Update gcc ja.po. * ja.po: Update. --- gcc/po/ja.po | 84 ++++++++++++++++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 48 deletions(-) (limited to 'gcc') diff --git a/gcc/po/ja.po b/gcc/po/ja.po index 049450e..4199919 100644 --- a/gcc/po/ja.po +++ b/gcc/po/ja.po @@ -19,10 +19,10 @@ # Hiroshi Takekawa , , 2020, 2021 msgid "" msgstr "" -"Project-Id-Version: gcc 11.1-b20210207\n" +"Project-Id-Version: gcc 11.1.0\n" "Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n" "POT-Creation-Date: 2021-04-20 18:19+0000\n" -"PO-Revision-Date: 2021-02-10 19:45+0900\n" +"PO-Revision-Date: 2021-05-11 22:47+0900\n" "Last-Translator: Hiroshi Takekawa \n" "Language-Team: Japanese \n" "Language: ja\n" @@ -512,10 +512,6 @@ msgid "" " 'none' means revert to the default behavior of\n" " guessing the language based on the file's extension.\n" msgstr "" -" -x これ以降入力するファイルの言語を指定する。\n" -" 指定可能な言語は: c c++ assembler none\n" -" 'none' が指定されるとデフォルトのふるまいである\n" -" 拡張子から言語を推測する。\n" #: gcc.c:3798 #, c-format @@ -908,14 +904,14 @@ msgid " -p, --preserve-paths Preserve all pathname components\n" msgstr " -p, --preserve-paths すべてのパス名要素を保護する\n" #: gcov.c:944 -#, fuzzy, c-format +#, c-format msgid " -q, --use-hotness-colors Emit perf-like colored output for hot lines\n" -msgstr " -n, --no-output 出力ファイルを作成しない\n" +msgstr " -q, --use-hotness-colors perf のように hot line に色をつける\n" #: gcov.c:945 -#, fuzzy, c-format +#, c-format msgid " -r, --relative-only Only show data for relative sources\n" -msgstr " -a, --all-blocks 各基本ブロックに関する情報を表示する\n" +msgstr " -r, --relative-only 相対ソースのデータのみ表示する\n" #: gcov.c:946 #, c-format @@ -1498,9 +1494,8 @@ msgid "function not considered for inlining" msgstr "inline に出来ると見なされていない関数です" #: cif-code.def:43 -#, fuzzy msgid "caller is not optimized" -msgstr "%qE は初期化されていません" +msgstr "caller は最適化されていません" #: cif-code.def:47 msgid "function body not available" @@ -1596,9 +1591,8 @@ msgid "callee refers to comdat-local symbols" msgstr "" #: cif-code.def:134 -#, fuzzy msgid "sanitizer function attribute mismatch" -msgstr "関数属性が合いません" +msgstr "sanitizer関数属性が合いません" #: cif-code.def:139 msgid "function has external linkage when the user requests only inlining static for live patching" @@ -1993,14 +1987,12 @@ msgid "invalid address mode" msgstr "無効なアドレスモードです" #: config/aarch64/aarch64.c:25211 config/arm/arm.c:33660 -#, fuzzy msgid "invalid conversion from type %" -msgstr "%<__fpreg%> からの無効な変換です" +msgstr "% からの無効な変換です" #: config/aarch64/aarch64.c:25213 config/arm/arm.c:33662 -#, fuzzy msgid "invalid conversion to type %" -msgstr "無効なバージョン番号形式" +msgstr "% への無効な変換です" #: config/aarch64/aarch64.c:25228 config/aarch64/aarch64.c:25244 #: config/arm/arm.c:33677 config/arm/arm.c:33693 @@ -2008,9 +2000,8 @@ msgid "operation not permitted on type %" msgstr "" #: config/aarch64/aarch64.c:25252 -#, fuzzy msgid "cannot combine GNU and SVE vectors in a binary operation" -msgstr "二進演算内で無効な被演算子です" +msgstr "GNU と SVE ベクタの二項演算はできません" #: config/alpha/alpha.c:5076 config/i386/i386.c:13227 #: config/rs6000/rs6000.c:14147 config/sparc/sparc.c:9323 @@ -2233,9 +2224,8 @@ msgid "operands to %T/%t must be reg + const_int:" msgstr "出力被演算子 %d は %<&%> 制約を使用しなければいけません" #: config/avr/avr.c:2863 config/avr/avr.c:2930 -#, fuzzy msgid "bad address, not an I/O address:" -msgstr "誤ったアドレスです。(reg+disp) ではありません:" +msgstr "誤ったアドレスです。I/O アドレスではありません:" #: config/avr/avr.c:2872 msgid "bad address, not a constant:" @@ -2304,9 +2294,8 @@ msgid "structure field" msgstr "構造体フィールド" #: config/avr/avr.c:10039 -#, fuzzy msgid "return type of function" -msgstr "`%s' の宣言は関数の配列" +msgstr "関数の戻り値の型" #: config/avr/avr.c:10044 msgid "pointer" @@ -2567,9 +2556,9 @@ msgid "operand %%xn code invalid for QImode" msgstr "被演算子は条件コードではありません。無効な被演算子コード 'Y' です" #: config/gcn/gcn.c:6171 -#, fuzzy, c-format +#, c-format msgid "invalid fp constant" -msgstr "無効な命令:" +msgstr "無効な浮動小数点定数です" #: config/h8300/h8300.c:1565 config/h8300/h8300.c:1573 #: config/h8300/h8300.c:1581 config/h8300/h8300.c:1589 @@ -2584,9 +2573,9 @@ msgid "invalid UNSPEC as operand" msgstr "被演算子として無効な UNSPEC です" #: config/i386/i386.c:12591 -#, fuzzy, c-format +#, c-format msgid "invalid use of register '%s'" -msgstr "% の誤った使用法です" +msgstr "'%s' の誤った用法です" #: config/i386/i386.c:12596 #, fuzzy, c-format @@ -2673,9 +2662,9 @@ msgid "unknown insn mode" msgstr "不明な命令モード" #: config/i386/djgpp.h:143 -#, fuzzy, c-format +#, c-format msgid "-f%s ignored (not supported for DJGPP)\n" -msgstr "Unicos/Mk 用としては -f%s は無視されました (サポートされていません)" +msgstr "-f%s は (DJGPP ではサポートされていないので) 無視されました\n" #: config/ia64/ia64.c:5459 #, c-format @@ -2874,14 +2863,14 @@ msgid "invalid zero extract" msgstr "% の誤った使用法です" #: config/or1k/or1k.c:1116 config/or1k/or1k.c:1124 -#, fuzzy, c-format +#, c-format msgid "invalid relocation" -msgstr "無効な %%d 被演算子です" +msgstr "無効な再配置です" #: config/or1k/or1k.c:1218 -#, fuzzy, c-format +#, c-format msgid "invalid %%H value" -msgstr "無効な %%J 値" +msgstr "無効な %%H 値" #: config/or1k/or1k.c:1231 config/xtensa/xtensa.c:2473 #, c-format @@ -2919,14 +2908,14 @@ msgid "unsupported operand %s for code '%c'" msgstr "コード '%c' に対する無効な被演算子です" #: config/pru/pru.c:1870 -#, fuzzy, c-format +#, c-format msgid "unexpected text address:" -msgstr "アドレス内の予期しない副作用" +msgstr "予期しないテキストアドレス:" #: config/pru/pru.c:1889 -#, fuzzy, c-format +#, c-format msgid "unsupported constant address:" -msgstr "サポートされていない組み合わせです: %s" +msgstr "サポートされていない定数アドレス:" #: config/pru/pru.c:1950 #, fuzzy, c-format @@ -2991,7 +2980,7 @@ msgid "Bad 128-bit move" msgstr "誤った 128 ビット move" #: config/rs6000/rs6000.c:13589 -#, fuzzy, c-format +#, c-format msgid "invalid %%A value" msgstr "無効な %%A 値" @@ -3001,7 +2990,7 @@ msgid "invalid %%D value" msgstr "無効な %%D 値です" #: config/rs6000/rs6000.c:13613 -#, fuzzy, c-format +#, c-format msgid "invalid %%e value" msgstr "無効な %%e 値" @@ -3051,7 +3040,7 @@ msgid "invalid %%q value" msgstr "無効な %%q 値です" #: config/rs6000/rs6000.c:13858 -#, fuzzy, c-format +#, c-format msgid "invalid %%t value" msgstr "無効な %%t 値" @@ -3081,9 +3070,9 @@ msgid "invalid %%x value" msgstr "無効な %%x 値です" #: config/rs6000/rs6000.c:14025 -#, fuzzy, c-format +#, c-format msgid "invalid %%z value" -msgstr "無効な %%J 値" +msgstr "無効な %%z 値" #: config/rs6000/rs6000.c:14094 #, c-format @@ -3114,14 +3103,12 @@ msgid "Bad GPR fusion" msgstr "" #: config/rs6000/rs6000.c:27776 -#, fuzzy msgid "invalid conversion from type %<__vector_quad%>" -msgstr "%<__fpreg%> からの無効な変換です" +msgstr "%<__vector_quad%> からの無効な変換です" #: config/rs6000/rs6000.c:27778 -#, fuzzy msgid "invalid conversion to type %<__vector_quad%>" -msgstr "無効なバージョン番号形式" +msgstr "%<__vector_quad%> への無効な変換です" #: config/rs6000/rs6000.c:27780 #, fuzzy @@ -58665,8 +58652,9 @@ msgstr "クラス名が予期されます" #: d/dmd/dsymbolsem.c:1372 #, fuzzy, gcc-internal-format +#| msgid "unexpected text address:" msgid "function name expected for start address" -msgstr "アドレス内の予期しない副作用" +msgstr "予期しないテキストアドレス:" #: d/dmd/dsymbolsem.c:1387 #, gcc-internal-format, gfc-internal-format -- cgit v1.1 From 71d38ec80008afdbb9a059253407d80598b765c0 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 11 May 2021 23:54:01 +0000 Subject: preprocessor: Support C2X #elifdef, #elifndef C2X adds #elifdef and #elifndef preprocessor directives; these have also been proposed for C++. Implement these directives in libcpp accordingly. In this implementation, #elifdef and #elifndef are treated as non-directives for any language version other than c2x and gnu2x (if the feature is accepted for C++, it can trivially be enabled for relevant C++ versions). In strict conformance modes for prior language versions, this is required, as illustrated by the c11-elifdef-1.c test added. Bootstrapped with no regressions for x86_64-pc-linux-gnu. libcpp/ * include/cpplib.h (struct cpp_options): Add elifdef. * init.c (struct lang_flags): Add elifdef. (lang_defaults): Update to include elifdef initializers. (cpp_set_lang): Set elifdef for pfile based on language. * directives.c (STDC2X, ELIFDEF): New macros. (EXTENSION): Increase value to 3. (DIRECTIVE_TABLE): Add #elifdef and #elifndef. (_cpp_handle_directive): Do not treat ELIFDEF directives as directives for language versions without the #elifdef feature. (do_elif): Handle #elifdef and #elifndef. (do_elifdef, do_elifndef): New functions. gcc/testsuite/ * gcc.dg/cpp/c11-elifdef-1.c, gcc.dg/cpp/c2x-elifdef-1.c, gcc.dg/cpp/c2x-elifdef-2.c: New tests. --- gcc/testsuite/gcc.dg/cpp/c11-elifdef-1.c | 16 ++++++++ gcc/testsuite/gcc.dg/cpp/c2x-elifdef-1.c | 57 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/cpp/c2x-elifdef-2.c | 63 ++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/cpp/c11-elifdef-1.c create mode 100644 gcc/testsuite/gcc.dg/cpp/c2x-elifdef-1.c create mode 100644 gcc/testsuite/gcc.dg/cpp/c2x-elifdef-2.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/cpp/c11-elifdef-1.c b/gcc/testsuite/gcc.dg/cpp/c11-elifdef-1.c new file mode 100644 index 0000000..2d5809a --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/c11-elifdef-1.c @@ -0,0 +1,16 @@ +/* Test #elifdef and #elifndef not in C11. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +#define A +#undef B + +#if 0 +#elifdef A +#error "#elifdef A applied" +#endif + +#if 0 +#elifndef B +#error "#elifndef B applied" +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/c2x-elifdef-1.c b/gcc/testsuite/gcc.dg/cpp/c2x-elifdef-1.c new file mode 100644 index 0000000..b23e311 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/c2x-elifdef-1.c @@ -0,0 +1,57 @@ +/* Test #elifdef and #elifndef in C2x. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#define A +#undef B + +#if 0 +#elifdef A +#define M1 1 +#endif + +#if M1 != 1 +#error "#elifdef A did not apply" +#endif + +#if 0 +#elifdef B +#error "#elifdef B applied" +#endif + +#if 0 +#elifndef A +#error "#elifndef A applied" +#endif + +#if 0 +#elifndef B +#define M2 2 +#endif + +#if M2 != 2 +#error "#elifndef B did not apply" +#endif + +#if 0 +#elifdef A +#else +#error "#elifdef A did not apply" +#endif + +#if 0 +#elifndef B +#else +#error "#elifndef B did not apply" +#endif + +/* As with #elif, the syntax of the new directives is relaxed after a + non-skipped group. */ + +#if 1 +#elifdef x * y +#endif + +#if 1 +#elifndef ! +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/c2x-elifdef-2.c b/gcc/testsuite/gcc.dg/cpp/c2x-elifdef-2.c new file mode 100644 index 0000000..9132832 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/c2x-elifdef-2.c @@ -0,0 +1,63 @@ +/* Test #elifdef and #elifndef in C2x: erroneous usages. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#define A +#undef B + +#elifdef A /* { dg-error "#elifdef without #if" } */ +#elifdef B /* { dg-error "#elifdef without #if" } */ +#elifndef A /* { dg-error "#elifndef without #if" } */ +#elifndef B /* { dg-error "#elifndef without #if" } */ + +#if 1 /* { dg-error "-:began here" } */ +#else +#elifdef A /* { dg-error "#elifdef after #else" } */ +#endif + +#if 1 /* { dg-error "-:began here" } */ +#else +#elifdef B /* { dg-error "#elifdef after #else" } */ +#endif + +#if 1 /* { dg-error "-:began here" } */ +#else +#elifndef A /* { dg-error "#elifndef after #else" } */ +#endif + +#if 1 /* { dg-error "-:began here" } */ +#else +#elifndef B /* { dg-error "#elifndef after #else" } */ +#endif + +#if 0 +#elifdef A = /* { dg-error "extra tokens at end of #elifdef directive" } */ +#endif + +#if 0 +#elifdef B = /* { dg-error "extra tokens at end of #elifdef directive" } */ +#endif + +#if 0 +#elifndef A = /* { dg-error "extra tokens at end of #elifndef directive" } */ +#endif + +#if 0 +#elifndef B = /* { dg-error "extra tokens at end of #elifndef directive" } */ +#endif + +#if 0 +#elifdef /* { dg-error "no macro name given in #elifdef directive" } */ +#endif + +#if 0 +#elifndef /* { dg-error "no macro name given in #elifndef directive" } */ +#endif + +#if 0 +#elifdef , /* { dg-error "macro names must be identifiers" } */ +#endif + +#if 0 +#elifndef , /* { dg-error "macro names must be identifiers" } */ +#endif -- cgit v1.1 From b1f7fd8a2a5558da1e101de11bb1cdba081ce010 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 12 May 2021 08:11:18 +0200 Subject: i386: Implement FP vector compares for V2SFmode [PR98218] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement FP vector compares for V2SFmode for TARGET_MMX_WITH_SSE. 2021-05-12 Uroš Bizjak gcc/ PR target/98218 * config/i386/i386-expand.c (ix86_expand_sse_movcc): Handle V2SF mode. * config/i386/mmx.md (MMXMODE124): New mode iterator. (V2FI): Ditto. (mmxintvecmode): New mode attribute. (mmxintvecmodelower): Ditto. (*mmx_maskcmpv2sf3_comm): New insn pattern. (*mmx_maskcmpv2sf3): Ditto. (vec_cmpv2sfv2si): New expander. (vcondv2si): Ditto. (mmx_vlendvps): New insn pattern. (vcond): Also handle V2SFmode. (vcondu): Ditto. (vcond_mask_): Ditto. gcc/testsuite/ PR target/98218 * g++.target/i386/pr98218-1.C: Ditto. * gcc.target/i386/pr98218-4.c: New test. * gcc.target/i386/pr98218-1.c: Correct PR number. * gcc.target/i386/pr98218-1a.c: Ditto. * gcc.target/i386/pr98218-2.c: Ditto. * gcc.target/i386/pr98218-2a.c: Ditto. * gcc.target/i386/pr98218-3.c: Ditto. * gcc.target/i386/pr98218-3a.c: Ditto. --- gcc/config/i386/i386-expand.c | 7 ++ gcc/config/i386/mmx.md | 130 +++++++++++++++++++++++++---- gcc/testsuite/g++.target/i386/pr98218-1.C | 20 +++++ gcc/testsuite/gcc.target/i386/pr98218-1.c | 2 +- gcc/testsuite/gcc.target/i386/pr98218-1a.c | 2 +- gcc/testsuite/gcc.target/i386/pr98218-2.c | 2 +- gcc/testsuite/gcc.target/i386/pr98218-2a.c | 2 +- gcc/testsuite/gcc.target/i386/pr98218-3.c | 2 +- gcc/testsuite/gcc.target/i386/pr98218-3a.c | 2 +- gcc/testsuite/gcc.target/i386/pr98218-4.c | 16 ++++ 10 files changed, 161 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.target/i386/pr98218-1.C create mode 100644 gcc/testsuite/gcc.target/i386/pr98218-4.c (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 5cfde5b..dd23008 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -3680,6 +3680,13 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false) switch (mode) { + case E_V2SFmode: + if (TARGET_SSE4_1) + { + gen = gen_mmx_blendvps; + op_true = force_reg (mode, op_true); + } + break; case E_V4SFmode: if (TARGET_SSE4_1) gen = gen_sse4_1_blendvps; diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index f085708..d433c52 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -49,6 +49,7 @@ ;; All 8-byte vector modes handled by MMX (define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF]) +(define_mode_iterator MMXMODE124 [V8QI V4HI V2SI V2SF]) ;; Mix-n-match (define_mode_iterator MMXMODE12 [V8QI V4HI]) @@ -56,12 +57,22 @@ (define_mode_iterator MMXMODE24 [V4HI V2SI]) (define_mode_iterator MMXMODE248 [V4HI V2SI V1DI]) +;; All V2S* modes +(define_mode_iterator V2FI [V2SF V2SI]) + ;; Mapping from integer vector mode to mnemonic suffix (define_mode_attr mmxvecsize [(V8QI "b") (V4HI "w") (V2SI "d") (V1DI "q")]) (define_mode_attr mmxdoublemode [(V8QI "V8HI") (V4HI "V4SI")]) +;; Mapping of vector float modes to an integer mode of the same size +(define_mode_attr mmxintvecmode + [(V2SF "V2SI") (V2SI "V2SI") (V4HI "V4HI") (V8QI "V8QI")]) + +(define_mode_attr mmxintvecmodelower + [(V2SF "v2si") (V2SI "v2si") (V4HI "v4hi") (V8QI "v8qi")]) + (define_mode_attr Yv_Yw [(V8QI "Yw") (V4HI "Yw") (V2SI "Yv") (V1DI "Yv") (V2SF "Yv")]) @@ -714,6 +725,85 @@ (set_attr "prefix_extra" "1") (set_attr "mode" "V2SF")]) +(define_insn "*mmx_maskcmpv2sf3_comm" + [(set (match_operand:V2SF 0 "register_operand" "=x,x") + (match_operator:V2SF 3 "sse_comparison_operator" + [(match_operand:V2SF 1 "register_operand" "%0,x") + (match_operand:V2SF 2 "register_operand" "x,x")]))] + "TARGET_MMX_WITH_SSE + && GET_RTX_CLASS (GET_CODE (operands[3])) == RTX_COMM_COMPARE" + "@ + cmp%D3ps\t{%2, %0|%0, %2} + vcmp%D3ps\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "ssecmp") + (set_attr "length_immediate" "1") + (set_attr "prefix" "orig,vex") + (set_attr "mode" "V4SF")]) + +(define_insn "*mmx_maskcmpv2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=x,x") + (match_operator:V2SF 3 "sse_comparison_operator" + [(match_operand:V2SF 1 "register_operand" "0,x") + (match_operand:V2SF 2 "register_operand" "x,x")]))] + "TARGET_MMX_WITH_SSE" + "@ + cmp%D3ps\t{%2, %0|%0, %2} + vcmp%D3ps\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "ssecmp") + (set_attr "length_immediate" "1") + (set_attr "prefix" "orig,vex") + (set_attr "mode" "V4SF")]) + +(define_expand "vec_cmpv2sfv2si" + [(set (match_operand:V2SI 0 "register_operand") + (match_operator:V2SI 1 "" + [(match_operand:V2SF 2 "register_operand") + (match_operand:V2SF 3 "register_operand")]))] + "TARGET_MMX_WITH_SSE" +{ + bool ok = ix86_expand_fp_vec_cmp (operands); + gcc_assert (ok); + DONE; +}) + +(define_expand "vcondv2sf" + [(set (match_operand:V2FI 0 "register_operand") + (if_then_else:V2FI + (match_operator 3 "" + [(match_operand:V2SF 4 "register_operand") + (match_operand:V2SF 5 "register_operand")]) + (match_operand:V2FI 1) + (match_operand:V2FI 2)))] + "TARGET_MMX_WITH_SSE" +{ + bool ok = ix86_expand_fp_vcond (operands); + gcc_assert (ok); + DONE; +}) + +(define_insn "mmx_blendvps" + [(set (match_operand:V2SF 0 "register_operand" "=Yr,*x,x") + (unspec:V2SF + [(match_operand:V2SF 1 "register_operand" "0,0,x") + (match_operand:V2SF 2 "register_operand" "Yr,*x,x") + (match_operand:V2SF 3 "register_operand" "Yz,Yz,x")] + UNSPEC_BLENDV))] + "TARGET_SSE4_1 && TARGET_MMX_WITH_SSE" + "@ + blendvps\t{%3, %2, %0|%0, %2, %3} + blendvps\t{%3, %2, %0|%0, %2, %3} + vblendvps\t{%3, %2, %1, %0|%0, %1, %2, %3}" + [(set_attr "isa" "noavx,noavx,avx") + (set_attr "type" "ssemov") + (set_attr "length_immediate" "1") + (set_attr "prefix_data16" "1,1,*") + (set_attr "prefix_extra" "1") + (set_attr "prefix" "orig,orig,vex") + (set_attr "btver2_decode" "vector") + (set_attr "mode" "V4SF")]) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parallel single-precision floating point logical operations @@ -1657,42 +1747,46 @@ DONE; }) -(define_expand "vcond" - [(set (match_operand:MMXMODEI 0 "register_operand") - (if_then_else:MMXMODEI +(define_expand "vcond" + [(set (match_operand:MMXMODE124 0 "register_operand") + (if_then_else:MMXMODE124 (match_operator 3 "" [(match_operand:MMXMODEI 4 "register_operand") (match_operand:MMXMODEI 5 "register_operand")]) - (match_operand:MMXMODEI 1) - (match_operand:MMXMODEI 2)))] - "TARGET_MMX_WITH_SSE" + (match_operand:MMXMODE124 1) + (match_operand:MMXMODE124 2)))] + "TARGET_MMX_WITH_SSE + && (GET_MODE_NUNITS (mode) + == GET_MODE_NUNITS (mode))" { bool ok = ix86_expand_int_vcond (operands); gcc_assert (ok); DONE; }) -(define_expand "vcondu" - [(set (match_operand:MMXMODEI 0 "register_operand") - (if_then_else:MMXMODEI +(define_expand "vcondu" + [(set (match_operand:MMXMODE124 0 "register_operand") + (if_then_else:MMXMODE124 (match_operator 3 "" [(match_operand:MMXMODEI 4 "register_operand") (match_operand:MMXMODEI 5 "register_operand")]) - (match_operand:MMXMODEI 1) - (match_operand:MMXMODEI 2)))] - "TARGET_MMX_WITH_SSE" + (match_operand:MMXMODE124 1) + (match_operand:MMXMODE124 2)))] + "TARGET_MMX_WITH_SSE + && (GET_MODE_NUNITS (mode) + == GET_MODE_NUNITS (mode))" { bool ok = ix86_expand_int_vcond (operands); gcc_assert (ok); DONE; }) -(define_expand "vcond_mask_" - [(set (match_operand:MMXMODEI 0 "register_operand") - (vec_merge:MMXMODEI - (match_operand:MMXMODEI 1 "register_operand") - (match_operand:MMXMODEI 2 "register_operand") - (match_operand:MMXMODEI 3 "register_operand")))] +(define_expand "vcond_mask_" + [(set (match_operand:MMXMODE124 0 "register_operand") + (vec_merge:MMXMODE124 + (match_operand:MMXMODE124 1 "register_operand") + (match_operand:MMXMODE124 2 "register_operand") + (match_operand: 3 "register_operand")))] "TARGET_MMX_WITH_SSE" { ix86_expand_sse_movcc (operands[0], operands[3], diff --git a/gcc/testsuite/g++.target/i386/pr98218-1.C b/gcc/testsuite/g++.target/i386/pr98218-1.C new file mode 100644 index 0000000..61ea4bf --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr98218-1.C @@ -0,0 +1,20 @@ +/* PR target/98218 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -msse2" } */ + +typedef unsigned int __attribute__((__vector_size__ (8))) v64u32; +typedef int __attribute__((__vector_size__ (8))) v64s32; +typedef float __attribute__((__vector_size__ (8))) v64f32; + +v64u32 au, bu; +v64s32 as, bs; +v64f32 af, bf; + +v64u32 tu (v64f32 a, v64f32 b) { return (a > b) ? au : bu; } +v64s32 ts (v64f32 a, v64f32 b) { return (a > b) ? as : bs; } +v64f32 fu (v64u32 a, v64u32 b) { return (a > b) ? af : bf; } +v64f32 fs (v64s32 a, v64s32 b) { return (a > b) ? af : bf; } +v64f32 ff (v64f32 a, v64f32 b) { return (a > b) ? af : bf; } + +/* { dg-final { scan-assembler-times "cmpltps" 3 } } */ +/* { dg-final { scan-assembler-times "pcmpgtd" 2 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr98218-1.c b/gcc/testsuite/gcc.target/i386/pr98218-1.c index 48407da..9d6602c 100644 --- a/gcc/testsuite/gcc.target/i386/pr98218-1.c +++ b/gcc/testsuite/gcc.target/i386/pr98218-1.c @@ -1,4 +1,4 @@ -/* PR target/98522 */ +/* PR target/98218 */ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -msse2" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr98218-1a.c b/gcc/testsuite/gcc.target/i386/pr98218-1a.c index 3470c87..2610438 100644 --- a/gcc/testsuite/gcc.target/i386/pr98218-1a.c +++ b/gcc/testsuite/gcc.target/i386/pr98218-1a.c @@ -1,4 +1,4 @@ -/* PR target/98522 */ +/* PR target/98218 */ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -ftree-vectorize -msse2" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr98218-2.c b/gcc/testsuite/gcc.target/i386/pr98218-2.c index 0b71612..948bf4f 100644 --- a/gcc/testsuite/gcc.target/i386/pr98218-2.c +++ b/gcc/testsuite/gcc.target/i386/pr98218-2.c @@ -1,4 +1,4 @@ -/* PR target/98522 */ +/* PR target/98218 */ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -msse2" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr98218-2a.c b/gcc/testsuite/gcc.target/i386/pr98218-2a.c index 6afd0a4..73c7226 100644 --- a/gcc/testsuite/gcc.target/i386/pr98218-2a.c +++ b/gcc/testsuite/gcc.target/i386/pr98218-2a.c @@ -1,4 +1,4 @@ -/* PR target/98522 */ +/* PR target/98218 */ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -ftree-vectorize -msse2" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr98218-3.c b/gcc/testsuite/gcc.target/i386/pr98218-3.c index 83a8c29..1b40d0ce 100644 --- a/gcc/testsuite/gcc.target/i386/pr98218-3.c +++ b/gcc/testsuite/gcc.target/i386/pr98218-3.c @@ -1,4 +1,4 @@ -/* PR target/98522 */ +/* PR target/98218 */ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -msse2" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr98218-3a.c b/gcc/testsuite/gcc.target/i386/pr98218-3a.c index 272d54e..cf1d497 100644 --- a/gcc/testsuite/gcc.target/i386/pr98218-3a.c +++ b/gcc/testsuite/gcc.target/i386/pr98218-3a.c @@ -1,4 +1,4 @@ -/* PR target/98522 */ +/* PR target/98218 */ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O2 -ftree-vectorize -msse2" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr98218-4.c b/gcc/testsuite/gcc.target/i386/pr98218-4.c new file mode 100644 index 0000000..647bdb1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr98218-4.c @@ -0,0 +1,16 @@ +/* PR target/98218 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -msse2" } */ + +typedef unsigned int __attribute__((__vector_size__ (8))) v64u32; +typedef int __attribute__((__vector_size__ (8))) v64s32; +typedef float __attribute__((__vector_size__ (8))) v64f32; + +v64u32 tu (v64f32 a, v64f32 b) { return a > b; } +v64s32 ts (v64f32 a, v64f32 b) { return a > b; } +v64f32 fu (v64u32 a, v64u32 b) { return a > b; } +v64f32 fs (v64s32 a, v64s32 b) { return a > b; } +v64f32 ff (v64f32 a, v64f32 b) { return a > b; } + +/* { dg-final { scan-assembler-times "cmpltps" 3 } } */ +/* { dg-final { scan-assembler-times "pcmpgtd" 2 } } */ -- cgit v1.1 From e0c4c6bce88528773ee4445a540e86784fb72aa7 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 11 May 2021 10:59:51 +0200 Subject: Minor fixes --- gcc/ada/ChangeLog | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b956fea..66ebaae 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -2,10 +2,11 @@ PR bootstrap/100506 * Make-generated.in: Replace version.c with ada/version.c. - * gcc-interface/Make-lang.in: Add version.o to GNAT1_C_OBJS. - Add version.o to GNAT_ADA_OBJS and GNATBIND_OBJS. - * gcc-interface/Makefile.in: Add version.o to TOOLS_LIBS. - * gnatvsn.adb: Start using a new C symbol gnat_version_string. + * gcc-interface/Make-lang.in: Add version.o to GNAT1_C_OBJS and + GNATBIND_OBJS. + * gcc-interface/Makefile.in: Replace version.c with ada/version.c. + Add version.o to TOOLS_LIBS. + * gnatvsn.adb: Replace version_string with gnat_version_string. * version.c: New file. 2021-05-10 Eric Botcazou -- cgit v1.1 From f5f1838435400b837c8677c53a611e2dc6d56442 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 12 May 2021 09:46:03 +0200 Subject: match.pd: Optimize (x & y) == x into (x & ~y) == 0 [PR94589] > Somewhere in RTL (_M_value&1)==_M_value is turned into (_M_value&-2)==0, > that could be worth doing already in GIMPLE. Apparently it is /* Simplify eq/ne (and/ior x y) x/y) for targets with a BICS instruction or constant folding if x/y is a constant. */ if ((code == EQ || code == NE) && (op0code == AND || op0code == IOR) && !side_effects_p (op1) && op1 != CONST0_RTX (cmp_mode)) { /* Both (eq/ne (and x y) x) and (eq/ne (ior x y) y) simplify to (eq/ne (and (not y) x) 0). */ ... /* Both (eq/ne (and x y) y) and (eq/ne (ior x y) x) simplify to (eq/ne (and (not x) y) 0). */ Yes, doing that on GIMPLE for the case where the not argument is constant would simplify the phiopt follow-up (it would be single imm use then). On Thu, May 06, 2021 at 09:42:41PM +0200, Marc Glisse wrote: > We can probably do it in 2 steps, first something like > > (for cmp (eq ne) > (simplify > (cmp (bit_and:c @0 @1) @0) > (cmp (@0 (bit_not! @1)) { build_zero_cst (TREE_TYPE (@0)); }))) > > to get rid of the double use, and then simplify X&C==0 to X<=~C if C is a > mask 111...000 (I thought we already had a function to detect such masks, or > the 000...111, but I can't find them anymore). Ok, here is the first step then. 2021-05-12 Jakub Jelinek Marc Glisse PR tree-optimization/94589 * match.pd ((X & Y) == X -> (X & ~Y) == 0, (X | Y) == Y -> (X & ~Y) == 0): New GIMPLE simplifications. * gcc.dg/tree-ssa/pr94589-1.c: New test. --- gcc/match.pd | 12 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c (limited to 'gcc') diff --git a/gcc/match.pd b/gcc/match.pd index 19f4a78..cdb8763 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4764,6 +4764,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cmp:c (bit_xor:c @0 @1) @0) (cmp @1 { build_zero_cst (TREE_TYPE (@1)); })) +#if GIMPLE + /* (X & Y) == X becomes (X & ~Y) == 0. */ + (simplify + (cmp:c (bit_and:c @0 @1) @0) + (cmp (bit_and @0 (bit_not! @1)) { build_zero_cst (TREE_TYPE (@0)); })) + + /* (X | Y) == Y becomes (X & ~Y) == 0. */ + (simplify + (cmp:c (bit_ior:c @0 @1) @1) + (cmp (bit_and @0 (bit_not! @1)) { build_zero_cst (TREE_TYPE (@0)); })) +#endif + /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */ (simplify (cmp (convert?@3 (bit_xor @0 INTEGER_CST@1)) INTEGER_CST@2) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c new file mode 100644 index 0000000..7e1aaaa --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94589-1.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/94589 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (int x) +{ + return (x & 23) == x; +/* { dg-final { scan-tree-dump " & -24;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " & 23;" "optimized" } } */ +/* { dg-final { scan-tree-dump " == 0" "optimized" } } */ +} + +int +bar (int x) +{ + return (x | 137) != 137; +/* { dg-final { scan-tree-dump " & -138;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " \\| 137;" "optimized" } } */ +/* { dg-final { scan-tree-dump " != 0" "optimized" } } */ +} -- cgit v1.1 From 4d27d1adeef6da5e7581edfa65f69ea0cdbc877b Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 10 May 2021 15:36:59 +0200 Subject: ada: do not use binary mode in conf.py gcc/ada/ChangeLog: * doc/share/conf.py: Do not use binary mode. Do not use u' literals as Python3 uses unicode by default. --- gcc/ada/doc/share/conf.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/doc/share/conf.py b/gcc/ada/doc/share/conf.py index debd716..705a678 100644 --- a/gcc/ada/doc/share/conf.py +++ b/gcc/ada/doc/share/conf.py @@ -18,9 +18,9 @@ import latex_elements DOCS = { 'gnat_rm': { - 'title': u'GNAT Reference Manual'}, + 'title': 'GNAT Reference Manual'}, 'gnat_ugn': { - 'title': u'GNAT User\'s Guide for Native Platforms'}} + 'title': 'GNAT User\'s Guide for Native Platforms'}} # Then retrieve the source directory root_source_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -28,17 +28,17 @@ gnatvsn_spec = os.path.join(root_source_dir, '..', 'gnatvsn.ads') basever = os.path.join(root_source_dir, '..', '..', 'BASE-VER') texi_fsf = True # Set to False when FSF doc is switched to sphinx by default -with open(gnatvsn_spec, 'rb') as fd: +with open(gnatvsn_spec, 'r') as fd: gnatvsn_content = fd.read() def get_copyright(): - return u'2008-%s, Free Software Foundation' % time.strftime('%Y') + return '2008-%s, Free Software Foundation' % time.strftime('%Y') def get_gnat_version(): - m = re.search(br'Gnat_Static_Version_String : ' + - br'constant String := "([^\(\)]+)\(.*\)?";', + m = re.search(r'Gnat_Static_Version_String : ' + + r'constant String := "([^\(\)]+)\(.*\)?";', gnatvsn_content) if m: return m.group(1).strip().decode() @@ -57,12 +57,12 @@ def get_gnat_version(): def get_gnat_build_type(): - m = re.search(br'Build_Type : constant Gnat_Build_Type := (.+);', + m = re.search(r'Build_Type : constant Gnat_Build_Type := (.+);', gnatvsn_content) if m: - return {b'Gnatpro': 'PRO', - b'FSF': 'FSF', - b'GPL': 'GPL'}[m.group(1).strip()] + return {'Gnatpro': 'PRO', + 'FSF': 'FSF', + 'GPL': 'GPL'}[m.group(1).strip()] else: print('cannot compute GNAT build type') sys.exit(1) @@ -119,8 +119,8 @@ copyright_macros = { 'date': time.strftime("%b %d, %Y"), 'edition': 'GNAT %s Edition' % 'Pro' if get_gnat_build_type() == 'PRO' else 'GPL', - 'name': u'GNU Ada', - 'tool': u'GNAT', + 'name': 'GNU Ada', + 'tool': 'GNAT', 'version': version} latex_elements = { @@ -134,11 +134,11 @@ latex_elements = { 'tableofcontents': latex_elements.TOC % copyright_macros} latex_documents = [ - (master_doc, '%s.tex' % doc_name, project, u'AdaCore', 'manual')] + (master_doc, '%s.tex' % doc_name, project, 'AdaCore', 'manual')] texinfo_documents = [ (master_doc, doc_name, project, - u'AdaCore', doc_name, doc_name, '')] + 'AdaCore', doc_name, doc_name, '')] def setup(app): -- cgit v1.1 From 19040050aa2c8ee890fc58dda48639fc91bf0af0 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 12 May 2021 10:38:35 +0200 Subject: expand: Don't reuse DEBUG_EXPRs with vector type if they have different modes [PR100508] The inliner doesn't remap DEBUG_EXPR_DECLs, so the same decls can appear in multiple functions. Furthermore, expansion reuses corresponding DEBUG_EXPRs too, so they again can be reused in multiple functions. Neither of that is a major problem, DEBUG_EXPRs are just magic value holders and what value they stand for is independent in each function and driven by what debug stmts or DEBUG_INSNs they are bound to. Except for DEBUG_EXPR*s with vector types, TYPE_MODE can be either BLKmode or some vector mode depending on whether current function's enabled ISAs support that vector mode or not. On the following testcase, we expand it first in foo function without AVX2 enabled and so the DEBUG_EXPR is BLKmode, but later the same DEBUG_EXPR_DECL is used in a simd clone with AVX2 enabled and expansion ICEs because of a mode mismatch. The following patch fixes that by forcing recreation of a DEBUG_EXPR if there is a mode mismatch for vector typed DEBUG_EXPR_DECL, DEBUG_EXPRs will be still reused in between functions otherwise and within the same function the mode should be always the same. 2021-05-12 Jakub Jelinek PR middle-end/100508 * cfgexpand.c (expand_debug_expr): For DEBUG_EXPR_DECL with vector type, don't reuse DECL_RTL if it has different mode, instead force creation of a new DEBUG_EXPR. * gcc.dg/gomp/pr100508.c: New test. --- gcc/cfgexpand.c | 7 ++++++- gcc/testsuite/gcc.dg/gomp/pr100508.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/gomp/pr100508.c (limited to 'gcc') diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 747ca3e..e3814ee 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -4512,7 +4512,12 @@ expand_debug_expr (tree exp) op0 = DECL_RTL_IF_SET (exp); if (op0) - return op0; + { + if (GET_MODE (op0) != mode) + gcc_assert (VECTOR_TYPE_P (TREE_TYPE (exp))); + else + return op0; + } op0 = gen_rtx_DEBUG_EXPR (mode); DEBUG_EXPR_TREE_DECL (op0) = exp; diff --git a/gcc/testsuite/gcc.dg/gomp/pr100508.c b/gcc/testsuite/gcc.dg/gomp/pr100508.c new file mode 100644 index 0000000..c3fa2fc --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr100508.c @@ -0,0 +1,14 @@ +/* PR middle-end/100508 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g -fopenmp-simd" } */ + +typedef int __attribute__((__vector_size__(32))) V; +V j; + +#pragma omp declare simd +int +foo (void) +{ + V m = j; + return 0; +} -- cgit v1.1 From 229a6dbd9ef1680f1ca02d6ce63e8abdffaaeeba Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 12 May 2021 09:07:42 +0200 Subject: middle-end/100547 - check rtvec_alloc size This makes the rtvec_alloc argument size_t catching overflow and truncated arguments (from "invalid" testcases), verifying the argument against INT_MAX which is the limit set by the int typed rtvec_def.num_elem member. 2021-05-12 Richard Biener PR middle-end/100547 * rtl.h (rtvec_alloc): Make argument size_t. * rtl.c (rtvec_alloc): Verify the count is less than INT_MAX. --- gcc/rtl.c | 5 ++++- gcc/rtl.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/rtl.c b/gcc/rtl.c index 035eadc..b0ba1ff 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -158,10 +158,13 @@ static size_t rtvec_alloc_sizes; Store the length, and initialize all elements to zero. */ rtvec -rtvec_alloc (int n) +rtvec_alloc (size_t n) { rtvec rt; + /* rtvec_def.num_elem is an int. */ + gcc_assert (n < INT_MAX); + rt = ggc_alloc_rtvec_sized (n); /* Clear out the vector. */ memset (&rt->elem[0], 0, n * sizeof (rtx)); diff --git a/gcc/rtl.h b/gcc/rtl.h index c5f3d20..35178b5 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2976,7 +2976,7 @@ extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int); (sizeof (struct hwivec_def) \ + ((NWORDS)-1) * sizeof (HOST_WIDE_INT))) \ -extern rtvec rtvec_alloc (int); +extern rtvec rtvec_alloc (size_t); extern rtvec shallow_copy_rtvec (rtvec); extern bool shared_const_p (const_rtx); extern rtx copy_rtx (rtx); -- cgit v1.1 From 037e36611108283a729d94a8ae15962995742886 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 12 May 2021 08:51:03 +0000 Subject: Daily bump. --- gcc/ChangeLog | 202 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 18 +++++ gcc/c-family/ChangeLog | 4 + gcc/cp/ChangeLog | 27 +++++++ gcc/po/ChangeLog | 4 + gcc/testsuite/ChangeLog | 99 ++++++++++++++++++++++++ 7 files changed, 355 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 02e66c8..d0df507 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,205 @@ +2021-05-12 Richard Biener + + PR middle-end/100547 + * rtl.h (rtvec_alloc): Make argument size_t. + * rtl.c (rtvec_alloc): Verify the count is less than INT_MAX. + +2021-05-12 Jakub Jelinek + + PR middle-end/100508 + * cfgexpand.c (expand_debug_expr): For DEBUG_EXPR_DECL with vector + type, don't reuse DECL_RTL if it has different mode, instead force + creation of a new DEBUG_EXPR. + +2021-05-12 Jakub Jelinek + Marc Glisse + + PR tree-optimization/94589 + * match.pd ((X & Y) == X -> (X & ~Y) == 0, + (X | Y) == Y -> (X & ~Y) == 0): New GIMPLE simplifications. + +2021-05-12 Uroš Bizjak + + PR target/98218 + * config/i386/i386-expand.c (ix86_expand_sse_movcc): Handle V2SF mode. + * config/i386/mmx.md (MMXMODE124): New mode iterator. + (V2FI): Ditto. + (mmxintvecmode): New mode attribute. + (mmxintvecmodelower): Ditto. + (*mmx_maskcmpv2sf3_comm): New insn pattern. + (*mmx_maskcmpv2sf3): Ditto. + (vec_cmpv2sfv2si): New expander. + (vcondv2si): Ditto. + (mmx_vlendvps): New insn pattern. + (vcond): Also handle V2SFmode. + (vcondu): Ditto. + (vcond_mask_): Ditto. + +2021-05-11 Martin Sebor + + PR middle-end/21433 + * expr.c (expand_expr_real_1): Replace unreachable code with an assert. + +2021-05-11 Richard Biener + + * gimple-fold.c (gimple_fold_call): Do not call + maybe_fold_reference on call arguments or the static chain. + (fold_stmt_1): Do not call maybe_fold_reference on GIMPLE_ASM + inputs. + +2021-05-11 Martin Liska + + * builtins.def (DEF_HSAIL_BUILTIN): Remove. + (DEF_HSAIL_ATOMIC_BUILTIN): Likewise. + (DEF_HSAIL_SAT_BUILTIN): Likewise. + (DEF_HSAIL_INTR_BUILTIN): Likewise. + (DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN): Likewise. + * doc/frontends.texi: Remove BRIG. + * doc/install.texi: Likewise. + * doc/invoke.texi: Likewise. + * doc/standards.texi: Likewise. + * brig-builtins.def: Removed. + * brig/ChangeLog: Removed. + * brig/Make-lang.in: Removed. + * brig/brig-builtins.h: Removed. + * brig/brig-c.h: Removed. + * brig/brig-lang.c: Removed. + * brig/brigfrontend/brig-arg-block-handler.cc: Removed. + * brig/brigfrontend/brig-atomic-inst-handler.cc: Removed. + * brig/brigfrontend/brig-basic-inst-handler.cc: Removed. + * brig/brigfrontend/brig-branch-inst-handler.cc: Removed. + * brig/brigfrontend/brig-cmp-inst-handler.cc: Removed. + * brig/brigfrontend/brig-code-entry-handler.cc: Removed. + * brig/brigfrontend/brig-code-entry-handler.h: Removed. + * brig/brigfrontend/brig-comment-handler.cc: Removed. + * brig/brigfrontend/brig-control-handler.cc: Removed. + * brig/brigfrontend/brig-copy-move-inst-handler.cc: Removed. + * brig/brigfrontend/brig-cvt-inst-handler.cc: Removed. + * brig/brigfrontend/brig-fbarrier-handler.cc: Removed. + * brig/brigfrontend/brig-function-handler.cc: Removed. + * brig/brigfrontend/brig-function.cc: Removed. + * brig/brigfrontend/brig-function.h: Removed. + * brig/brigfrontend/brig-inst-mod-handler.cc: Removed. + * brig/brigfrontend/brig-label-handler.cc: Removed. + * brig/brigfrontend/brig-lane-inst-handler.cc: Removed. + * brig/brigfrontend/brig-machine.c: Removed. + * brig/brigfrontend/brig-machine.h: Removed. + * brig/brigfrontend/brig-mem-inst-handler.cc: Removed. + * brig/brigfrontend/brig-module-handler.cc: Removed. + * brig/brigfrontend/brig-queue-inst-handler.cc: Removed. + * brig/brigfrontend/brig-seg-inst-handler.cc: Removed. + * brig/brigfrontend/brig-signal-inst-handler.cc: Removed. + * brig/brigfrontend/brig-to-generic.cc: Removed. + * brig/brigfrontend/brig-to-generic.h: Removed. + * brig/brigfrontend/brig-util.cc: Removed. + * brig/brigfrontend/brig-util.h: Removed. + * brig/brigfrontend/brig-variable-handler.cc: Removed. + * brig/brigfrontend/hsa-brig-format.h: Removed. + * brig/brigfrontend/phsa.h: Removed. + * brig/brigspec.c: Removed. + * brig/config-lang.in: Removed. + * brig/gccbrig.texi: Removed. + * brig/lang-specs.h: Removed. + * brig/lang.opt: Removed. + +2021-05-11 Richard Biener + + PR ipa/100513 + * ipa-param-manipulation.c + (ipa_param_body_adjustments::modify_call_stmt): Avoid + altering SSA_NAME_DEF_STMT by adjusting the calls LHS + via gimple_call_lhs_ptr. + +2021-05-11 Alex Coplan + + PR target/99725 + * config/arm/arm.c (cmse_nonsecure_call_inline_register_clear): + Avoid emitting CFA adjusts on the sp if we have the fp. + +2021-05-11 Richard Sandiford + + * config/aarch64/iterators.md (VMUL_CHANGE_NLANES): Delete. + (VMULD): New iterator. + (VCOND): Handle V4HF and V8HF. + (VCONQ): Fix entry for V2SF. + * config/aarch64/aarch64-simd.md (mul_lane3): Use VMULD + instead of VMUL. Use a 64-bit vector mode for the indexed operand. + (*aarch64_mul3_elt_): Merge with... + (mul_laneq3): ...this define_insn. Use VMUL instead of VDQSF. + Use a 128-bit vector mode for the indexed operand. Use stype for + the scheduling type. + +2021-05-11 Richard Biener + + * gimple-fold.c (maybe_fold_reference): Only return + is_gimple_min_invariant values. + +2021-05-11 Richard Biener + + PR middle-end/100509 + * gimple-fold.c (fold_gimple_assign): Only call + get_symbol_constant_value on register type symbols. + +2021-05-11 Srinath Parvathaneni + Joe Ramsay + + PR target/100419 + * config/arm/arm_mve.h (__arm_vstrwq_scatter_offset): Fix wrong arguments. + (__arm_vcmpneq): Remove duplicate definition. + (__arm_vstrwq_scatter_offset_p): Likewise. + (__arm_vmaxq_x): Likewise. + (__arm_vmlsdavaq): Likewise. + (__arm_vmlsdavaxq): Likewise. + (__arm_vmlsdavq_p): Likewise. + (__arm_vmlsdavxq_p): Likewise. + (__arm_vrmlaldavhaq): Likewise. + (__arm_vstrbq_p): Likewise. + (__arm_vstrbq_scatter_offset): Likewise. + (__arm_vstrbq_scatter_offset_p): Likewise. + (__arm_vstrdq_scatter_offset): Likewise. + (__arm_vstrdq_scatter_offset_p): Likewise. + (__arm_vstrdq_scatter_shifted_offset): Likewise. + (__arm_vstrdq_scatter_shifted_offset_p): Likewise. + +2021-05-11 Jakub Jelinek + + PR middle-end/100471 + * omp-low.c (lower_omp_task_reductions): For OMP_TASKLOOP, if data + is 0, bypass the reduction loop including + GOMP_taskgroup_reduction_unregister call. + +2021-05-11 Kewen Lin + + * config/rs6000/rs6000.c (struct rs6000_cost_data): New member + costing_for_scalar. + (rs6000_density_test): Early return if costing_for_scalar is true. + (rs6000_init_cost): Init costing_for_scalar of rs6000_cost_data. + +2021-05-11 Kewen Lin + + * doc/tm.texi: Regenerated. + * target.def (init_cost): Add new parameter costing_for_scalar. + * targhooks.c (default_init_cost): Adjust for new parameter. + * targhooks.h (default_init_cost): Likewise. + * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Likewise. + (vect_compute_single_scalar_iteration_cost): Likewise. + (vect_analyze_loop_2): Likewise. + * tree-vect-slp.c (_bb_vec_info::_bb_vec_info): Likewise. + (vect_bb_vectorization_profitable_p): Likewise. + * tree-vectorizer.h (init_cost): Likewise. + * config/aarch64/aarch64.c (aarch64_init_cost): Likewise. + * config/i386/i386.c (ix86_init_cost): Likewise. + * config/rs6000/rs6000.c (rs6000_init_cost): Likewise. + +2021-05-11 Kewen Lin + + * config/rs6000/rs6000.c (rs6000_vect_nonmem): Renamed to + vect_nonmem and moved into... + (struct rs6000_cost_data): ...here. + (rs6000_init_cost): Use vect_nonmem of cost_data instead. + (rs6000_add_stmt_cost): Likewise. + (rs6000_finish_cost): Likewise. + 2021-05-10 Eric Botcazou * range-op.cc (get_bool_state): Adjust head comment. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index abf046d..d143140 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210511 +20210512 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 66ebaae..4261aa6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,21 @@ +2021-05-12 Martin Liska + + * doc/share/conf.py: Do not use binary mode. + Do not use u' literals as Python3 uses unicode by default. + +2021-05-11 Martin Liska + + * gcc-interface/ada-tree.h (BUILT_IN_LIKELY): Use builtins + from COROUTINES. + (BUILT_IN_UNLIKELY): Likewise. + +2021-05-11 Eric Botcazou + + * gnatvsn.adb (Version_String): Rename to... + (C_Version_String): ...this. + (Gnat_Version_String): Adjust to above renaming. + * version.c : Fix formatting glitches. + 2021-05-10 Martin Liska PR bootstrap/100506 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index e73c3ee..3860677 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,7 @@ +2021-05-11 Joseph Myers + + * c-lex.c (interpret_float): Handle digit separators for C2X. + 2021-05-10 Martin Liska * c-ada-spec.c (print_destructor): Use startswith diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 122808e..80ea065 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,30 @@ +2021-05-11 Jason Merrill + + PR c++/100517 + * typeck.c (build_reinterpret_cast_1): Check intype on + cast to vector. + +2021-05-11 Patrick Palka + + PR c++/51577 + * name-lookup.c (maybe_save_operator_binding): Unconditionally + enable for all function templates, not just generic lambdas. + Handle compound-assignment operator expressions. + * typeck.c (build_x_compound_expr): Call maybe_save_operator_binding + in the type-dependent case. + (build_x_modify_expr): Likewise. Move declaration of 'op' closer + to its first use. + +2021-05-11 Patrick Palka + + PR c++/100138 + * constraint.cc (tsubst_constraint): Set up cp_unevaluated. + (satisfy_atom): Set up iloc_sentinel before calling + cxx_constant_value. + * pt.c (tsubst_pack_expansion): When returning a rebuilt pack + expansion, carry over PACK_EXPANSION_LOCAL_P and + PACK_EXPANSION_SIZEOF_P from the original pack expansion. + 2021-05-10 Richard Biener PR middle-end/100464 diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog index 6c78000..cc54ad4 100644 --- a/gcc/po/ChangeLog +++ b/gcc/po/ChangeLog @@ -1,3 +1,7 @@ +2021-05-11 Joseph Myers + + * ja.po: Update. + 2021-04-29 Joseph Myers * sv.po: Update. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 75e235b..fd12630 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,102 @@ +2021-05-12 Jakub Jelinek + + PR middle-end/100508 + * gcc.dg/gomp/pr100508.c: New test. + +2021-05-12 Jakub Jelinek + Marc Glisse + + PR tree-optimization/94589 + * gcc.dg/tree-ssa/pr94589-1.c: New test. + +2021-05-12 Uroš Bizjak + + PR target/98218 + * g++.target/i386/pr98218-1.C: Ditto. + * gcc.target/i386/pr98218-4.c: New test. + * gcc.target/i386/pr98218-1.c: Correct PR number. + * gcc.target/i386/pr98218-1a.c: Ditto. + * gcc.target/i386/pr98218-2.c: Ditto. + * gcc.target/i386/pr98218-2a.c: Ditto. + * gcc.target/i386/pr98218-3.c: Ditto. + * gcc.target/i386/pr98218-3a.c: Ditto. + +2021-05-11 Joseph Myers + + * gcc.dg/cpp/c11-elifdef-1.c, gcc.dg/cpp/c2x-elifdef-1.c, + gcc.dg/cpp/c2x-elifdef-2.c: New tests. + +2021-05-11 Joseph Myers + + * g++.dg/cpp1y/digit-sep-paste.C, gcc.dg/c2x-digit-separators-3.c: + New tests. + +2021-05-11 Stefan Schulze Frielinghaus + + * gcc.dg/guality/pr43077-1.c: Align types of output and input + operands by lifting immediates to type long. + +2021-05-11 Joseph Myers + + * gcc.dg/c11-digit-separators-1.c, + gcc.dg/c2x-digit-separators-1.c, gcc.dg/c2x-digit-separators-2.c: + New tests. + +2021-05-11 Jason Merrill + + PR c++/100517 + * g++.dg/ext/vector41.C: New test. + +2021-05-11 Martin Liska + + * gfortran.dg/goacc/pr78027.f90: Remove -Wno-hsa option. + * brig.dg/README: Removed. + * brig.dg/dg.exp: Removed. + * brig.dg/test/gimple/alloca.hsail: Removed. + * brig.dg/test/gimple/atomics.hsail: Removed. + * brig.dg/test/gimple/branches.hsail: Removed. + * brig.dg/test/gimple/fbarrier.hsail: Removed. + * brig.dg/test/gimple/function_calls.hsail: Removed. + * brig.dg/test/gimple/internal-casts.hsail: Removed. + * brig.dg/test/gimple/kernarg.hsail: Removed. + * brig.dg/test/gimple/mem.hsail: Removed. + * brig.dg/test/gimple/mulhi.hsail: Removed. + * brig.dg/test/gimple/packed.hsail: Removed. + * brig.dg/test/gimple/priv-array-offset-access.hsail: Removed. + * brig.dg/test/gimple/smoke_test.hsail: Removed. + * brig.dg/test/gimple/variables.hsail: Removed. + * brig.dg/test/gimple/vector.hsail: Removed. + * lib/brig-dg.exp: Removed. + * lib/brig.exp: Removed. + +2021-05-11 Alex Coplan + + PR target/99725 + * gcc.target/arm/cmse/pr99725.c: New test. + +2021-05-11 Richard Sandiford + + * gcc.target/aarch64/fmul_lane_1.c: New test. + +2021-05-11 Richard Biener + + PR middle-end/100509 + * gcc.dg/pr100509.c: New testcase. + +2021-05-11 Robin Dapp + + * gcc.target/s390/risbg-ll-3.c: Change match pattern. + +2021-05-11 Patrick Palka + + PR c++/51577 + * g++.dg/lookup/operator-3.C: New test. + +2021-05-11 Patrick Palka + + PR c++/100138 + * g++.dg/cpp2a/concepts-ctad4.C: New test. + 2021-05-10 Eric Botcazou * gnat.dg/specs/opt5.ads: New test. -- cgit v1.1 From dd39327854de1d18110fada5f8a7a4630da6d144 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Wed, 12 May 2021 10:51:21 +0200 Subject: Remove version.h from object files gcc/ChangeLog: PR bootstrap/100560 * Makefile.in: Remove version.h from linker command line. --- gcc/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 487db22..1b5d3f4 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2942,10 +2942,10 @@ build/genmatch$(build_exeext) : $(BUILD_CPPLIB) \ # These programs are not linked with the MD reader. build/gengtype$(build_exeext) : build/gengtype-lex.o build/gengtype-parse.o \ - build/gengtype-state.o version.h build/errors.o + build/gengtype-state.o build/errors.o gengtype$(exeext) : gengtype.o gengtype-lex.o gengtype-parse.o \ - gengtype-state.o version.h errors.o $(LIBDEPS) + gengtype-state.o errors.o $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ $(filter-out ($LIBDEPS), $^) $(LIBS) -- cgit v1.1 From 1ecd1e6c894fbdbc10fdcfee419922b24e1115ee Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Tue, 11 May 2021 17:55:18 +0200 Subject: Fix ICE in output_rnglists, at dwarf2out.c:12294 In this testcase the compile unit consists of a single text section with a single embedded DECL_IGNORED_P function. So we have a kind of multi-range text section here. To avoid an ICE in output_rnglists we need to make sure that have_multiple_function_sections is set to true. This is a regression from e69ac020372 ("Add line debug info for virtual thunks") 2021-05-12 Bernd Edlinger PR debug/100515 * dwarf2out.c (dwarf2out_finish): Set have_multiple_function_sections with multi-range text_section. * gcc.dg/debug/dwarf2/pr100515.c: New testcase. --- gcc/dwarf2out.c | 1 + gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c (limited to 'gcc') diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 8fc8298..b99598e 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -31956,6 +31956,7 @@ dwarf2out_finish (const char *filename) add_AT_addr (main_comp_unit_die, DW_AT_entry_pc, const0_rtx, true); add_ranges (NULL); + have_multiple_function_sections = true; } } diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c new file mode 100644 index 0000000..7c72fcd --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c @@ -0,0 +1,19 @@ +/* PR debug/100515 */ +/* { dg-do compile } */ +/* { dg-options "-g -O2 -fopenmp" } */ + +void +foo (int x) +{ +#pragma omp taskloop + for (int i = 0; i < x; i++) + ; +} + +void +bar (int x) +{ +#pragma omp taskloop + for (int i = 0; i < x; i++) + ; +} -- cgit v1.1 From 227a2ecf663d69972b851f51f1934d18927b62cd Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 12 Mar 2021 11:53:47 +0100 Subject: lto-wrapper: Use vec data type. gcc/ChangeLog: * lto-wrapper.c (get_options_from_collect_gcc_options): Change return type. (append_option): Remove. (find_option): Rework to use the vector type. (remove_option): Remove. (merge_and_complain): Use vectors for cl_decoded_option data type arguments. (append_compiler_options): Likewise. (append_diag_options): Likewise. (append_linker_options): Likewise. (append_offload_options): Likewise. (compile_offload_image): Likewise. (compile_images_for_offload_targets): Likewise. (find_and_merge_options): Likewise. (run_gcc): Likewise. --- gcc/lto-wrapper.c | 396 ++++++++++++++++++++++++------------------------------ 1 file changed, 176 insertions(+), 220 deletions(-) (limited to 'gcc') diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index d6be7f0..11d4d20 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -139,12 +139,12 @@ maybe_unlink (const char *file) /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS environment. */ -static void +static vec get_options_from_collect_gcc_options (const char *collect_gcc, - const char *collect_gcc_options, - struct cl_decoded_option **decoded_options, - unsigned int *decoded_options_count) + const char *collect_gcc_options) { + cl_decoded_option *decoded_options; + unsigned int decoded_options_count; struct obstack argv_obstack; const char **argv; int argc; @@ -157,57 +157,49 @@ get_options_from_collect_gcc_options (const char *collect_gcc, argv = XOBFINISH (&argv_obstack, const char **); decode_cmdline_options_to_array (argc, (const char **)argv, CL_DRIVER, - decoded_options, decoded_options_count); + &decoded_options, &decoded_options_count); + vec decoded; + decoded.create (decoded_options_count); + for (unsigned i = 0; i < decoded_options_count; ++i) + decoded.quick_push (decoded_options[i]); + free (decoded_options); + obstack_free (&argv_obstack, NULL); + + return decoded; } -/* Append OPTION to the options array DECODED_OPTIONS with size - DECODED_OPTIONS_COUNT. */ +/* Find option in OPTIONS based on OPT_INDEX. -1 value is returned + if the option is not present. */ -static void -append_option (struct cl_decoded_option **decoded_options, - unsigned int *decoded_options_count, - struct cl_decoded_option *option) +static int +find_option (vec &options, size_t opt_index) { - ++*decoded_options_count; - *decoded_options - = (struct cl_decoded_option *) - xrealloc (*decoded_options, - (*decoded_options_count - * sizeof (struct cl_decoded_option))); - memcpy (&(*decoded_options)[*decoded_options_count - 1], option, - sizeof (struct cl_decoded_option)); -} + for (unsigned i = 0; i < options.length (); ++i) + if (options[i].opt_index == opt_index) + return i; -/* Remove option number INDEX from DECODED_OPTIONS, update - DECODED_OPTIONS_COUNT. */ + return -1; +} -static void -remove_option (struct cl_decoded_option **decoded_options, - int index, unsigned int *decoded_options_count) +static int +find_option (vec &options, cl_decoded_option *option) { - --*decoded_options_count; - memmove (&(*decoded_options)[index + 1], - &(*decoded_options)[index], - sizeof (struct cl_decoded_option) - * (*decoded_options_count - index)); + return find_option (options, option->opt_index); } /* Try to merge and complain about options FDECODED_OPTIONS when applied ontop of DECODED_OPTIONS. */ static void -merge_and_complain (struct cl_decoded_option **decoded_options, - unsigned int *decoded_options_count, - struct cl_decoded_option *fdecoded_options, - unsigned int fdecoded_options_count, - struct cl_decoded_option *decoded_cl_options, - unsigned int decoded_cl_options_count) +merge_and_complain (vec decoded_options, + vec fdecoded_options, + vec decoded_cl_options) { unsigned int i, j; - struct cl_decoded_option *pic_option = NULL; - struct cl_decoded_option *pie_option = NULL; - struct cl_decoded_option *cf_protection_option = NULL; + cl_decoded_option *pic_option = NULL; + cl_decoded_option *pie_option = NULL; + cl_decoded_option *cf_protection_option = NULL; /* ??? Merge options from files. Most cases can be handled by either unioning or intersecting @@ -224,9 +216,9 @@ merge_and_complain (struct cl_decoded_option **decoded_options, /* Look for a -fcf-protection option in the link-time options which overrides any -fcf-protection from the lto sections. */ - for (i = 0; i < decoded_cl_options_count; ++i) + for (i = 0; i < decoded_cl_options.length (); ++i) { - struct cl_decoded_option *foption = &decoded_cl_options[i]; + cl_decoded_option *foption = &decoded_cl_options[i]; if (foption->opt_index == OPT_fcf_protection_) { cf_protection_option = foption; @@ -235,9 +227,10 @@ merge_and_complain (struct cl_decoded_option **decoded_options, /* The following does what the old LTO option code did, union all target and a selected set of common options. */ - for (i = 0; i < fdecoded_options_count; ++i) + for (i = 0; i < fdecoded_options.length (); ++i) { - struct cl_decoded_option *foption = &fdecoded_options[i]; + cl_decoded_option *foption = &fdecoded_options[i]; + int existing_opt = find_option (decoded_options, foption); switch (foption->opt_index) { case OPT_SPECIAL_unknown: @@ -265,11 +258,8 @@ merge_and_complain (struct cl_decoded_option **decoded_options, setting per OPT code, we pick the first we encounter. ??? This doesn't make too much sense, but when it doesn't then we should complain. */ - for (j = 0; j < *decoded_options_count; ++j) - if ((*decoded_options)[j].opt_index == foption->opt_index) - break; - if (j == *decoded_options_count) - append_option (decoded_options, decoded_options_count, foption); + if (existing_opt == -1) + decoded_options.safe_push (*foption); break; /* Figure out what PIC/PIE level wins and merge the results. */ @@ -285,25 +275,19 @@ merge_and_complain (struct cl_decoded_option **decoded_options, case OPT_fopenmp: case OPT_fopenacc: /* For selected options we can merge conservatively. */ - for (j = 0; j < *decoded_options_count; ++j) - if ((*decoded_options)[j].opt_index == foption->opt_index) - break; - if (j == *decoded_options_count) - append_option (decoded_options, decoded_options_count, foption); + if (existing_opt == -1) + decoded_options.safe_push (*foption); /* -fopenmp > -fno-openmp, -fopenacc > -fno-openacc */ - else if (foption->value > (*decoded_options)[j].value) - (*decoded_options)[j] = *foption; + else if (foption->value > decoded_options[existing_opt].value) + decoded_options[existing_opt] = *foption; break; case OPT_fopenacc_dim_: /* Append or check identical. */ - for (j = 0; j < *decoded_options_count; ++j) - if ((*decoded_options)[j].opt_index == foption->opt_index) - break; - if (j == *decoded_options_count) - append_option (decoded_options, decoded_options_count, foption); - else if (strcmp ((*decoded_options)[j].arg, foption->arg)) + if (existing_opt == -1) + decoded_options.safe_push (*foption); + else if (strcmp (decoded_options[existing_opt].arg, foption->arg)) fatal_error (input_location, "option %s with different values", foption->orig_option_with_args_text); @@ -314,12 +298,9 @@ merge_and_complain (struct cl_decoded_option **decoded_options, if (!cf_protection_option || cf_protection_option->value == CF_CHECK) { - for (j = 0; j < *decoded_options_count; ++j) - if ((*decoded_options)[j].opt_index == foption->opt_index) - break; - if (j == *decoded_options_count) - append_option (decoded_options, decoded_options_count, foption); - else if ((*decoded_options)[j].value != foption->value) + if (existing_opt == -1) + decoded_options.safe_push (*foption); + else if (decoded_options[existing_opt].value != foption->value) { if (cf_protection_option && cf_protection_option->value == CF_CHECK) @@ -327,22 +308,23 @@ merge_and_complain (struct cl_decoded_option **decoded_options, "option %qs with mismatching values" " (%s, %s)", "-fcf-protection", - (*decoded_options)[j].arg, foption->arg); + decoded_options[existing_opt].arg, + foption->arg); else { /* Merge and update the -fcf-protection option. */ - (*decoded_options)[j].value &= (foption->value - & CF_FULL); - switch ((*decoded_options)[j].value) + decoded_options[existing_opt].value + &= (foption->value & CF_FULL); + switch (decoded_options[existing_opt].value) { case CF_NONE: - (*decoded_options)[j].arg = "none"; + decoded_options[existing_opt].arg = "none"; break; case CF_BRANCH: - (*decoded_options)[j].arg = "branch"; + decoded_options[existing_opt].arg = "branch"; break; case CF_RETURN: - (*decoded_options)[j].arg = "return"; + decoded_options[existing_opt].arg = "return"; break; default: gcc_unreachable (); @@ -356,15 +338,19 @@ merge_and_complain (struct cl_decoded_option **decoded_options, case OPT_Ofast: case OPT_Og: case OPT_Os: - for (j = 0; j < *decoded_options_count; ++j) - if ((*decoded_options)[j].opt_index == OPT_O - || (*decoded_options)[j].opt_index == OPT_Ofast - || (*decoded_options)[j].opt_index == OPT_Og - || (*decoded_options)[j].opt_index == OPT_Os) - break; - if (j == *decoded_options_count) - append_option (decoded_options, decoded_options_count, foption); - else if ((*decoded_options)[j].opt_index == foption->opt_index + existing_opt = -1; + for (j = 0; j < decoded_options.length (); ++j) + if (decoded_options[j].opt_index == OPT_O + || decoded_options[j].opt_index == OPT_Ofast + || decoded_options[j].opt_index == OPT_Og + || decoded_options[j].opt_index == OPT_Os) + { + existing_opt = j; + break; + } + if (existing_opt == -1) + decoded_options.safe_push (*foption); + else if (decoded_options[existing_opt].opt_index == foption->opt_index && foption->opt_index != OPT_O) /* Exact same options get merged. */ ; @@ -394,13 +380,14 @@ merge_and_complain (struct cl_decoded_option **decoded_options, default: gcc_unreachable (); } - switch ((*decoded_options)[j].opt_index) + switch (decoded_options[existing_opt].opt_index) { case OPT_O: - if ((*decoded_options)[j].arg[0] == '\0') + if (decoded_options[existing_opt].arg[0] == '\0') level = MAX (level, 1); else - level = MAX (level, atoi ((*decoded_options)[j].arg)); + level = MAX (level, + atoi (decoded_options[existing_opt].arg)); break; case OPT_Ofast: level = MAX (level, 3); @@ -414,23 +401,20 @@ merge_and_complain (struct cl_decoded_option **decoded_options, default: gcc_unreachable (); } - (*decoded_options)[j].opt_index = OPT_O; + decoded_options[existing_opt].opt_index = OPT_O; char *tem; tem = xasprintf ("-O%d", level); - (*decoded_options)[j].arg = &tem[2]; - (*decoded_options)[j].canonical_option[0] = tem; - (*decoded_options)[j].value = 1; + decoded_options[existing_opt].arg = &tem[2]; + decoded_options[existing_opt].canonical_option[0] = tem; + decoded_options[existing_opt].value = 1; } break; case OPT_foffload_abi_: - for (j = 0; j < *decoded_options_count; ++j) - if ((*decoded_options)[j].opt_index == foption->opt_index) - break; - if (j == *decoded_options_count) - append_option (decoded_options, decoded_options_count, foption); - else if (foption->value != (*decoded_options)[j].value) + if (existing_opt == -1) + decoded_options.safe_push (*foption); + else if (foption->value != decoded_options[existing_opt].value) fatal_error (input_location, "option %s not used consistently in all LTO input" " files", foption->orig_option_with_args_text); @@ -438,7 +422,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options, case OPT_foffload_: - append_option (decoded_options, decoded_options_count, foption); + decoded_options.safe_push (*foption); break; } } @@ -458,12 +442,12 @@ merge_and_complain (struct cl_decoded_option **decoded_options, It would be good to warn on mismatches, but it is bit hard to do as we do not know what nothing translates to. */ - for (unsigned int j = 0; j < *decoded_options_count;) - if ((*decoded_options)[j].opt_index == OPT_fPIC - || (*decoded_options)[j].opt_index == OPT_fpic) + for (unsigned int j = 0; j < decoded_options.length ();) + if (decoded_options[j].opt_index == OPT_fPIC + || decoded_options[j].opt_index == OPT_fpic) { /* -fno-pic in one unit implies -fno-pic everywhere. */ - if ((*decoded_options)[j].value == 0) + if (decoded_options[j].value == 0) j++; /* If we have no pic option or merge in -fno-pic, we still may turn existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present. */ @@ -472,41 +456,41 @@ merge_and_complain (struct cl_decoded_option **decoded_options, { if (pie_option) { - bool big = (*decoded_options)[j].opt_index == OPT_fPIC + bool big = decoded_options[j].opt_index == OPT_fPIC && pie_option->opt_index == OPT_fPIE; - (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie; + decoded_options[j].opt_index = big ? OPT_fPIE : OPT_fpie; if (pie_option->value) - (*decoded_options)[j].canonical_option[0] + decoded_options[j].canonical_option[0] = big ? "-fPIE" : "-fpie"; else - (*decoded_options)[j].canonical_option[0] = "-fno-pie"; - (*decoded_options)[j].value = pie_option->value; - j++; + decoded_options[j].canonical_option[0] = "-fno-pie"; + decoded_options[j].value = pie_option->value; + j++; } else if (pic_option) { - (*decoded_options)[j] = *pic_option; - j++; + decoded_options[j] = *pic_option; + j++; } /* We do not know if target defaults to pic or not, so just remove option if it is missing in one unit but enabled in other. */ else - remove_option (decoded_options, j, decoded_options_count); + decoded_options.ordered_remove (j); } else if (pic_option->opt_index == OPT_fpic - && (*decoded_options)[j].opt_index == OPT_fPIC) + && decoded_options[j].opt_index == OPT_fPIC) { - (*decoded_options)[j] = *pic_option; + decoded_options[j] = *pic_option; j++; } else j++; } - else if ((*decoded_options)[j].opt_index == OPT_fPIE - || (*decoded_options)[j].opt_index == OPT_fpie) + else if (decoded_options[j].opt_index == OPT_fPIE + || decoded_options[j].opt_index == OPT_fpie) { /* -fno-pie in one unit implies -fno-pie everywhere. */ - if ((*decoded_options)[j].value == 0) + if (decoded_options[j].value == 0) j++; /* If we have no pie option or merge in -fno-pie, we still preserve PIE/pie if pic/PIC is present. */ @@ -517,32 +501,32 @@ merge_and_complain (struct cl_decoded_option **decoded_options, if (pic_option) { if (pic_option->opt_index == OPT_fpic - && (*decoded_options)[j].opt_index == OPT_fPIE) + && decoded_options[j].opt_index == OPT_fPIE) { - (*decoded_options)[j].opt_index = OPT_fpie; - (*decoded_options)[j].canonical_option[0] + decoded_options[j].opt_index = OPT_fpie; + decoded_options[j].canonical_option[0] = pic_option->value ? "-fpie" : "-fno-pie"; } else if (!pic_option->value) - (*decoded_options)[j].canonical_option[0] = "-fno-pie"; - (*decoded_options)[j].value = pic_option->value; + decoded_options[j].canonical_option[0] = "-fno-pie"; + decoded_options[j].value = pic_option->value; j++; } else if (pie_option) { - (*decoded_options)[j] = *pie_option; + decoded_options[j] = *pie_option; j++; } /* Because we always append pic/PIE options this code path should not happen unless the LTO object was built by old lto1 which did not contain that logic yet. */ else - remove_option (decoded_options, j, decoded_options_count); + decoded_options.ordered_remove (j); } else if (pie_option->opt_index == OPT_fpie - && (*decoded_options)[j].opt_index == OPT_fPIE) + && decoded_options[j].opt_index == OPT_fPIE) { - (*decoded_options)[j] = *pie_option; + decoded_options[j] = *pie_option; j++; } else @@ -554,37 +538,41 @@ merge_and_complain (struct cl_decoded_option **decoded_options, if (!xassembler_options_error) for (i = j = 0; ; i++, j++) { - for (; i < *decoded_options_count; i++) - if ((*decoded_options)[i].opt_index == OPT_Xassembler) - break; - - for (; j < fdecoded_options_count; j++) - if (fdecoded_options[j].opt_index == OPT_Xassembler) - break; - - if (i == *decoded_options_count && j == fdecoded_options_count) + int existing_opt_index + = find_option (decoded_options, OPT_Xassembler); + int existing_opt2_index + = find_option (fdecoded_options, OPT_Xassembler); + + cl_decoded_option *existing_opt = NULL; + cl_decoded_option *existing_opt2 = NULL; + if (existing_opt_index != -1) + existing_opt = &decoded_options[existing_opt_index]; + if (existing_opt2_index != -1) + existing_opt2 = &fdecoded_options[existing_opt2_index]; + + if (existing_opt == NULL && existing_opt2 == NULL) break; - else if (i < *decoded_options_count && j == fdecoded_options_count) + else if (existing_opt != NULL && existing_opt2 == NULL) { warning (0, "Extra option to %<-Xassembler%>: %s," " dropping all %<-Xassembler%> and %<-Wa%> options.", - (*decoded_options)[i].arg); + existing_opt->arg); xassembler_options_error = true; break; } - else if (i == *decoded_options_count && j < fdecoded_options_count) + else if (existing_opt == NULL && existing_opt2 != NULL) { warning (0, "Extra option to %<-Xassembler%>: %s," " dropping all %<-Xassembler%> and %<-Wa%> options.", - fdecoded_options[j].arg); + existing_opt2->arg); xassembler_options_error = true; break; } - else if (strcmp ((*decoded_options)[i].arg, fdecoded_options[j].arg)) + else if (strcmp (existing_opt->arg, existing_opt2->arg) != 0) { warning (0, "Options to %<-Xassembler%> do not match: %s, %s," " dropping all %<-Xassembler%> and %<-Wa%> options.", - (*decoded_options)[i].arg, fdecoded_options[j].arg); + existing_opt->arg, existing_opt2->arg); xassembler_options_error = true; break; } @@ -655,13 +643,12 @@ parse_env_var (const char *str, char ***pvalues, const char *append) /* Append options OPTS from lto or offload_lto sections to ARGV_OBSTACK. */ static void -append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts, - unsigned int count) +append_compiler_options (obstack *argv_obstack, vec opts) { /* Append compiler driver arguments as far as they were merged. */ - for (unsigned int j = 1; j < count; ++j) + for (unsigned int j = 1; j < opts.length (); ++j) { - struct cl_decoded_option *option = &opts[j]; + cl_decoded_option *option = &opts[j]; /* File options have been properly filtered by lto-opts.c. */ switch (option->opt_index) @@ -722,16 +709,15 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts, } } -/* Append diag options in OPTS with length COUNT to ARGV_OBSTACK. */ +/* Append diag options in OPTS to ARGV_OBSTACK. */ static void -append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts, - unsigned int count) +append_diag_options (obstack *argv_obstack, vec opts) { /* Append compiler driver arguments as far as they were merged. */ - for (unsigned int j = 1; j < count; ++j) + for (unsigned int j = 1; j < opts.length (); ++j) { - struct cl_decoded_option *option = &opts[j]; + cl_decoded_option *option = &opts[j]; switch (option->opt_index) { @@ -758,14 +744,13 @@ append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts, /* Append linker options OPTS to ARGV_OBSTACK. */ static void -append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts, - unsigned int count) +append_linker_options (obstack *argv_obstack, vec opts) { /* Append linker driver arguments. Compiler options from the linker driver arguments will override / merge with those from the compiler. */ - for (unsigned int j = 1; j < count; ++j) + for (unsigned int j = 1; j < opts.length (); ++j) { - struct cl_decoded_option *option = &opts[j]; + cl_decoded_option *option = &opts[j]; /* Do not pass on frontend specific flags not suitable for lto. */ if (!(cl_options[option->opt_index].flags @@ -803,15 +788,14 @@ append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts, static void append_offload_options (obstack *argv_obstack, const char *target, - struct cl_decoded_option *options, - unsigned int options_count) + vec options) { - for (unsigned i = 0; i < options_count; i++) + for (unsigned i = 0; i < options.length (); i++) { const char *cur, *next, *opts; char **argv; unsigned argc; - struct cl_decoded_option *option = &options[i]; + cl_decoded_option *option = &options[i]; if (option->opt_index != OPT_foffload_) continue; @@ -883,10 +867,8 @@ access_check (const char *name, int mode) static char * compile_offload_image (const char *target, const char *compiler_path, unsigned in_argc, char *in_argv[], - struct cl_decoded_option *compiler_opts, - unsigned int compiler_opt_count, - struct cl_decoded_option *linker_opts, - unsigned int linker_opt_count) + vec compiler_opts, + vec linker_opts) { char *filename = NULL; char *dumpbase; @@ -943,19 +925,16 @@ compile_offload_image (const char *target, const char *compiler_path, obstack_ptr_grow (&argv_obstack, in_argv[i]); /* Append options from offload_lto sections. */ - append_compiler_options (&argv_obstack, compiler_opts, - compiler_opt_count); - append_diag_options (&argv_obstack, linker_opts, linker_opt_count); + append_compiler_options (&argv_obstack, compiler_opts); + append_diag_options (&argv_obstack, linker_opts); obstack_ptr_grow (&argv_obstack, "-dumpbase"); obstack_ptr_grow (&argv_obstack, dumpbase); /* Append options specified by -foffload last. In case of conflicting options we expect offload compiler to choose the latest. */ - append_offload_options (&argv_obstack, target, compiler_opts, - compiler_opt_count); - append_offload_options (&argv_obstack, target, linker_opts, - linker_opt_count); + append_offload_options (&argv_obstack, target, compiler_opts); + append_offload_options (&argv_obstack, target, linker_opts); obstack_ptr_grow (&argv_obstack, NULL); argv = XOBFINISH (&argv_obstack, char **); @@ -974,10 +953,8 @@ compile_offload_image (const char *target, const char *compiler_path, static void compile_images_for_offload_targets (unsigned in_argc, char *in_argv[], - struct cl_decoded_option *compiler_opts, - unsigned int compiler_opt_count, - struct cl_decoded_option *linker_opts, - unsigned int linker_opt_count) + vec compiler_opts, + vec linker_opts) { char **names = NULL; const char *target_names = getenv (OFFLOAD_TARGET_NAMES_ENV); @@ -997,8 +974,7 @@ compile_images_for_offload_targets (unsigned in_argc, char *in_argv[], { offload_names[next_name_entry] = compile_offload_image (names[i], compiler_path, in_argc, in_argv, - compiler_opts, compiler_opt_count, - linker_opts, linker_opt_count); + compiler_opts, linker_opts); if (!offload_names[next_name_entry]) #if OFFLOAD_DEFAULTED continue; @@ -1080,25 +1056,22 @@ find_crtoffloadtable (int save_temps, const char *dumppfx) } /* A subroutine of run_gcc. Examine the open file FD for lto sections with - name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS - and OPT_COUNT. Return true if we found a matching section, false + name prefix PREFIX, at FILE_OFFSET, and store any options we find in OPTS. + Return true if we found a matching section, false otherwise. COLLECT_GCC holds the value of the environment variable with the same name. */ static bool find_and_merge_options (int fd, off_t file_offset, const char *prefix, - struct cl_decoded_option *decoded_cl_options, - unsigned int decoded_cl_options_count, - struct cl_decoded_option **opts, - unsigned int *opt_count, const char *collect_gcc) + vec decoded_cl_options, + vec *opts, const char *collect_gcc) { off_t offset, length; char *data; char *fopts; const char *errmsg; int err; - struct cl_decoded_option *fdecoded_options = *opts; - unsigned int fdecoded_options_count = *opt_count; + vec fdecoded_options; simple_object_read *sobj; sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO", @@ -1120,24 +1093,19 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix, data = (char *)xmalloc (length); read (fd, data, length); fopts = data; + bool first = true; do { - struct cl_decoded_option *f2decoded_options; - unsigned int f2decoded_options_count; - get_options_from_collect_gcc_options (collect_gcc, fopts, - &f2decoded_options, - &f2decoded_options_count); - if (!fdecoded_options) - { - fdecoded_options = f2decoded_options; - fdecoded_options_count = f2decoded_options_count; - } + vec f2decoded_options + = get_options_from_collect_gcc_options (collect_gcc, fopts); + if (first) + { + fdecoded_options = f2decoded_options; + first = false; + } else - merge_and_complain (&fdecoded_options, - &fdecoded_options_count, - f2decoded_options, f2decoded_options_count, - decoded_cl_options, - decoded_cl_options_count); + merge_and_complain (fdecoded_options, f2decoded_options, + decoded_cl_options); fopts += strlen (fopts) + 1; } @@ -1146,7 +1114,6 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix, free (data); simple_object_release_read (sobj); *opts = fdecoded_options; - *opt_count = fdecoded_options_count; return true; } @@ -1391,12 +1358,9 @@ run_gcc (unsigned argc, char *argv[]) int jobserver = 0; int auto_parallel = 0; bool no_partition = false; - struct cl_decoded_option *fdecoded_options = NULL; - struct cl_decoded_option *offload_fdecoded_options = NULL; - unsigned int fdecoded_options_count = 0; - unsigned int offload_fdecoded_options_count = 0; - struct cl_decoded_option *decoded_options; - unsigned int decoded_options_count; + vec fdecoded_options; + fdecoded_options.create (16); + vec offload_fdecoded_options = vNULL; struct obstack argv_obstack; int new_head_argc; bool have_lto = false; @@ -1438,9 +1402,8 @@ run_gcc (unsigned argc, char *argv[]) NULL); } - get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options, - &decoded_options, - &decoded_options_count); + vec decoded_options + = get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options); /* Allocate array for input object files with LTO IL, and for possible preceding arguments. */ @@ -1489,8 +1452,7 @@ run_gcc (unsigned argc, char *argv[]) } if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX, - decoded_options, decoded_options_count, - &fdecoded_options, &fdecoded_options_count, + decoded_options, &fdecoded_options, collect_gcc)) { have_lto = true; @@ -1505,14 +1467,13 @@ run_gcc (unsigned argc, char *argv[]) obstack_ptr_grow (&argv_obstack, "-xlto"); obstack_ptr_grow (&argv_obstack, "-c"); - append_compiler_options (&argv_obstack, fdecoded_options, - fdecoded_options_count); - append_linker_options (&argv_obstack, decoded_options, decoded_options_count); + append_compiler_options (&argv_obstack, fdecoded_options); + append_linker_options (&argv_obstack, decoded_options); /* Scan linker driver arguments for things that are of relevance to us. */ - for (j = 1; j < decoded_options_count; ++j) + for (j = 1; j < decoded_options.length (); ++j) { - struct cl_decoded_option *option = &decoded_options[j]; + cl_decoded_option *option = &decoded_options[j]; switch (option->opt_index) { case OPT_o: @@ -1731,9 +1692,7 @@ cont1: fatal_error (input_location, "cannot open %s: %m", filename); if (!find_and_merge_options (fd, file_offset, OFFLOAD_SECTION_NAME_PREFIX, - decoded_options, decoded_options_count, - &offload_fdecoded_options, - &offload_fdecoded_options_count, + decoded_options, &offload_fdecoded_options, collect_gcc)) fatal_error (input_location, "cannot read %s: %m", filename); close (fd); @@ -1742,10 +1701,7 @@ cont1: } compile_images_for_offload_targets (num_offload_files, offload_argv, - offload_fdecoded_options, - offload_fdecoded_options_count, - decoded_options, - decoded_options_count); + offload_fdecoded_options, decoded_options); free_array_of_ptrs ((void **) offload_argv, num_offload_files); -- cgit v1.1 From 7d7d925d0d799eb9dda4a6bd6162af0a7db9c98b Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 22 Apr 2021 16:27:19 +0200 Subject: Print warning diagnostics for -flto issues. gcc/ChangeLog: * lto-wrapper.c (print_lto_docs_link): New function. (run_gcc): Print warning about missing job server detection after we know NR of partitions. Do the same for -flto{,=1}. * opts.c (get_option_html_page): Support -flto option. --- gcc/lto-wrapper.c | 39 +++++++++++++++++++++++++++++++++++++-- gcc/opts.c | 6 +++++- 2 files changed, 42 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 11d4d20..7931ae3 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "simple-object.h" #include "lto-section-names.h" #include "collect-utils.h" +#include "opts-diagnostic.h" /* Environment variable, used for passing the names of offload targets from GCC driver to lto-wrapper. */ @@ -1322,6 +1323,23 @@ jobserver_active_p (void) return JS_PREFIX "cannot access %<" JS_NEEDLE "%> file descriptors"; } +/* Print link to -flto documentation with a hint message. */ + +void +print_lto_docs_link () +{ + const char *url = get_option_url (NULL, OPT_flto); + + pretty_printer pp; + pp.url_format = URL_FORMAT_DEFAULT; + pp_string (&pp, "see the "); + pp_begin_url (&pp, url); + pp_string (&pp, "%<-flto%> option documentation"); + pp_end_url (&pp); + pp_string (&pp, " for more information"); + inform (UNKNOWN_LOCATION, pp_formatted_text (&pp)); +} + /* Test that a make command is present and working, return true if so. */ static bool @@ -1356,8 +1374,10 @@ run_gcc (unsigned argc, char *argv[]) char *collect_gcc_options; int parallel = 0; int jobserver = 0; + bool jobserver_requested = false; int auto_parallel = 0; bool no_partition = false; + const char *jobserver_error = NULL; vec fdecoded_options; fdecoded_options.create (16); vec offload_fdecoded_options = vNULL; @@ -1502,6 +1522,7 @@ run_gcc (unsigned argc, char *argv[]) { parallel = 1; jobserver = 1; + jobserver_requested = true; } else if (strcmp (option->arg, "auto") == 0) { @@ -1556,15 +1577,15 @@ run_gcc (unsigned argc, char *argv[]) { lto_mode = LTO_MODE_LTO; jobserver = 0; + jobserver_requested = false; auto_parallel = 0; parallel = 0; } else { - const char *jobserver_error = jobserver_active_p (); + jobserver_error = jobserver_active_p (); if (jobserver && jobserver_error != NULL) { - warning (0, jobserver_error); /* Fall back to auto parallelism. */ jobserver = 0; auto_parallel = 1; @@ -1879,6 +1900,20 @@ cont: maybe_unlink (ltrans_output_file); ltrans_output_file = NULL; + if (nr > 1) + { + if (jobserver_requested && jobserver_error != NULL) + { + warning (0, jobserver_error); + print_lto_docs_link (); + } + else if (parallel == 0) + { + warning (0, "using serial compilation of %d LTRANS jobs", nr); + print_lto_docs_link (); + } + } + if (parallel) { makefile = make_temp_file (".mk"); diff --git a/gcc/opts.c b/gcc/opts.c index 24bb641..fe6fddb 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -3243,9 +3243,13 @@ get_option_html_page (int option_index) const cl_option *cl_opt = &cl_options[option_index]; /* Analyzer options are on their own page. */ - if (strstr(cl_opt->opt_text, "analyzer-")) + if (strstr (cl_opt->opt_text, "analyzer-")) return "gcc/Static-Analyzer-Options.html"; + /* Handle -flto= option. */ + if (strstr (cl_opt->opt_text, "flto")) + return "gcc/Optimize-Options.html"; + #ifdef CL_Fortran if ((cl_opt->flags & CL_Fortran) != 0 /* If it is option common to both C/C++ and Fortran, it is documented -- cgit v1.1 From 3835aa0eb90292d652dd6b200f302f3cac7e643f Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Wed, 12 May 2021 11:59:17 +0200 Subject: LTO: merge -flto=arg from object files. gcc/ChangeLog: * lto-wrapper.c (merge_and_complain): Merge -flto=arg options. (run_gcc): Use -flto argument detection for merged fdecoded_options. --- gcc/lto-wrapper.c | 77 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 20 deletions(-) (limited to 'gcc') diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 7931ae3..a71d614 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -425,6 +425,31 @@ merge_and_complain (vec decoded_options, case OPT_foffload_: decoded_options.safe_push (*foption); break; + + case OPT_flto_: + if (existing_opt == -1) + decoded_options.safe_push (*foption); + else + { + if (strcmp (foption->arg, decoded_options[existing_opt].arg) != 0) + { + /* -flto=auto is preferred. */ + if (strcmp (decoded_options[existing_opt].arg, "auto") == 0) + ; + else if (strcmp (foption->arg, "auto") == 0 + || strcmp (foption->arg, "jobserver") == 0) + decoded_options[existing_opt].arg = foption->arg; + else if (strcmp (decoded_options[existing_opt].arg, + "jobserver") != 0) + { + int n = atoi (foption->arg); + int original_n = atoi (decoded_options[existing_opt].arg); + if (n > original_n) + decoded_options[existing_opt].arg = foption->arg; + } + } + } + break; } } @@ -1490,6 +1515,37 @@ run_gcc (unsigned argc, char *argv[]) append_compiler_options (&argv_obstack, fdecoded_options); append_linker_options (&argv_obstack, decoded_options); + /* Process LTO-related options on merged options. */ + for (j = 1; j < fdecoded_options.length (); ++j) + { + cl_decoded_option *option = &fdecoded_options[j]; + switch (option->opt_index) + { + case OPT_flto_: + if (strcmp (option->arg, "jobserver") == 0) + { + parallel = 1; + jobserver = 1; + } + else if (strcmp (option->arg, "auto") == 0) + { + parallel = 1; + auto_parallel = 1; + } + else + { + parallel = atoi (option->arg); + if (parallel <= 1) + parallel = 0; + } + /* Fallthru. */ + + case OPT_flto: + lto_mode = LTO_MODE_WHOPR; + break; + } + } + /* Scan linker driver arguments for things that are of relevance to us. */ for (j = 1; j < decoded_options.length (); ++j) { @@ -1519,26 +1575,7 @@ run_gcc (unsigned argc, char *argv[]) case OPT_flto_: if (strcmp (option->arg, "jobserver") == 0) - { - parallel = 1; - jobserver = 1; - jobserver_requested = true; - } - else if (strcmp (option->arg, "auto") == 0) - { - parallel = 1; - auto_parallel = 1; - } - else - { - parallel = atoi (option->arg); - if (parallel <= 1) - parallel = 0; - } - /* Fallthru. */ - - case OPT_flto: - lto_mode = LTO_MODE_WHOPR; + jobserver_requested = true; break; case OPT_flinker_output_: -- cgit v1.1 From ac18ded230f1559f271f8d66121b2f16805f0b27 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 12 May 2021 11:56:47 +0200 Subject: Fix uninitialized variable in Atree.Size_In_Slots Size_In_Slots uses the Nkind to look up the size in a table indexed by Nkind. This patch fixes a couple of places where the Nkind is wrong (uninitialized or zeroed out) so Size_In_Slots cannot be used. gcc/ada/ PR ada/100564 * atree.adb (Change_Node): Do not call Zero_Slots on a Node_Id when the Nkind has not yet been set; call the other Zero_Slots that takes a range of slot offsets. Call the new Mutate_Kind that takes an Old_Size, for the same reason -- the size cannot be computed without the Nkind. (Mutate_Nkind): New function that allows specifying the Old_Size. (Size_In_Slots): Assert that the Nkind has proper (nonzero) value. * atree.ads: Minor reformatting. --- gcc/ada/atree.adb | 32 +++++++++++++++++++++++++------- gcc/ada/atree.ads | 3 +-- 2 files changed, 26 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb index 4d4dc43..608819b 100644 --- a/gcc/ada/atree.adb +++ b/gcc/ada/atree.adb @@ -216,6 +216,13 @@ package body Atree is -- cannot be used to modify an already-initialized Nkind field. See also -- Mutate_Nkind. + procedure Mutate_Nkind + (N : Node_Id; Val : Node_Kind; Old_Size : Field_Offset); + -- Called by the other Mutate_Nkind to do all the work. This is needed + -- because the call in Change_Node, which calls this one directly, happens + -- after zeroing N's slots, which destroys its Nkind, which prevents us + -- from properly computing Old_Size. + package Field_Checking is function Field_Present (Kind : Node_Kind; Field : Node_Field) return Boolean; @@ -868,9 +875,8 @@ package body Atree is end Init_Nkind; procedure Mutate_Nkind - (N : Node_Id; Val : Node_Kind) + (N : Node_Id; Val : Node_Kind; Old_Size : Field_Offset) is - Old_Size : constant Field_Offset := Size_In_Slots (N); New_Size : constant Field_Offset := Size_In_Slots_To_Alloc (Val); All_Node_Offsets : Node_Offsets.Table_Type renames @@ -905,6 +911,11 @@ package body Atree is pragma Debug (Validate_Node_Write (N)); end Mutate_Nkind; + procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) is + begin + Mutate_Nkind (N, Val, Old_Size => Size_In_Slots (N)); + end Mutate_Nkind; + Ekind_Offset : constant Field_Offset := Entity_Field_Descriptors (Ekind).Offset; @@ -998,13 +1009,19 @@ package body Atree is end if; if New_Size > Old_Size then - pragma Debug (Zero_Slots (N)); - Node_Offsets.Table (N) := Alloc_Slots (New_Size); - end if; + declare + New_Offset : constant Field_Offset := Alloc_Slots (New_Size); + begin + pragma Debug (Zero_Slots (N)); + Node_Offsets.Table (N) := New_Offset; + Zero_Slots (New_Offset, New_Offset + New_Size - 1); + end; - Zero_Slots (N); + else + Zero_Slots (N); + end if; - Mutate_Nkind (N, New_Kind); + Mutate_Nkind (N, New_Kind, Old_Size); Set_Sloc (N, Save_Sloc); Set_In_List (N, Save_In_List); @@ -2125,6 +2142,7 @@ package body Atree is function Size_In_Slots (N : Node_Or_Entity_Id) return Field_Offset is begin + pragma Assert (Nkind (N) /= N_Unused_At_Start); return (if Nkind (N) in N_Entity then Einfo.Entities.Max_Entity_Size else Sinfo.Nodes.Size (Nkind (N))); diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads index efb8ca2..e2d3492 100644 --- a/gcc/ada/atree.ads +++ b/gcc/ada/atree.ads @@ -571,8 +571,7 @@ package Atree is (N : Entity_Id; Field : Entity_Field) return Boolean; -- True if the field value is the initial zero value - procedure Mutate_Nkind - (N : Node_Id; Val : Node_Kind) with Inline; + procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) with Inline; -- There is no Set_Nkind in Sinfo.Nodes. We use this instead. This is here, -- and has a different name, because it does some extra checking. Nkind is -- like a discriminant, in that it controls which fields exist, and that -- cgit v1.1 From cd36bbb2281ada10b5e1df143ecf64b88cdb8119 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 11 May 2021 14:59:59 +0200 Subject: tree-optimization/100519 - avoid reassociating asm goto defs This splits can_associate_p into checks for SSA defs and checks for the type so it can be called from is_reassociable_op to catch cases not catched by the earlier fix. 2021-05-11 Richard Biener PR tree-optimization/100519 * tree-ssa-reassoc.c (can_associate_p): Split into... (can_associate_op_p): ... this (can_associate_type_p): ... and this. (is_reassociable_op): Call can_associate_op_p. (break_up_subtract_bb): Call the appropriate predicates. (reassociate_bb): Likewise. * gcc.dg/torture/pr100519.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr100519.c | 13 +++++ gcc/tree-ssa-reassoc.c | 86 +++++++++++++++++---------------- 2 files changed, 58 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr100519.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr100519.c b/gcc/testsuite/gcc.dg/torture/pr100519.c new file mode 100644 index 0000000..faf6e24 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr100519.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-additional-options "--param tree-reassoc-width=2" } */ + +unsigned int foo_a1, foo_a2; + +unsigned int foo() +{ + unsigned int v0, x; + asm goto("" : "=r"(x) : : : lab); +lab: + v0 += x + x; + return v0 + x + foo_a1 + foo_a2; +} diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 359367c..32e1632 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -593,6 +593,36 @@ add_repeat_to_ops_vec (vec *ops, tree op, reassociate_stats.pows_encountered++; } +/* Returns true if we can associate the SSA def OP. */ + +static bool +can_reassociate_op_p (tree op) +{ + if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op)) + return false; + /* Make sure asm goto outputs do not participate in reassociation since + we have no way to find an insertion place after asm goto. */ + if (TREE_CODE (op) == SSA_NAME + && gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_ASM + && gimple_asm_nlabels (as_a (SSA_NAME_DEF_STMT (op))) != 0) + return false; + return true; +} + +/* Returns true if we can reassociate operations of TYPE. + That is for integral or non-saturating fixed-point types, and for + floating point type when associative-math is enabled. */ + +static bool +can_reassociate_type_p (tree type) +{ + if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)) + || NON_SAT_FIXED_POINT_TYPE_P (type) + || (flag_associative_math && FLOAT_TYPE_P (type))) + return true; + return false; +} + /* Return true if STMT is reassociable operation containing a binary operation with tree code CODE, and is inside LOOP. */ @@ -613,12 +643,8 @@ is_reassociable_op (gimple *stmt, enum tree_code code, class loop *loop) { tree rhs1 = gimple_assign_rhs1 (stmt); tree rhs2 = gimple_assign_rhs2 (stmt); - if (TREE_CODE (rhs1) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1)) - return false; - if (rhs2 - && TREE_CODE (rhs2) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs2)) + if (!can_reassociate_op_p (rhs1) + || (rhs2 && !can_reassociate_op_p (rhs2))) return false; return true; } @@ -5887,29 +5913,6 @@ repropagate_negates (void) } } -/* Returns true if OP is of a type for which we can do reassociation. - That is for integral or non-saturating fixed-point types, and for - floating point type when associative-math is enabled. */ - -static bool -can_reassociate_p (tree op) -{ - tree type = TREE_TYPE (op); - if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op)) - return false; - /* Make sure asm goto outputs do not participate in reassociation since - we have no way to find an insertion place after asm goto. */ - if (TREE_CODE (op) == SSA_NAME - && gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_ASM - && gimple_asm_nlabels (as_a (SSA_NAME_DEF_STMT (op))) != 0) - return false; - if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)) - || NON_SAT_FIXED_POINT_TYPE_P (type) - || (flag_associative_math && FLOAT_TYPE_P (type))) - return true; - return false; -} - /* Break up subtract operations in block BB. We do this top down because we don't know whether the subtract is @@ -5942,14 +5945,15 @@ break_up_subtract_bb (basic_block bb) gimple_set_uid (stmt, uid++); if (!is_gimple_assign (stmt) - || !can_reassociate_p (gimple_assign_lhs (stmt))) + || !can_reassociate_type_p (TREE_TYPE (gimple_assign_lhs (stmt))) + || !can_reassociate_op_p (gimple_assign_lhs (stmt))) continue; /* Look for simple gimple subtract operations. */ if (gimple_assign_rhs_code (stmt) == MINUS_EXPR) { - if (!can_reassociate_p (gimple_assign_rhs1 (stmt)) - || !can_reassociate_p (gimple_assign_rhs2 (stmt))) + if (!can_reassociate_op_p (gimple_assign_rhs1 (stmt)) + || !can_reassociate_op_p (gimple_assign_rhs2 (stmt))) continue; /* Check for a subtract used only in an addition. If this @@ -5960,7 +5964,7 @@ break_up_subtract_bb (basic_block bb) break_up_subtract (stmt, &gsi); } else if (gimple_assign_rhs_code (stmt) == NEGATE_EXPR - && can_reassociate_p (gimple_assign_rhs1 (stmt))) + && can_reassociate_op_p (gimple_assign_rhs1 (stmt))) plus_negates.safe_push (gimple_assign_lhs (stmt)); } for (son = first_dom_son (CDI_DOMINATORS, bb); @@ -6553,14 +6557,14 @@ reassociate_bb (basic_block bb) /* For non-bit or min/max operations we can't associate all types. Verify that here. */ - if (rhs_code != BIT_IOR_EXPR - && rhs_code != BIT_AND_EXPR - && rhs_code != BIT_XOR_EXPR - && rhs_code != MIN_EXPR - && rhs_code != MAX_EXPR - && (!can_reassociate_p (lhs) - || !can_reassociate_p (rhs1) - || !can_reassociate_p (rhs2))) + if ((rhs_code != BIT_IOR_EXPR + && rhs_code != BIT_AND_EXPR + && rhs_code != BIT_XOR_EXPR + && rhs_code != MIN_EXPR + && rhs_code != MAX_EXPR + && !can_reassociate_type_p (TREE_TYPE (lhs))) + || !can_reassociate_op_p (rhs1) + || !can_reassociate_op_p (rhs2)) continue; if (associative_tree_code (rhs_code)) -- cgit v1.1 From 8da3b309d8fb3ddec0b42218ca6762967b402dc3 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Wed, 7 Apr 2021 09:58:54 +0800 Subject: i386: Optimize vpblendvb on inverted mask register to vpblendvb on swapping the order of operand 1 and operand 2. [PR target/99908] - vpcmpeqd %ymm3, %ymm3, %ymm3 - vpandn %ymm3, %ymm2, %ymm2 - vpblendvb %ymm2, %ymm1, %ymm0, %ymm0 + vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 gcc/ChangeLog: PR target/99908 * config/i386/sse.md (_pblendvb): Add splitters for pblendvb of NOT mask register. gcc/testsuite/ChangeLog: PR target/99908 * gcc.target/i386/avx2-pr99908.c: New test. * gcc.target/i386/sse4_1-pr99908.c: New test. --- gcc/config/i386/sse.md | 29 ++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/avx2-pr99908.c | 25 ++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/sse4_1-pr99908.c | 23 ++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/avx2-pr99908.c create mode 100644 gcc/testsuite/gcc.target/i386/sse4_1-pr99908.c (limited to 'gcc') diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 244fb13..49dda74 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -17734,6 +17734,35 @@ (set_attr "btver2_decode" "vector,vector,vector") (set_attr "mode" "")]) +(define_split + [(set (match_operand:VI1_AVX2 0 "register_operand") + (unspec:VI1_AVX2 + [(match_operand:VI1_AVX2 1 "vector_operand") + (match_operand:VI1_AVX2 2 "register_operand") + (not:VI1_AVX2 (match_operand:VI1_AVX2 3 "register_operand"))] + UNSPEC_BLENDV))] + "TARGET_SSE4_1" + [(set (match_dup 0) + (unspec:VI1_AVX2 + [(match_dup 2) (match_dup 1) (match_dup 3)] + UNSPEC_BLENDV))]) + +(define_split + [(set (match_operand:VI1_AVX2 0 "register_operand") + (unspec:VI1_AVX2 + [(match_operand:VI1_AVX2 1 "vector_operand") + (match_operand:VI1_AVX2 2 "register_operand") + (subreg:VI1_AVX2 (not (match_operand 3 "register_operand")) 0)] + UNSPEC_BLENDV))] + "TARGET_SSE4_1 + && GET_MODE_CLASS (GET_MODE (operands[3])) == MODE_VECTOR_INT + && GET_MODE_SIZE (GET_MODE (operands[3])) == " + [(set (match_dup 0) + (unspec:VI1_AVX2 + [(match_dup 2) (match_dup 1) (match_dup 4)] + UNSPEC_BLENDV))] + "operands[4] = gen_lowpart (mode, operands[3]);") + (define_insn_and_split "*_pblendvb_lt" [(set (match_operand:VI1_AVX2 0 "register_operand" "=Yr,*x,x") (unspec:VI1_AVX2 diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr99908.c b/gcc/testsuite/gcc.target/i386/avx2-pr99908.c new file mode 100644 index 0000000..2775f3b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx2-pr99908.c @@ -0,0 +1,25 @@ +/* PR target/99908 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx2 -masm=att" } */ +/* { dg-final { scan-assembler-times "\tvpblendvb\t" 2 } } */ +/* { dg-final { scan-assembler-not "\tvpcmpeq" } } */ +/* { dg-final { scan-assembler-not "\tvpandn" } } */ + +#include + +__m256i +f1 (__m256i a, __m256i b, __m256i mask) +{ + return _mm256_blendv_epi8(a, b, + _mm256_andnot_si256(mask, _mm256_set1_epi8(255))); +} + +__m256i +f2 (__v32qi x, __v32qi a, __v32qi b) +{ + x ^= (__v32qi) { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; + return _mm256_blendv_epi8 ((__m256i) a, (__m256i) b, (__m256i) x); +} diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-pr99908.c b/gcc/testsuite/gcc.target/i386/sse4_1-pr99908.c new file mode 100644 index 0000000..c13e730 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse4_1-pr99908.c @@ -0,0 +1,23 @@ +/* PR target/99908 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse4.1 -mno-avx -masm=att" } */ +/* { dg-final { scan-assembler-times "\tpblendvb\t" 2 } } */ +/* { dg-final { scan-assembler-not "\tpcmpeq" } } */ +/* { dg-final { scan-assembler-not "\tpandn" } } */ + +#include + +__m128i +f1 (__m128i a, __m128i b, __m128i mask) +{ + return _mm_blendv_epi8(a, b, + _mm_andnot_si128(mask, _mm_set1_epi8(255))); +} + +__m128i +f2 (__v16qi x, __v16qi a, __v16qi b) +{ + x ^= (__v16qi) { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; + return _mm_blendv_epi8 ((__m128i) a, (__m128i) b, (__m128i) x); +} -- cgit v1.1 From fc186594e3ee86a57841442e96306dddfd8eb85d Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Wed, 12 May 2021 14:03:36 +0200 Subject: lto-wrapper: silent warnings in tests Silents the following warning: lto-wrapper: warning: using serial compilation of 2 LTRANS jobs gcc/testsuite/ChangeLog: * lib/lto.exp: When running tests without jobserver, one can see the following warning for tests that use 1to1 partitioning. --- gcc/testsuite/lib/lto.exp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp index 94a81ff..77919e8 100644 --- a/gcc/testsuite/lib/lto.exp +++ b/gcc/testsuite/lib/lto.exp @@ -159,6 +159,9 @@ proc lto_prune_warns { text } { regsub -all "(^|\n)\[ \t\]*\[\(\]file \[^\n\]* value=\[^\n\]*; file \[^\n\]* value=\[^\n\]*\[)\];" $text "" text regsub -all "(^|\n)\[ \t\]*\[^\n\]* definition taken" $text "" text + # Ignore missing jobserver for tests that do more than 1 LTRANS unit + regsub -all "(^|\n)\[^\n\]*: warning: using serial compilation of \[^\n\]*" $text "" text + # Ignore informational notes. regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text -- cgit v1.1 From c6b664e2c4c127025e076d8b584abe0976694629 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 12 May 2021 15:14:35 +0200 Subject: libcpp: Fix up -fdirectives-only preprocessing of includes not ending with newline [PR100392] If a header doesn't end with a new-line, with -fdirectives-only we right now preprocess it as int i = 1;# 2 "pr100392.c" 2 i.e. the line directive isn't on the next line, which means we fail to parse it when compiling. GCC 10 and earlier libcpp/directives-only.c had for this: if (!pfile->state.skipping && cur != base) { /* If the file was not newline terminated, add rlimit, which is guaranteed to point to a newline, to the end of our range. */ if (cur[-1] != '\n') { cur++; CPP_INCREMENT_LINE (pfile, 0); lines++; } cb->print_lines (lines, base, cur - base); } and we have the assertion /* Files always end in a newline or carriage return. We rely on this for character peeking safety. */ gcc_assert (buffer->rlimit[0] == '\n' || buffer->rlimit[0] == '\r'); So, this patch just does readd the more less same thing, so that we emit a newline after the inline even when it wasn't there before. 2021-05-12 Jakub Jelinek PR preprocessor/100392 * lex.c (cpp_directive_only_process): If buffer doesn't end with '\n', add buffer->rlimit[0] character to the printed range and CPP_INCREMENT_LINE and increment line_count. * gcc.dg/cpp/pr100392.c: New test. * gcc.dg/cpp/pr100392.h: New file. --- gcc/testsuite/gcc.dg/cpp/pr100392.c | 5 +++++ gcc/testsuite/gcc.dg/cpp/pr100392.h | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/cpp/pr100392.c create mode 100644 gcc/testsuite/gcc.dg/cpp/pr100392.h (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/cpp/pr100392.c b/gcc/testsuite/gcc.dg/cpp/pr100392.c new file mode 100644 index 0000000..670ad2b --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/pr100392.c @@ -0,0 +1,5 @@ +/* PR preprocessor/100392 */ +/* { dg-do compile } */ +/* { dg-options "-save-temps -fdirectives-only" } */ + +#include "pr100392.h" diff --git a/gcc/testsuite/gcc.dg/cpp/pr100392.h b/gcc/testsuite/gcc.dg/cpp/pr100392.h new file mode 100644 index 0000000..340bc92 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/pr100392.h @@ -0,0 +1,4 @@ +/* PR preprocessor/100392 */ + +/* No newline after ; below. */ +int i = 1; \ No newline at end of file -- cgit v1.1 From 097fde5e7514e909f2e8472be2e008d0cab2260d Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 12 May 2021 15:39:52 +0200 Subject: tree-optimization/100566 - fix another predication issue in VN This amends the fix for PR100053 where I failed to amend all edge tests in dominated_by_p_w_unex. 2021-05-12 Richard Biener PR tree-optimization/100566 * tree-ssa-sccvn.c (dominated_by_p_w_unex): Properly handle allow_back for all edge queries. * gcc.dg/torture/pr100566.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr100566.c | 36 +++++++++++++++++++++++++++++++++ gcc/tree-ssa-sccvn.c | 6 ++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr100566.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/torture/pr100566.c b/gcc/testsuite/gcc.dg/torture/pr100566.c new file mode 100644 index 0000000..ed85691 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr100566.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ + +volatile int s, c; + +__attribute__((noipa)) void +foo (void) +{ + if (c++ > 1) + __builtin_abort (); +} + +__attribute__((noipa)) int +bar (void) +{ + int i = 0, j = s; + if (j == 0) + goto lab; + for (i = 0; i < j; i++) + { + lab: + foo (); + if (!j) + goto lab; + } + return 0; +} + +int +main () +{ + s = 1; + bar (); + if (c != 1) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index e54a0c9..e876121 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -4529,7 +4529,8 @@ dominated_by_p_w_unex (basic_block bb1, basic_block bb2, bool allow_back) /* Iterate to the single executable bb2 successor. */ edge succe = NULL; FOR_EACH_EDGE (e, ei, bb2->succs) - if (e->flags & EDGE_EXECUTABLE) + if ((e->flags & EDGE_EXECUTABLE) + || (!allow_back && (e->flags & EDGE_DFS_BACK))) { if (succe) { @@ -4547,7 +4548,8 @@ dominated_by_p_w_unex (basic_block bb1, basic_block bb2, bool allow_back) { FOR_EACH_EDGE (e, ei, succe->dest->preds) if (e != succe - && (e->flags & EDGE_EXECUTABLE)) + && ((e->flags & EDGE_EXECUTABLE) + || (!allow_back && (e->flags & EDGE_DFS_BACK)))) { succe = NULL; break; -- cgit v1.1 From 2a1586401a21dcd43e0f904bb6eec26c8b2f366b Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 12 May 2021 12:40:37 +0200 Subject: [nvptx] Add -mptx=3.1/6.3 Add nvptx option -mptx that sets the ptx ISA version. This is currently hardcoded to 3.1. Tested libgomp on x86_64-linux with nvptx accelerator, both with default set to 3.1 and 6.3. gcc/ChangeLog: 2021-05-12 Tom de Vries PR target/96005 * config/nvptx/nvptx-opts.h (enum ptx_version): New enum. * config/nvptx/nvptx.c (nvptx_file_start): Print .version according to ptx_version_option. * config/nvptx/nvptx.h (TARGET_PTX_6_3): Define. * config/nvptx/nvptx.md (define_insn "nvptx_shuffle") (define_insn "nvptx_vote_ballot"): Use sync variant for TARGET_PTX_6_3. * config/nvptx/nvptx.opt (ptx_version): Add enum. (mptx): Add option. * doc/invoke.texi (Nvidia PTX Options): Add mptx item. --- gcc/config/nvptx/nvptx-opts.h | 6 ++++++ gcc/config/nvptx/nvptx.c | 5 ++++- gcc/config/nvptx/nvptx.h | 2 ++ gcc/config/nvptx/nvptx.md | 14 ++++++++++++-- gcc/config/nvptx/nvptx.opt | 14 ++++++++++++++ gcc/doc/invoke.texi | 6 ++++++ 6 files changed, 44 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/config/nvptx/nvptx-opts.h b/gcc/config/nvptx/nvptx-opts.h index ce88245..bfa926e 100644 --- a/gcc/config/nvptx/nvptx-opts.h +++ b/gcc/config/nvptx/nvptx-opts.h @@ -26,5 +26,11 @@ enum ptx_isa PTX_ISA_SM35 }; +enum ptx_version +{ + PTX_VERSION_3_1, + PTX_VERSION_6_3 +}; + #endif diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index 7a7a913..ebbfa92 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -5309,7 +5309,10 @@ static void nvptx_file_start (void) { fputs ("// BEGIN PREAMBLE\n", asm_out_file); - fputs ("\t.version\t3.1\n", asm_out_file); + if (TARGET_PTX_6_3) + fputs ("\t.version\t6.3\n", asm_out_file); + else + fputs ("\t.version\t3.1\n", asm_out_file); if (TARGET_SM35) fputs ("\t.target\tsm_35\n", asm_out_file); else diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h index 2451703..fdaacdd 100644 --- a/gcc/config/nvptx/nvptx.h +++ b/gcc/config/nvptx/nvptx.h @@ -98,6 +98,8 @@ #define TARGET_SM35 (ptx_isa_option >= PTX_ISA_SM35) +#define TARGET_PTX_6_3 (ptx_version_option >= PTX_VERSION_6_3) + /* Registers. Since ptx is a virtual target, we just define a few hard registers for special purposes and leave pseudos unallocated. We have to have some available hard registers, to keep gcc setup diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 0f15609..00bb8fe 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -1452,14 +1452,24 @@ (match_operand:SI 3 "const_int_operand" "n")] UNSPEC_SHUFFLE))] "" - "%.\\tshfl%S3.b32\\t%0, %1, %2, 31;") + { + if (TARGET_PTX_6_3) + return "%.\\tshfl.sync%S3.b32\\t%0, %1, %2, 31, 0xffffffff;"; + else + return "%.\\tshfl%S3.b32\\t%0, %1, %2, 31;"; + }) (define_insn "nvptx_vote_ballot" [(set (match_operand:SI 0 "nvptx_register_operand" "=R") (unspec:SI [(match_operand:BI 1 "nvptx_register_operand" "R")] UNSPEC_VOTE_BALLOT))] "" - "%.\\tvote.ballot.b32\\t%0, %1;") + { + if (TARGET_PTX_6_3) + return "%.\\tvote.sync.ballot.b32\\t%0, %1, 0xffffffff;"; + else + return "%.\\tvote.ballot.b32\\t%0, %1;"; + }) ;; Patterns for OpenMP SIMD-via-SIMT lowering diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt index 51363e4..468c6ca 100644 --- a/gcc/config/nvptx/nvptx.opt +++ b/gcc/config/nvptx/nvptx.opt @@ -65,3 +65,17 @@ Enum(ptx_isa) String(sm_35) Value(PTX_ISA_SM35) misa= Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) Init(PTX_ISA_SM35) Specify the version of the ptx ISA to use. + +Enum +Name(ptx_version) Type(int) +Known PTX versions (for use with the -mptx= option): + +EnumValue +Enum(ptx_version) String(3.1) Value(PTX_VERSION_3_1) + +EnumValue +Enum(ptx_version) String(6.3) Value(PTX_VERSION_6_3) + +mptx= +Target RejectNegative ToLower Joined Enum(ptx_version) Var(ptx_version_option) Init(PTX_VERSION_3_1) +Specify the version of the ptx version to use. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index fddaa8c..5198815 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -26284,6 +26284,12 @@ Generate code for given the specified PTX ISA (e.g.@: @samp{sm_35}). ISA strings must be lower-case. Valid ISA strings include @samp{sm_30} and @samp{sm_35}. The default ISA is sm_35. +@item -mptx=@var{version-string} +@opindex mptx +Generate code for given the specified PTX version (e.g.@: @samp{6.3}). +Valid version strings include @samp{3.1} and @samp{6.3}. The default PTX +version is 3.1. + @item -mmainkernel @opindex mmainkernel Link in code for a __main kernel. This is for stand-alone instead of -- cgit v1.1 From fa6894ec9ce25f5aff10ec176212383f5c88b1ec Mon Sep 17 00:00:00 2001 From: Marcel Vollweiler Date: Wed, 12 May 2021 09:31:58 -0700 Subject: OpenMP: Add support for 'close' in map clause gcc/c/ChangeLog: * c-parser.c (c_parser_omp_clause_map): Support map-type-modifier 'close'. gcc/cp/ChangeLog: * parser.c (cp_parser_omp_clause_map): Support map-type-modifier 'close'. gcc/testsuite/ChangeLog: * c-c++-common/gomp/map-6.c: New test. * c-c++-common/gomp/map-7.c: New test. --- gcc/c/c-parser.c | 116 +++++++++++++-------------- gcc/cp/parser.c | 90 ++++++++++++++++----- gcc/testsuite/c-c++-common/gomp/map-6.c | 135 ++++++++++++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/map-7.c | 20 +++++ 4 files changed, 283 insertions(+), 78 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/map-6.c create mode 100644 gcc/testsuite/c-c++-common/gomp/map-7.c (limited to 'gcc') diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 5cdeb21..f79b839 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -15643,54 +15643,83 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) map-kind: alloc | to | from | tofrom | release | delete - map ( always [,] map-kind: variable-list ) */ + map ( always [,] map-kind: variable-list ) + + OpenMP 5.0: + map ( [map-type-modifier[,] ...] map-kind: variable-list ) + + map-type-modifier: + always | close */ static tree c_parser_omp_clause_map (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; enum gomp_map_kind kind = GOMP_MAP_TOFROM; - int always = 0; - enum c_id_kind always_id_kind = C_ID_NONE; - location_t always_loc = UNKNOWN_LOCATION; - tree always_id = NULL_TREE; tree nl, c; matching_parens parens; if (!parens.require_open (parser)) return list; - if (c_parser_next_token_is (parser, CPP_NAME)) + int pos = 1; + int map_kind_pos = 0; + while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME) + { + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON) + { + map_kind_pos = pos; + break; + } + + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA) + pos++; + pos++; + } + + int always_modifier = 0; + int close_modifier = 0; + for (int pos = 1; pos < map_kind_pos; ++pos) { c_token *tok = c_parser_peek_token (parser); + + if (tok->type == CPP_COMMA) + { + c_parser_consume_token (parser); + continue; + } + const char *p = IDENTIFIER_POINTER (tok->value); - always_id_kind = tok->id_kind; - always_loc = tok->location; - always_id = tok->value; if (strcmp ("always", p) == 0) { - c_token *sectok = c_parser_peek_2nd_token (parser); - if (sectok->type == CPP_COMMA) + if (always_modifier) { - c_parser_consume_token (parser); - c_parser_consume_token (parser); - always = 2; + c_parser_error (parser, "too many % modifiers"); + parens.skip_until_found_close (parser); + return list; } - else if (sectok->type == CPP_NAME) + always_modifier++; + } + else if (strcmp ("close", p) == 0) + { + if (close_modifier) { - p = IDENTIFIER_POINTER (sectok->value); - if (strcmp ("alloc", p) == 0 - || strcmp ("to", p) == 0 - || strcmp ("from", p) == 0 - || strcmp ("tofrom", p) == 0 - || strcmp ("release", p) == 0 - || strcmp ("delete", p) == 0) - { - c_parser_consume_token (parser); - always = 1; - } + c_parser_error (parser, "too many % modifiers"); + parens.skip_until_found_close (parser); + return list; } + close_modifier++; } + else + { + c_parser_error (parser, "%<#pragma omp target%> with " + "modifier other than % or %" + "on % clause"); + parens.skip_until_found_close (parser); + return list; + } + + c_parser_consume_token (parser); } if (c_parser_next_token_is (parser, CPP_NAME) @@ -15700,11 +15729,11 @@ c_parser_omp_clause_map (c_parser *parser, tree list) if (strcmp ("alloc", p) == 0) kind = GOMP_MAP_ALLOC; else if (strcmp ("to", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO; + kind = always_modifier ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO; else if (strcmp ("from", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM; + kind = always_modifier ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM; else if (strcmp ("tofrom", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM; + kind = always_modifier ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM; else if (strcmp ("release", p) == 0) kind = GOMP_MAP_RELEASE; else if (strcmp ("delete", p) == 0) @@ -15719,35 +15748,6 @@ c_parser_omp_clause_map (c_parser *parser, tree list) c_parser_consume_token (parser); c_parser_consume_token (parser); } - else if (always) - { - if (always_id_kind != C_ID_ID) - { - c_parser_error (parser, "expected identifier"); - parens.skip_until_found_close (parser); - return list; - } - - tree t = lookup_name (always_id); - if (t == NULL_TREE) - { - undeclared_variable (always_loc, always_id); - t = error_mark_node; - } - if (t != error_mark_node) - { - tree u = build_omp_clause (clause_loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_DECL (u) = t; - OMP_CLAUSE_CHAIN (u) = list; - OMP_CLAUSE_SET_MAP_KIND (u, kind); - list = u; - } - if (always == 1) - { - parens.skip_until_found_close (parser); - return list; - } - } nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0fe29c6..41df5dd 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -37859,40 +37859,90 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) map-kind: alloc | to | from | tofrom | release | delete - map ( always [,] map-kind: variable-list ) */ + map ( always [,] map-kind: variable-list ) + + OpenMP 5.0: + map ( [map-type-modifier[,] ...] map-kind: variable-list ) + + map-type-modifier: + always | close */ static tree cp_parser_omp_clause_map (cp_parser *parser, tree list) { tree nlist, c; enum gomp_map_kind kind = GOMP_MAP_TOFROM; - bool always = false; if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + int pos = 1; + int map_kind_pos = 0; + while (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_NAME + || cp_lexer_peek_nth_token (parser->lexer, pos)->keyword == RID_DELETE) { - tree id = cp_lexer_peek_token (parser->lexer)->u.value; - const char *p = IDENTIFIER_POINTER (id); + if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COLON) + { + map_kind_pos = pos; + break; + } + + if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA) + pos++; + pos++; + } + bool always_modifier = false; + bool close_modifier = false; + for (int pos = 1; pos < map_kind_pos; ++pos) + { + cp_token *tok = cp_lexer_peek_token (parser->lexer); + if (tok->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); + continue; + } + + const char *p = IDENTIFIER_POINTER (tok->u.value); if (strcmp ("always", p) == 0) { - int nth = 2; - if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COMMA) - nth++; - if ((cp_lexer_peek_nth_token (parser->lexer, nth)->type == CPP_NAME - || (cp_lexer_peek_nth_token (parser->lexer, nth)->keyword - == RID_DELETE)) - && (cp_lexer_peek_nth_token (parser->lexer, nth + 1)->type - == CPP_COLON)) + if (always_modifier) { - always = true; - cp_lexer_consume_token (parser->lexer); - if (nth == 3) - cp_lexer_consume_token (parser->lexer); + cp_parser_error (parser, "too many % modifiers"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + always_modifier = true; + } + else if (strcmp ("close", p) == 0) + { + if (close_modifier) + { + cp_parser_error (parser, "too many % modifiers"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; } + close_modifier = true; } + else + { + cp_parser_error (parser, "%<#pragma omp target%> with " + "modifier other than % or %" + "on % clause"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + + cp_lexer_consume_token (parser->lexer); } if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) @@ -37904,11 +37954,11 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list) if (strcmp ("alloc", p) == 0) kind = GOMP_MAP_ALLOC; else if (strcmp ("to", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO; + kind = always_modifier ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO; else if (strcmp ("from", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM; + kind = always_modifier ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM; else if (strcmp ("tofrom", p) == 0) - kind = always ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM; + kind = always_modifier ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM; else if (strcmp ("release", p) == 0) kind = GOMP_MAP_RELEASE; else diff --git a/gcc/testsuite/c-c++-common/gomp/map-6.c b/gcc/testsuite/c-c++-common/gomp/map-6.c new file mode 100644 index 0000000..6ee5971 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/map-6.c @@ -0,0 +1,135 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-original" } */ + +void +foo (void) +{ + /* Test to ensure that the close modifier is parsed and ignored in map clauses. */ + int a, b, b1, b2, b3, b4, b5, b6, b7; + + #pragma omp target map (a) + ; + + #pragma omp target map (to:a) + ; + + #pragma omp target map (a to: b) /* { dg-error "'#pragma omp target' with modifier other than 'always' or 'close'" } */ + ; + + #pragma omp target map (close, a to: b) /* { dg-error "'#pragma omp target' with modifier other than 'always' or 'close'" } */ + ; + + #pragma omp target map (close a) /* { dg-error "'close' undeclared" "" { target c } } */ + /* { dg-error "'close' has not been declared" "" { target c++ } .-1 } */ + /* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */ + ; + + #pragma omp target map (always a) /* { dg-error "'always' undeclared" "" { target c } } */ + /* { dg-error "'always' has not been declared" "" { target c++ } .-1 } */ + /* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */ + ; + + #pragma omp target map (close to:a) + ; + + #pragma omp target map (close, to:a) + ; + + #pragma omp target map (close delete:a) /* { dg-error "'#pragma omp target' with map-type other than 'to', 'from', 'tofrom' or 'alloc' on 'map' clause" } */ + ; + + #pragma omp target map (close always to:b1) + ; + + #pragma omp target map (close, always to:b2) + ; + + #pragma omp target map (close, always, to:b3) + ; + + #pragma omp target map (always close to:b4) + ; + + #pragma omp target map (always, close to:b5) + ; + + #pragma omp target map (always, close, to:b6) + ; + + #pragma omp target map (always, always, to:a) /* { dg-error "too many 'always' modifiers" } */ + ; + + #pragma omp target map (always always, to:a) /* { dg-error "too many 'always' modifiers" } */ + ; + + #pragma omp target map (always, always to:a) /* { dg-error "too many 'always' modifiers" } */ + ; + + #pragma omp target map (always always to:a) /* { dg-error "too many 'always' modifiers" } */ + ; + + #pragma omp target map (close, close, to:a) /* { dg-error "too many 'close' modifiers" } */ + ; + + #pragma omp target map (close close, to:a) /* { dg-error "too many 'close' modifiers" } */ + ; + + #pragma omp target map (close, close to:a) /* { dg-error "too many 'close' modifiers" } */ + ; + + #pragma omp target map (close close to:a) /* { dg-error "too many 'close' modifiers" } */ + ; + + #pragma omp target map (always to : a) map (close to : b) + ; + + int close = 0; + #pragma omp target map (close) + ; + + #pragma omp target map (close a) /* { dg-error "expected '\\)' before 'a'" } */ + ; + + int always = 0; + #pragma omp target map (always) + ; + + #pragma omp target map (always a) /* { dg-error "expected '\\)' before 'a'" } */ + ; + + #pragma omp target map (always, close) + ; + + #pragma omp target map (always, always) /* { dg-error "'always' appears more than once in map clauses" } */ + ; + + #pragma omp target map (always, always, close) /* { dg-error "'always' appears more than once in map clauses" } */ + ; + + #pragma omp target map (always, close, to: always, close, b7) + ; + + int to = 0; + #pragma omp target map (always, close, to) + ; + + #pragma omp target map (to, always, close) + { + to = always = close = 1; + } + if (to != 1 || always != 1 || close != 1) + __builtin_abort (); + ; +} + +/* { dg-final { scan-tree-dump-not "map\\(\[^\n\r)]*close\[^\n\r)]*to:" "original" } } */ + +/* { dg-final { scan-tree-dump-times "pragma omp target map\\(always,to:" 7 "original" } } */ + +/* { dg-final { scan-tree-dump "pragma omp target map\\(always,to:b1" "original" } } */ +/* { dg-final { scan-tree-dump "pragma omp target map\\(always,to:b2" "original" } } */ +/* { dg-final { scan-tree-dump "pragma omp target map\\(always,to:b3" "original" } } */ +/* { dg-final { scan-tree-dump "pragma omp target map\\(always,to:b4" "original" } } */ +/* { dg-final { scan-tree-dump "pragma omp target map\\(always,to:b5" "original" } } */ +/* { dg-final { scan-tree-dump "pragma omp target map\\(always,to:b6" "original" } } */ +/* { dg-final { scan-tree-dump "pragma omp target map\\(always,to:b7\\) map\\(always,to:close\\) map\\(always,to:always\\)" "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/map-7.c b/gcc/testsuite/c-c++-common/gomp/map-7.c new file mode 100644 index 0000000..3f1e972 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/map-7.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +void +foo (void) +{ + /* Test to ensure that the close modifier is parsed and ignored in map clauses. */ + + #define N 1024 + int always[N]; + int close; + + #pragma omp target map(always[:N]) + ; + + #pragma omp target map(close, always[:N]) + ; + + #pragma omp target map(always[:N], close) + ; +} -- cgit v1.1 From 3a2b12bc5a7da7f0c5cf2ef4879d435a02feda8d Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 12 May 2021 11:19:13 -0400 Subject: c++: Disable -Wint-in-bool-context in instantiations This warning is of questionable value when it's emitted when instantiating a template, as in the following testcase. It could be silenced by writing hb(i) << 1 instead of 2 * hb(i) but that's unnecessary obfuscation. gcc/cp/ChangeLog: * pt.c (tsubst_copy_and_build): Add warn_int_in_bool_context sentinel. gcc/testsuite/ChangeLog: * g++.dg/warn/Wint-in-bool-context-2.C: New test. --- gcc/cp/pt.c | 1 + gcc/testsuite/g++.dg/warn/Wint-in-bool-context-2.C | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/Wint-in-bool-context-2.C (limited to 'gcc') diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 85c05af..d7d6a3f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -19801,6 +19801,7 @@ tsubst_copy_and_build (tree t, warning_sentinel s(warn_useless_cast); warning_sentinel s2(warn_ignored_qualifiers); + warning_sentinel s3(warn_int_in_bool_context); switch (TREE_CODE (t)) { case CAST_EXPR: diff --git a/gcc/testsuite/g++.dg/warn/Wint-in-bool-context-2.C b/gcc/testsuite/g++.dg/warn/Wint-in-bool-context-2.C new file mode 100644 index 0000000..6cb482d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wint-in-bool-context-2.C @@ -0,0 +1,16 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-Wint-in-bool-context" } + +unsigned hb(unsigned i) { return ~i; } + +template +void f(int i) +{ + auto l = [i]() { return T(2 * hb(i)); }; // { dg-bogus "in boolean context" } + (void) l; +} + +int main() +{ + f(0); +} -- cgit v1.1 From d902a1b57606536982a1001670f998de685eaf7c Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Wed, 12 May 2021 15:22:15 -0400 Subject: Skip out on processing __builtin_clz when varying. The previous changes to irange::constant_p return TRUE for VARYING, since VARYING has numerical end points like any other constant range. The problem is that some users of constant_p depended on constant_p excluding the full domain. The range handler for __builtin_clz, that is shared between ranger and vr_values, is one such user. This patch excludes varying_p(), to match the original behavior for clz. gcc/ChangeLog: PR c/100521 * gimple-range.cc (range_of_builtin_call): Skip out on processing __builtin_clz when varying. --- gcc/gimple-range.cc | 2 +- gcc/testsuite/gcc.dg/pr100521.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr100521.c (limited to 'gcc') diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index e94bb35..5b288d8 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -737,7 +737,7 @@ range_of_builtin_call (range_query &query, irange &r, gcall *call) query.range_of_expr (r, arg, call); // From clz of minimum we can compute result maximum. - if (r.constant_p ()) + if (r.constant_p () && !r.varying_p ()) { int newmaxi = prec - 1 - wi::floor_log2 (r.lower_bound ()); // Argument is unsigned, so do nothing if it is [0, ...] range. diff --git a/gcc/testsuite/gcc.dg/pr100521.c b/gcc/testsuite/gcc.dg/pr100521.c new file mode 100644 index 0000000..fd9f0db --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr100521.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int +__builtin_clz (int a) +{ + return __builtin_clz(a); +} -- cgit v1.1 From db514f98a383b2ebdcfe74feb80f98f406cec174 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 12 May 2021 15:57:34 -0600 Subject: Add test for PR middle-end/100571. gcc/testsuite: PR middle-end/100571 * gcc.dg/Wstringop-overflow-67.c: New test. --- gcc/testsuite/gcc.dg/Wstringop-overflow-67.c | 92 ++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-67.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-67.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-67.c new file mode 100644 index 0000000..7b8f3f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-67.c @@ -0,0 +1,92 @@ +/* PR middle-end/100571 - bogus -Wstringop-overflow with VLA of elements + larger than byte + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +__attribute__ ((access (read_only, 1, 2))) void fro (int *, int); +__attribute__ ((access (write_only, 1, 2))) void fwo (int *, int); +__attribute__ ((access (read_write, 1, 2))) void frw (int *, int); + +extern __SIZE_TYPE__ n; + +void alloca_ro (void) +{ + int *a = __builtin_alloca (n * sizeof *a); + a[0] = 0; + fro (a, n); +} + +void alloca_wo (void) +{ + int *a = __builtin_alloca (n * sizeof *a); + fwo (a, n); +} + +void alloca_rw (void) +{ + int *a = __builtin_alloca (n * sizeof *a); + a[0] = 0; + frw (a, n); +} + + +void calloc_ro (void) +{ + int *a = __builtin_calloc (n, sizeof *a); + fro (a, n); +} + +void calloc_wo (void) +{ + int *a = __builtin_calloc (n, sizeof *a); + fwo (a, n); +} + +void calloc_rw (void) +{ + int *a = __builtin_calloc (n, sizeof *a); + a[0] = 0; + frw (a, n); +} + + +void malloc_ro (void) +{ + int *a = __builtin_malloc (n * sizeof *a); + a[0] = 0; + fro (a, n); +} + +void malloc_wo (void) +{ + int *a = __builtin_malloc (n * sizeof *a); + fwo (a, n); +} + +void malloc_rw (void) +{ + int *a = __builtin_malloc (n * sizeof *a); + a[0] = 0; + frw (a, n); +} + + +void vla_ro (void) +{ + int a[n]; + a[0] = 0; + fro (a, n); +} + +void vla_wo (void) +{ + int a[n]; + fwo (a, n); +} + +void vla_rw (void) +{ + int a[n]; + a[0] = 0; + frw (a, n); +} -- cgit v1.1 From d21963ce7a87db3d4a6921a0fa98b72ea6f4e7f5 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Thu, 13 May 2021 00:12:31 +0200 Subject: OpenMP: detach - fix firstprivate handling gcc/ChangeLog: * omp-low.c (finish_taskreg_scan): Use the proper detach decl. libgomp/ChangeLog: * testsuite/libgomp.c-c++-common/task-detach-12.c: New test. * testsuite/libgomp.fortran/task-detach-12.f90: New test. --- gcc/omp-low.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/omp-low.c b/gcc/omp-low.c index c0ce1a4..cadca7e 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -2460,7 +2460,7 @@ finish_taskreg_scan (omp_context *ctx) TYPE_FIELDS (ctx->record_type) = field; if (ctx->srecord_type) { - field = lookup_sfield (OMP_CLAUSE_DECL (detach_clause), ctx); + field = lookup_sfield (OMP_CLAUSE_DECL (c), ctx); p = &TYPE_FIELDS (ctx->srecord_type); while (*p) if (*p == field) -- cgit v1.1 From 56b9b60464e851b5874c0da79b0eefc45b543709 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 12 May 2021 21:05:26 -0300 Subject: retry zero-call-used-regs from zeroed regs default_zero_call_used_regs currently requires all potentially zeroed registers to offer a move opcode that accepts zero as an operand. This is not the case e.g. for ARM's r12/ip in Thumb mode, and it was not the case of FP registers on AArch64 as of GCC 10. This patch introduces a fallback strategy to zero out registers, copying from registers that have already been zeroed. Adjacent sources to make up wider modes are also supported. This does not guarantee that there will be some zeroed-out register to use as the source, but it expands the cases in which the default implementation works out of the box. for gcc/ChangeLog * targhooks.c (default_zero_call_used_regs): Retry using successfully-zeroed registers as sources. --- gcc/targhooks.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 2e0fdb7..1947ef2 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1001,6 +1001,13 @@ default_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs) { gcc_assert (!hard_reg_set_empty_p (need_zeroed_hardregs)); + HARD_REG_SET failed; + CLEAR_HARD_REG_SET (failed); + bool progress = false; + + /* First, try to zero each register in need_zeroed_hardregs by + loading a zero into it, taking note of any failures in + FAILED. */ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno)) { @@ -1010,16 +1017,88 @@ default_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs) rtx_insn *insn = emit_move_insn (regno_reg_rtx[regno], zero); if (!valid_insn_p (insn)) { - static bool issued_error; - if (!issued_error) - { - issued_error = true; - sorry ("%qs not supported on this target", - "-fzero-call-used-regs"); - } + SET_HARD_REG_BIT (failed, regno); delete_insns_since (last_insn); } + else + progress = true; } + + /* Now retry with copies from zeroed registers, as long as we've + made some PROGRESS, and registers remain to be zeroed in + FAILED. */ + while (progress && !hard_reg_set_empty_p (failed)) + { + HARD_REG_SET retrying = failed; + + CLEAR_HARD_REG_SET (failed); + progress = false; + + for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (TEST_HARD_REG_BIT (retrying, regno)) + { + machine_mode mode = GET_MODE (regno_reg_rtx[regno]); + bool success = false; + /* Look for a source. */ + for (unsigned int src = 0; src < FIRST_PSEUDO_REGISTER; src++) + { + /* If SRC hasn't been zeroed (yet?), skip it. */ + if (! TEST_HARD_REG_BIT (need_zeroed_hardregs, src)) + continue; + if (TEST_HARD_REG_BIT (retrying, src)) + continue; + + /* Check that SRC can hold MODE, and that any other + registers needed to hold MODE in SRC have also been + zeroed. */ + if (!targetm.hard_regno_mode_ok (src, mode)) + continue; + unsigned n = targetm.hard_regno_nregs (src, mode); + bool ok = true; + for (unsigned i = 1; ok && i < n; i++) + ok = (TEST_HARD_REG_BIT (need_zeroed_hardregs, src + i) + && !TEST_HARD_REG_BIT (retrying, src + i)); + if (!ok) + continue; + + /* SRC is usable, try to copy from it. */ + rtx_insn *last_insn = get_last_insn (); + rtx zsrc = gen_rtx_REG (mode, src); + rtx_insn *insn = emit_move_insn (regno_reg_rtx[regno], zsrc); + if (!valid_insn_p (insn)) + /* It didn't work, remove any inserts. We'll look + for another SRC. */ + delete_insns_since (last_insn); + else + { + /* We're done for REGNO. */ + success = true; + break; + } + } + + /* If nothing worked for REGNO this round, marked it to be + retried if we get another round. */ + if (!success) + SET_HARD_REG_BIT (failed, regno); + else + /* Take note so as to enable another round if needed. */ + progress = true; + } + } + + /* If any register remained, report it. */ + if (!progress) + { + static bool issued_error; + if (!issued_error) + { + issued_error = true; + sorry ("%qs not supported on this target", + "-fzero-call-used-regs"); + } + } + return need_zeroed_hardregs; } -- cgit v1.1 From 0ff3a0f2b9d5cbea70d134cda2e74b674f8be9c9 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 13 May 2021 00:16:29 +0000 Subject: Daily bump. --- gcc/ChangeLog | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 12 +++++++ gcc/c/ChangeLog | 5 +++ gcc/cp/ChangeLog | 10 ++++++ gcc/testsuite/ChangeLog | 51 +++++++++++++++++++++++++++ 6 files changed, 172 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d0df507..9e39086 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,96 @@ +2021-05-13 Alexandre Oliva + + * targhooks.c (default_zero_call_used_regs): Retry using + successfully-zeroed registers as sources. + +2021-05-12 Tobias Burnus + + * omp-low.c (finish_taskreg_scan): Use the proper detach decl. + +2021-05-12 Aldy Hernandez + + PR c/100521 + * gimple-range.cc (range_of_builtin_call): Skip out on + processing __builtin_clz when varying. + +2021-05-12 Tom de Vries + + PR target/96005 + * config/nvptx/nvptx-opts.h (enum ptx_version): New enum. + * config/nvptx/nvptx.c (nvptx_file_start): Print .version according + to ptx_version_option. + * config/nvptx/nvptx.h (TARGET_PTX_6_3): Define. + * config/nvptx/nvptx.md (define_insn "nvptx_shuffle") + (define_insn "nvptx_vote_ballot"): Use sync variant for + TARGET_PTX_6_3. + * config/nvptx/nvptx.opt (ptx_version): Add enum. + (mptx): Add option. + * doc/invoke.texi (Nvidia PTX Options): Add mptx item. + +2021-05-12 Richard Biener + + PR tree-optimization/100566 + * tree-ssa-sccvn.c (dominated_by_p_w_unex): Properly handle + allow_back for all edge queries. + +2021-05-12 liuhongt + + PR target/99908 + * config/i386/sse.md (_pblendvb): Add + splitters for pblendvb of NOT mask register. + +2021-05-12 Richard Biener + + PR tree-optimization/100519 + * tree-ssa-reassoc.c (can_associate_p): Split into... + (can_associate_op_p): ... this + (can_associate_type_p): ... and this. + (is_reassociable_op): Call can_associate_op_p. + (break_up_subtract_bb): Call the appropriate predicates. + (reassociate_bb): Likewise. + +2021-05-12 Martin Liska + + * lto-wrapper.c (merge_and_complain): Merge -flto=arg options. + (run_gcc): Use -flto argument detection for merged + fdecoded_options. + +2021-05-12 Martin Liska + + * lto-wrapper.c (print_lto_docs_link): New function. + (run_gcc): Print warning about missing job server detection + after we know NR of partitions. Do the same for -flto{,=1}. + * opts.c (get_option_html_page): Support -flto option. + +2021-05-12 Martin Liska + + * lto-wrapper.c (get_options_from_collect_gcc_options): Change + return type. + (append_option): Remove. + (find_option): Rework to use the vector type. + (remove_option): Remove. + (merge_and_complain): Use vectors for cl_decoded_option data + type arguments. + (append_compiler_options): Likewise. + (append_diag_options): Likewise. + (append_linker_options): Likewise. + (append_offload_options): Likewise. + (compile_offload_image): Likewise. + (compile_images_for_offload_targets): Likewise. + (find_and_merge_options): Likewise. + (run_gcc): Likewise. + +2021-05-12 Bernd Edlinger + + PR debug/100515 + * dwarf2out.c (dwarf2out_finish): Set + have_multiple_function_sections with multi-range text_section. + +2021-05-12 Martin Liska + + PR bootstrap/100560 + * Makefile.in: Remove version.h from linker command line. + 2021-05-12 Richard Biener PR middle-end/100547 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d143140..92e74b6 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210512 +20210513 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4261aa6..2279e46 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,15 @@ +2021-05-12 Bob Duff + + PR ada/100564 + * atree.adb (Change_Node): Do not call Zero_Slots on a Node_Id + when the Nkind has not yet been set; call the other Zero_Slots + that takes a range of slot offsets. Call the new Mutate_Kind + that takes an Old_Size, for the same reason -- the size cannot + be computed without the Nkind. + (Mutate_Nkind): New function that allows specifying the Old_Size. + (Size_In_Slots): Assert that the Nkind has proper (nonzero) value. + * atree.ads: Minor reformatting. + 2021-05-12 Martin Liska * doc/share/conf.py: Do not use binary mode. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index d003883..0690d93 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2021-05-12 Marcel Vollweiler + + * c-parser.c (c_parser_omp_clause_map): Support map-type-modifier + 'close'. + 2021-05-10 Martin Liska * c-aux-info.c (affix_data_type): Use startswith diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 80ea065..5a8a650 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2021-05-12 Marek Polacek + + * pt.c (tsubst_copy_and_build): Add warn_int_in_bool_context + sentinel. + +2021-05-12 Marcel Vollweiler + + * parser.c (cp_parser_omp_clause_map): Support map-type-modifier + 'close'. + 2021-05-11 Jason Merrill PR c++/100517 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fd12630..82ef74c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,54 @@ +2021-05-12 Martin Sebor + + PR middle-end/100571 + * gcc.dg/Wstringop-overflow-67.c: New test. + +2021-05-12 Aldy Hernandez + + PR c/100521 + * gcc.dg/pr100521.c: New file. + +2021-05-12 Marek Polacek + + * g++.dg/warn/Wint-in-bool-context-2.C: New test. + +2021-05-12 Marcel Vollweiler + + * c-c++-common/gomp/map-6.c: New test. + * c-c++-common/gomp/map-7.c: New test. + +2021-05-12 Richard Biener + + PR tree-optimization/100566 + * gcc.dg/torture/pr100566.c: New testcase. + +2021-05-12 Jakub Jelinek + + PR preprocessor/100392 + * gcc.dg/cpp/pr100392.c: New test. + * gcc.dg/cpp/pr100392.h: New file. + +2021-05-12 Martin Liska + + * lib/lto.exp: When running tests without jobserver, one can see + the following warning for tests that use 1to1 partitioning. + +2021-05-12 liuhongt + + PR target/99908 + * gcc.target/i386/avx2-pr99908.c: New test. + * gcc.target/i386/sse4_1-pr99908.c: New test. + +2021-05-12 Richard Biener + + PR tree-optimization/100519 + * gcc.dg/torture/pr100519.c: New testcase. + +2021-05-12 Bernd Edlinger + + PR debug/100515 + * gcc.dg/debug/dwarf2/pr100515.c: New testcase. + 2021-05-12 Jakub Jelinek PR middle-end/100508 -- cgit v1.1 From 94de7e225c1fda079052c3f0725c926437d56c94 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Thu, 22 Apr 2021 15:33:16 +0800 Subject: Optimize __builtin_shuffle when it's used to zero the upper bits of the dest. [PR target/94680] If the second operand of __builtin_shuffle is const vector 0, and with specific mask, it can be optimized to movq/vmovps. .i.e. foo128: - vxorps %xmm1, %xmm1, %xmm1 - vmovlhps %xmm1, %xmm0, %xmm0 + vmovq %xmm0, %xmm0 foo256: - vxorps %xmm1, %xmm1, %xmm1 - vshuff32x4 $0, %ymm1, %ymm0, %ymm0 + vmovaps %xmm0, %xmm0 foo512: - vxorps %xmm1, %xmm1, %xmm1 - vshuff32x4 $68, %zmm1, %zmm0, %zmm0 + vmovaps %ymm0, %ymm0 gcc/ChangeLog: PR target/94680 * config/i386/sse.md (ssedoublevecmode): Add attribute for V64QI/V32HI/V16SI/V4DI. (ssehalfvecmode): Add attribute for V2DI/V2DF. (*vec_concatv4si_0): Extend to VI124_128. (*vec_concat_0): New pre-reload splitter. * config/i386/predicates.md (movq_parallel): New predicate. gcc/testsuite/ChangeLog: PR target/94680 * gcc.target/i386/avx-pr94680.c: New test. * gcc.target/i386/avx512f-pr94680.c: New test. * gcc.target/i386/sse2-pr94680.c: New test. --- gcc/config/i386/predicates.md | 32 ++++++ gcc/config/i386/sse.md | 37 ++++-- gcc/testsuite/gcc.target/i386/avx-pr94680.c | 107 ++++++++++++++++++ gcc/testsuite/gcc.target/i386/avx512f-pr94680.c | 144 ++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/sse2-pr94680.c | 91 +++++++++++++++ 5 files changed, 403 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/avx-pr94680.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512f-pr94680.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-pr94680.c (limited to 'gcc') diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 6dfbb08..abd307e 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1535,6 +1535,38 @@ (and (match_code "mem") (match_test "MEM_ALIGN (op) < GET_MODE_BITSIZE (mode)"))) +;; Return true if OP is a parallel for an mov{d,q,dqa,ps,pd} vec_select, +;; where one of the two operands of the vec_concat is const0_operand. +(define_predicate "movq_parallel" + (match_code "parallel") +{ + unsigned nelt = XVECLEN (op, 0); + unsigned nelt2 = nelt >> 1; + unsigned i; + + if (nelt < 2) + return false; + + /* Validate that all of the elements are constants, + lower halves of permute are lower halves of the first operand, + upper halves of permute come from any of the second operand. */ + for (i = 0; i < nelt; ++i) + { + rtx er = XVECEXP (op, 0, i); + unsigned HOST_WIDE_INT ei; + + if (!CONST_INT_P (er)) + return 0; + ei = INTVAL (er); + if (i < nelt2 && ei != i) + return 0; + if (i >= nelt2 && (ei < nelt || ei >= nelt << 1)) + return 0; + } + + return 1; +}) + ;; Return true if OP is a vzeroall operation, known to be a PARALLEL. (define_predicate "vzeroall_operation" (match_code "parallel") diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 49dda74..4072d0c 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -811,19 +811,22 @@ ;; Mapping of vector modes to a vector mode of double size (define_mode_attr ssedoublevecmode - [(V32QI "V64QI") (V16HI "V32HI") (V8SI "V16SI") (V4DI "V8DI") + [(V64QI "V128QI") (V32HI "V64HI") (V16SI "V32SI") (V8DI "V16DI") + (V32QI "V64QI") (V16HI "V32HI") (V8SI "V16SI") (V4DI "V8DI") (V16QI "V32QI") (V8HI "V16HI") (V4SI "V8SI") (V2DI "V4DI") + (V16SF "V32SF") (V8DF "V16DF") (V8SF "V16SF") (V4DF "V8DF") (V4SF "V8SF") (V2DF "V4DF")]) ;; Mapping of vector modes to a vector mode of half size +;; instead of V1DI/V1DF, DI/DF are used for V2DI/V2DF although they are scalar. (define_mode_attr ssehalfvecmode [(V64QI "V32QI") (V32HI "V16HI") (V16SI "V8SI") (V8DI "V4DI") (V4TI "V2TI") (V32QI "V16QI") (V16HI "V8HI") (V8SI "V4SI") (V4DI "V2DI") - (V16QI "V8QI") (V8HI "V4HI") (V4SI "V2SI") + (V16QI "V8QI") (V8HI "V4HI") (V4SI "V2SI") (V2DI "DI") (V16SF "V8SF") (V8DF "V4DF") (V8SF "V4SF") (V4DF "V2DF") - (V4SF "V2SF")]) + (V4SF "V2SF") (V2DF "DF")]) (define_mode_attr ssehalfvecmodelower [(V64QI "v32qi") (V32HI "v16hi") (V16SI "v8si") (V8DI "v4di") (V4TI "v2ti") @@ -15939,11 +15942,11 @@ (set_attr "prefix" "orig,maybe_evex,orig,orig,maybe_evex") (set_attr "mode" "TI,TI,V4SF,V2SF,V2SF")]) -(define_insn "*vec_concatv4si_0" - [(set (match_operand:V4SI 0 "register_operand" "=v,x") - (vec_concat:V4SI - (match_operand:V2SI 1 "nonimmediate_operand" "vm,?!*y") - (match_operand:V2SI 2 "const0_operand" " C,C")))] +(define_insn "*vec_concat_0" + [(set (match_operand:VI124_128 0 "register_operand" "=v,x") + (vec_concat:VI124_128 + (match_operand: 1 "nonimmediate_operand" "vm,?!*y") + (match_operand: 2 "const0_operand" " C,C")))] "TARGET_SSE2" "@ %vmovq\t{%1, %0|%0, %1} @@ -22158,6 +22161,24 @@ (set_attr "prefix" "maybe_evex") (set_attr "mode" "")]) +(define_insn_and_split "*vec_concat_0_1" + [(set (match_operand:V 0 "register_operand") + (vec_select:V + (vec_concat: + (match_operand:V 1 "nonimmediate_operand") + (match_operand:V 2 "const0_operand")) + (match_parallel 3 "movq_parallel" + [(match_operand 4 "const_int_operand")])))] + "ix86_pre_reload_split ()" + "#" + "&& 1" + [(set (match_dup 0) + (vec_concat:V (match_dup 1) (match_dup 5)))] +{ + operands[1] = gen_lowpart (mode, operands[1]); + operands[5] = CONST0_RTX (mode); +}) + (define_insn "vcvtph2ps" [(set (match_operand:V4SF 0 "register_operand" "=v") (vec_select:V4SF diff --git a/gcc/testsuite/gcc.target/i386/avx-pr94680.c b/gcc/testsuite/gcc.target/i386/avx-pr94680.c new file mode 100644 index 0000000..a89e496 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-pr94680.c @@ -0,0 +1,107 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx -mno-avx512f -O2" } */ +/* { dg-final { scan-assembler-times {(?n)vmov[a-z0-9]*[ \t]*%xmm[0-9]} 12 } } */ +/* { dg-final { scan-assembler-not "pxor" } } */ + +typedef float v8sf __attribute__((vector_size(32))); +typedef double v4df __attribute__ ((vector_size (32))); +typedef long long v4di __attribute__((vector_size(32))); +typedef int v8si __attribute__((vector_size(32))); +typedef short v16hi __attribute__ ((vector_size (32))); +typedef char v32qi __attribute__ ((vector_size (32))); + +v4df +foo_v4df (v4df x) +{ + return __builtin_shuffle (x, (v4df) { 0, 0, 0, 0 }, (v4di) { 0, 1, 4, 5 }); +} + +v4df +foo_v4df_l (v4df x) +{ + return __builtin_shuffle ((v4df) { 0, 0, 0, 0 }, x, (v4di) { 4, 5, 1, 2 }); +} + +v4di +foo_v4di (v4di x) +{ + return __builtin_shuffle (x, (v4di) { 0, 0, 0, 0 }, (v4di) { 0, 1, 4, 7 }); +} + +v4di +foo_v4di_l (v4di x) +{ + return __builtin_shuffle ((v4di) { 0, 0, 0, 0 }, x, (v4di) { 4, 5, 3, 1 }); +} + +v8sf +foo_v8sf (v8sf x) +{ + return __builtin_shuffle ((v8sf) { 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v8si) { 8, 9, 10, 11, 0, 1, 2, 3 }); +} + +v8sf +foo_v8sf_l (v8sf x) +{ + return __builtin_shuffle (x, (v8sf) { 0, 0, 0, 0, 0, 0, 0, 0 }, + (v8si) { 0, 1, 2, 3, 8, 9, 10, 11 }); +} + +v8si +foo_v8si (v8si x) +{ + return __builtin_shuffle (x, (v8si) { 0, 0, 0, 0, 0, 0, 0, 0 }, + (v8si) { 0, 1, 2, 3, 13, 12, 11, 15 }); +} + +v8si +foo_v8si_l (v8si x) +{ + return __builtin_shuffle ((v8si) { 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v8si) { 8, 9, 10, 11, 7, 6, 5, 4 }); +} + +v16hi +foo_v16hi (v16hi x) +{ + return __builtin_shuffle (x, (v16hi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + (v16hi) { 0, 1, 2, 3, 4, 5, 6, 7, + 24, 17, 26, 19, 28, 21, 30, 23 }); +} + +v16hi +foo_v16hi_l (v16hi x) +{ + return __builtin_shuffle ((v16hi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v16hi) { 16, 17, 18, 20, 21, 22, 23, + 15, 0, 13, 2, 11, 4, 9, 6 }); +} + +v32qi +foo_v32qi (v32qi x) +{ + return __builtin_shuffle (x, (v32qi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + (v32qi) { 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 32, 49, 34, 58, 36, 53, 38, 39, + 40, 60, 42, 43, 63, 45, 46, 47 }); +} + +v32qi +foo_v32qi_l (v32qi x) +{ + return __builtin_shuffle ((v32qi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v32qi) { 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 31, 0, 29, 2, 27, 4, 25, 6, + 23, 8, 21, 10, 19, 12, 17, 14 }); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr94680.c b/gcc/testsuite/gcc.target/i386/avx512f-pr94680.c new file mode 100644 index 0000000..c27431a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-pr94680.c @@ -0,0 +1,144 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512bw -mavx512vbmi -O2" } */ +/* { dg-final { scan-assembler-times {(?n)vmov[a-z0-9]*[ \t]*%ymm[0-9]} 12} } */ +/* { dg-final { scan-assembler-not "pxor" } } */ + + +typedef float v16sf __attribute__((vector_size(64))); +typedef double v8df __attribute__ ((vector_size (64))); +typedef long long v8di __attribute__((vector_size(64))); +typedef int v16si __attribute__((vector_size(64))); +typedef short v32hi __attribute__ ((vector_size (64))); +typedef char v64qi __attribute__ ((vector_size (64))); + +v8df +foo_v8df (v8df x) +{ + return __builtin_shuffle (x, (v8df) { 0, 0, 0, 0, 0, 0, 0, 0 }, + (v8di) { 0, 1, 2, 3, 15, 14, 10, 11 }); +} + +v8df +foo_v8df_l (v8df x) +{ + return __builtin_shuffle ((v8df) { 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v8di) { 8, 9, 10, 11, 0, 1, 2, 3 }); +} + +v8di +foo_v8di (v8di x) +{ + return __builtin_shuffle (x, (v8di) { 0, 0, 0, 0, 0, 0, 0, 0 }, + (v8di) { 0, 1, 2, 3, 8, 9, 10, 11 }); +} + +v8di +foo_v8di_l (v8di x) +{ + return __builtin_shuffle ((v8di) { 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v8di) { 8, 9, 10, 11, 7, 6, 5, 4 }); +} + +v16sf +foo_v16sf (v16sf x) +{ + return __builtin_shuffle (x, (v16sf) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + (v16si) { 0, 1, 2, 3, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23 }); +} + +v16sf +foo_v16sf_l (v16sf x) +{ + return __builtin_shuffle ((v16sf) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v16si) { 16, 17, 18, 19, 20, 21, 22, 23, + 0, 15, 2, 13, 4, 11, 6, 9 }); +} + +v16si +foo_v16si (v16si x) +{ + return __builtin_shuffle (x, (v16si) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + (v16si) { 0, 1, 2, 3, 4, 5, 6, 7, + 31, 30, 29, 28, 20, 21, 22, 23 }); +} + +v16si +foo_v16si_l (v16si x) +{ + return __builtin_shuffle ((v16si) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v16si) { 16, 17, 18, 19, 20, 21, 22, 23, + 15, 0, 13, 2, 11, 4, 9, 6 }); +} + +v32hi +foo_v32hi (v32hi x) +{ + return __builtin_shuffle (x, (v32hi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + (v32hi) { 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 63, 33, 61, 35, 59, 37, 57, 39, + 55, 41, 53, 43, 51, 45, 49, 47 }); +} + +v32hi +foo_v32hi_l (v32hi x) +{ + return __builtin_shuffle ((v32hi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v32hi) { 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 31, 0, 29, 2, 27, 4, 25, 6, + 23, 8, 21, 10, 19, 12, 17, 14 }); +} + +v64qi +foo_v64qi (v64qi x) +{ + return __builtin_shuffle (x, (v64qi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + (v64qi) {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 64, 127, 66, 125, 68, 123, 70, 121, + 72, 119, 74, 117, 76, 115, 78, 113, + 80, 111, 82, 109, 84, 107, 86, 105, + 88, 103, 90, 101, 92, 99, 94, 97 }); +} + +v64qi +foo_v64qi_l (v64qi x) +{ + return __builtin_shuffle ((v64qi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v64qi) { 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 0, 63, 2, 61, 4, 59, 6, 57, + 8, 55, 10, 53, 12, 51, 14, 49, + 16, 47, 18, 45, 20, 43, 22, 41, + 24, 39, 26, 37, 28, 35, 30, 33 }); +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-pr94680.c b/gcc/testsuite/gcc.target/i386/sse2-pr94680.c new file mode 100644 index 0000000..7e0ff9f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-pr94680.c @@ -0,0 +1,91 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -mno-sse4.1 -O2" } */ +/* { dg-final { scan-assembler-times {(?n)(?:mov|psrldq).*%xmm[0-9]} 12 } } */ +/* { dg-final { scan-assembler-not "pxor" } } */ + +typedef float v4sf __attribute__((vector_size(16))); +typedef double v2df __attribute__ ((vector_size (16))); +typedef long long v2di __attribute__((vector_size(16))); +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__ ((vector_size (16))); +typedef char v16qi __attribute__ ((vector_size (16))); + +v2df +foo_v2df (v2df x) +{ + return __builtin_shuffle (x, (v2df) { 0, 0 }, (v2di) {0, 2}); +} + +v2df +foo_v2df_l (v2df x) +{ + return __builtin_shuffle ((v2df) { 0, 0 }, x, (v2di) {3, 1}); +} + +v2di +foo_v2di (v2di x) +{ + return __builtin_shuffle (x, (v2di) { 0, 0 }, (v2di) {0, 3}); +} + +v2di +foo_v2di_l (v2di x) +{ + return __builtin_shuffle ((v2di) { 0, 0 }, x, (v2di) {3, 0}); +} + +v4sf +foo_v4sf (v4sf x) +{ + return __builtin_shuffle (x, (v4sf) { 0, 0, 0, 0 }, (v4si) {0, 1, 4, 5}); +} + +v4sf +foo_v4sf_l (v4sf x) +{ + return __builtin_shuffle ((v4sf) { 0, 0, 0, 0 }, x, (v4si) {4, 5, 3, 1}); +} + +v4si +foo_v4si (v4si x) +{ + return __builtin_shuffle (x, (v4si) { 0, 0, 0, 0 }, (v4si) {0, 1, 6, 7}); +} + +v4si +foo_v4si_l (v4si x) +{ + return __builtin_shuffle ((v4si) { 0, 0, 0, 0 }, x, (v4si) {4, 5, 1, 2}); +} + +v8hi +foo_v8hi (v8hi x) +{ + return __builtin_shuffle (x, (v8hi) { 0, 0, 0, 0, 0, 0, 0, 0 }, + (v8hi) { 0, 1, 2, 3, 8, 12, 10, 13 }); +} + +v8hi +foo_v8hi_l (v8hi x) +{ + return __builtin_shuffle ((v8hi) { 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v8hi) { 8, 9, 10, 11, 7, 6, 5, 4 }); +} + +v16qi +foo_v16qi (v16qi x) +{ + return __builtin_shuffle (x, (v16qi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + (v16qi) {0, 1, 2, 3, 4, 5, 6, 7, + 16, 24, 18, 26, 20, 28, 22, 30 }); +} + +v16qi +foo_v16qi_l (v16qi x) +{ + return __builtin_shuffle ((v16qi) { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, x, + (v16qi) { 16, 17, 18, 19, 20, 21, 22, 23, + 15, 0, 13, 2, 11, 4, 9, 6 }); +} -- cgit v1.1 From 0ffdbc85d9a626fab175823421d53bc0e9564252 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Thu, 13 May 2021 13:44:13 +0800 Subject: Fix typo in testcase. gcc/testsuite/ChangeLog: * gcc.target/i386/avx-pr94680.c: Fix typo in testcase. --- gcc/testsuite/gcc.target/i386/avx-pr94680.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/i386/avx-pr94680.c b/gcc/testsuite/gcc.target/i386/avx-pr94680.c index a89e496..cb5041b 100644 --- a/gcc/testsuite/gcc.target/i386/avx-pr94680.c +++ b/gcc/testsuite/gcc.target/i386/avx-pr94680.c @@ -76,7 +76,7 @@ foo_v16hi_l (v16hi x) { return __builtin_shuffle ((v16hi) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, x, - (v16hi) { 16, 17, 18, 20, 21, 22, 23, + (v16hi) { 16, 17, 18, 19, 20, 21, 22, 23, 15, 0, 13, 2, 11, 4, 9, 6 }); } -- cgit v1.1 From 810afb0b5fbb9da1e0e51ee9607f275f14c17459 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 13 May 2021 09:23:30 +0200 Subject: testsuite: prune new LTO warning libgomp/ChangeLog: PR testsuite/100569 * testsuite/libgomp.c/omp-nested-3.c: Prune new LTO warning. * testsuite/libgomp.c/pr46032-2.c: Likewise. * testsuite/libgomp.oacc-c-c++-common/data-clauses-kernels-ipa-pta.c: Likewise. * testsuite/libgomp.oacc-c-c++-common/data-clauses-parallel-ipa-pta.c: Likewise. gcc/testsuite/ChangeLog: PR testsuite/100569 * gcc.dg/atomic/c11-atomic-exec-2.c: Prune new LTO warning. * gcc.dg/torture/pr94947-1.c: Likewise. --- gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c | 1 + gcc/testsuite/gcc.dg/torture/pr94947-1.c | 1 + 2 files changed, 2 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c index 9ee56b6..3e75096 100644 --- a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c +++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c @@ -2,6 +2,7 @@ assignment. */ /* { dg-do run } */ /* { dg-options "-std=c11 -pedantic-errors" } */ +/* { dg-prune-output "warning: using serial compilation" } */ extern void abort (void); extern void exit (int); diff --git a/gcc/testsuite/gcc.dg/torture/pr94947-1.c b/gcc/testsuite/gcc.dg/torture/pr94947-1.c index ab8b488..832e40d 100644 --- a/gcc/testsuite/gcc.dg/torture/pr94947-1.c +++ b/gcc/testsuite/gcc.dg/torture/pr94947-1.c @@ -1,6 +1,7 @@ /* { dg-do run } */ /* { dg-additional-sources "pr94947-2.c" } */ /* { dg-additional-options "-fipa-pta -flto-partition=1to1" } */ +/* { dg-prune-output "warning: using serial compilation" } */ extern void abort (); extern void baz (); -- cgit v1.1 From c3e02c2e442e6b0c298dbe769e0e3b120b5201b2 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 13 May 2021 09:32:50 +0200 Subject: Prune another new LTO warning gcc/testsuite/ PR testsuite/100569 * gnat.dg/lto21.adb: Prune new LTO warning. --- gcc/testsuite/gnat.dg/lto21.adb | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/gnat.dg/lto21.adb b/gcc/testsuite/gnat.dg/lto21.adb index fe6fb273..f626697 100644 --- a/gcc/testsuite/gnat.dg/lto21.adb +++ b/gcc/testsuite/gnat.dg/lto21.adb @@ -1,5 +1,6 @@ -- { dg-do run } -- { dg-options "-O3 -flto" { target lto } } +-- { dg-prune-output "warning: using serial compilation" } with Lto21_Pkg1; with Lto21_Pkg2; use Lto21_Pkg2; -- cgit v1.1 From 23eb66d1d46a34cb28c4acbdf8a1deb80a7c5a05 Mon Sep 17 00:00:00 2001 From: marxin Date: Wed, 18 Nov 2020 16:13:23 +0100 Subject: gcov: Use system IO buffering gcc/ChangeLog: * gcov-io.c (gcov_write_block): Remove. (gcov_write_words): Likewise. (gcov_read_words): Re-implement using gcov_read_bytes. (gcov_allocate): Remove. (GCOV_BLOCK_SIZE): Likewise. (struct gcov_var): Remove most of the fields. (gcov_position): Implement with ftell. (gcov_rewrite): Remove setting of start and offset fields. (from_file): Re-format. (gcov_open): Remove setbuf call. It should not be needed. (gcov_close): Remove internal buffer handling. (gcov_magic): Use __builtin_bswap32. (gcov_write_counter): Use directly gcov_write_unsigned. (gcov_write_string): Use direct fwrite and do not round to 4 bytes. (gcov_seek): Use directly fseek. (gcov_write_tag): Use gcov_write_unsigned directly. (gcov_write_length): Likewise. (gcov_write_tag_length): Likewise. (gcov_read_bytes): Use directly fread. (gcov_read_unsigned): Use gcov_read_words. (gcov_read_counter): Likewise. (gcov_read_string): Use gcov_read_bytes. * gcov-io.h (GCOV_WORD_SIZE): Adjust to reflect that size is not in bytes, but words (4B). (GCOV_TAG_FUNCTION_LENGTH): Likewise. (GCOV_TAG_ARCS_LENGTH): Likewise. (GCOV_TAG_ARCS_NUM): Likewise. (GCOV_TAG_COUNTER_LENGTH): Likewise. (GCOV_TAG_COUNTER_NUM): Likewise. (GCOV_TAG_SUMMARY_LENGTH): Likewise. libgcc/ChangeLog: * libgcov-driver.c: Fix GNU coding style. --- gcc/gcov-io.c | 282 +++++++++++++--------------------------------------------- gcc/gcov-io.h | 17 ++-- 2 files changed, 74 insertions(+), 225 deletions(-) (limited to 'gcc') diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c index 21ca394..4b1e11d 100644 --- a/gcc/gcov-io.c +++ b/gcc/gcov-io.c @@ -27,40 +27,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* Routines declared in gcov-io.h. This file should be #included by another source file, after having #included gcov-io.h. */ -#if !IN_GCOV -static void gcov_write_block (unsigned); -static gcov_unsigned_t *gcov_write_words (unsigned); -#endif -static const gcov_unsigned_t *gcov_read_words (unsigned); -#if !IN_LIBGCOV -static void gcov_allocate (unsigned); -#endif - -/* Optimum number of gcov_unsigned_t's read from or written to disk. */ -#define GCOV_BLOCK_SIZE (1 << 10) +static gcov_unsigned_t *gcov_read_words (void *buffer, unsigned); struct gcov_var { FILE *file; - gcov_position_t start; /* Position of first byte of block */ - unsigned offset; /* Read/write position within the block. */ - unsigned length; /* Read limit in the block. */ - unsigned overread; /* Number of words overread. */ int error; /* < 0 overflow, > 0 disk error. */ - int mode; /* < 0 writing, > 0 reading */ + int mode; /* < 0 writing, > 0 reading. */ int endian; /* Swap endianness. */ -#if IN_LIBGCOV - /* Holds one block plus 4 bytes, thus all coverage reads & writes - fit within this buffer and we always can transfer GCOV_BLOCK_SIZE - to and from the disk. libgcov never backtracks and only writes 4 - or 8 byte objects. */ - gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; -#else - /* Holds a variable length block, as the compiler can write - strings and needs to backtrack. */ - size_t alloc; - gcov_unsigned_t *buffer; -#endif } gcov_var; /* Save the current position in the gcov file. */ @@ -71,8 +45,7 @@ static inline gcov_position_t gcov_position (void) { - gcov_nonruntime_assert (gcov_var.mode > 0); - return gcov_var.start + gcov_var.offset; + return ftell (gcov_var.file); } /* Return nonzero if the error flag is set. */ @@ -92,20 +65,16 @@ GCOV_LINKAGE inline void gcov_rewrite (void) { gcov_var.mode = -1; - gcov_var.start = 0; - gcov_var.offset = 0; fseek (gcov_var.file, 0L, SEEK_SET); } #endif -static inline gcov_unsigned_t from_file (gcov_unsigned_t value) +static inline gcov_unsigned_t +from_file (gcov_unsigned_t value) { #if !IN_LIBGCOV || defined (IN_GCOV_TOOL) if (gcov_var.endian) - { - value = (value >> 16) | (value << 16); - value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); - } + return __builtin_bswap32 (value); #endif return value; } @@ -142,9 +111,6 @@ gcov_open (const char *name, int mode) #endif gcov_nonruntime_assert (!gcov_var.file); - gcov_var.start = 0; - gcov_var.offset = gcov_var.length = 0; - gcov_var.overread = -1u; gcov_var.error = 0; #if !IN_LIBGCOV || defined (IN_GCOV_TOOL) gcov_var.endian = 0; @@ -222,8 +188,6 @@ gcov_open (const char *name, int mode) gcov_var.mode = mode ? mode : 1; - setbuf (gcov_var.file, (char *)0); - return 1; } @@ -235,19 +199,9 @@ gcov_close (void) { if (gcov_var.file) { -#if !IN_GCOV - if (gcov_var.offset && gcov_var.mode < 0) - gcov_write_block (gcov_var.offset); -#endif fclose (gcov_var.file); gcov_var.file = 0; - gcov_var.length = 0; } -#if !IN_LIBGCOV - free (gcov_var.buffer); - gcov_var.alloc = 0; - gcov_var.buffer = 0; -#endif gcov_var.mode = 0; return gcov_var.error; } @@ -262,9 +216,8 @@ gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) { if (magic == expected) return 1; - magic = (magic >> 16) | (magic << 16); - magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); - if (magic == expected) + + if (__builtin_bswap32 (magic) == expected) { gcov_var.endian = 1; return -1; @@ -273,71 +226,15 @@ gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) } #endif -#if !IN_LIBGCOV -static void -gcov_allocate (unsigned length) -{ - size_t new_size = gcov_var.alloc; - - if (!new_size) - new_size = GCOV_BLOCK_SIZE; - new_size += length; - new_size *= 2; - - gcov_var.alloc = new_size; - gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); -} -#endif - #if !IN_GCOV -/* Write out the current block, if needs be. */ - -static void -gcov_write_block (unsigned size) -{ - if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) - gcov_var.error = 1; - gcov_var.start += size; - gcov_var.offset -= size; -} - -/* Allocate space to write BYTES bytes to the gcov file. Return a - pointer to those bytes, or NULL on failure. */ - -static gcov_unsigned_t * -gcov_write_words (unsigned words) -{ - gcov_unsigned_t *result; - - gcov_nonruntime_assert (gcov_var.mode < 0); -#if IN_LIBGCOV - if (gcov_var.offset >= GCOV_BLOCK_SIZE) - { - gcov_write_block (GCOV_BLOCK_SIZE); - if (gcov_var.offset) - { - memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); - } - } -#else - if (gcov_var.offset + words > gcov_var.alloc) - gcov_allocate (gcov_var.offset + words); -#endif - result = &gcov_var.buffer[gcov_var.offset]; - gcov_var.offset += words; - - return result; -} - -/* Write unsigned VALUE to coverage file. Sets error flag - appropriately. */ +/* Write unsigned VALUE to coverage file. */ GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t value) { - gcov_unsigned_t *buffer = gcov_write_words (1); - - buffer[0] = value; + gcov_unsigned_t r = fwrite (&value, sizeof (value), 1, gcov_var.file); + if (r != 1) + gcov_var.error = 1; } /* Write counter VALUE to coverage file. Sets error flag @@ -347,13 +244,11 @@ gcov_write_unsigned (gcov_unsigned_t value) GCOV_LINKAGE void gcov_write_counter (gcov_type value) { - gcov_unsigned_t *buffer = gcov_write_words (2); - - buffer[0] = (gcov_unsigned_t) value; + gcov_write_unsigned ((gcov_unsigned_t) value); if (sizeof (value) > sizeof (gcov_unsigned_t)) - buffer[1] = (gcov_unsigned_t) (value >> 32); + gcov_write_unsigned ((gcov_unsigned_t) (value >> 32)); else - buffer[1] = 0; + gcov_write_unsigned (0); } #endif /* IN_LIBGCOV */ @@ -365,23 +260,16 @@ GCOV_LINKAGE void gcov_write_string (const char *string) { unsigned length = 0; - unsigned alloc = 0; - gcov_unsigned_t *buffer; if (string) - { - length = strlen (string); - alloc = (length + 4) >> 2; - } - - buffer = gcov_write_words (1 + alloc); + length = strlen (string) + 1; - buffer[0] = alloc; - - if (alloc > 0) + gcov_write_unsigned (length); + if (length > 0) { - buffer[alloc] = 0; /* place nul terminators. */ - memcpy (&buffer[1], string, length); + gcov_unsigned_t r = fwrite (string, length, 1, gcov_var.file); + if (r != 1) + gcov_var.error = 1; } } #endif @@ -418,6 +306,14 @@ gcov_write_filename (const char *filename) } #endif +/* Move to a given position in a gcov file. */ + +GCOV_LINKAGE void +gcov_seek (gcov_position_t base) +{ + fseek (gcov_var.file, base, SEEK_SET); +} + #if !IN_LIBGCOV /* Write a tag TAG and reserve space for the record length. Return a value to be used for gcov_write_length. */ @@ -425,11 +321,9 @@ gcov_write_filename (const char *filename) GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t tag) { - gcov_position_t result = gcov_var.start + gcov_var.offset; - gcov_unsigned_t *buffer = gcov_write_words (2); - - buffer[0] = tag; - buffer[1] = 0; + gcov_position_t result = gcov_position (); + gcov_write_unsigned (tag); + gcov_write_unsigned (0); return result; } @@ -442,19 +336,13 @@ gcov_write_tag (gcov_unsigned_t tag) GCOV_LINKAGE void gcov_write_length (gcov_position_t position) { - unsigned offset; - gcov_unsigned_t length; - gcov_unsigned_t *buffer; - + gcov_position_t current_position = gcov_position (); gcov_nonruntime_assert (gcov_var.mode < 0); - gcov_nonruntime_assert (position + 2 <= gcov_var.start + gcov_var.offset); - gcov_nonruntime_assert (position >= gcov_var.start); - offset = position - gcov_var.start; - length = gcov_var.offset - offset - 2; - buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; - buffer[1] = length; - if (gcov_var.offset >= GCOV_BLOCK_SIZE) - gcov_write_block (gcov_var.offset); + gcov_nonruntime_assert (current_position >= position + 2 * GCOV_WORD_SIZE); + + gcov_seek (position + GCOV_WORD_SIZE); + gcov_write_unsigned (current_position - position - 2 * GCOV_WORD_SIZE); + gcov_seek (current_position); } #else /* IN_LIBGCOV */ @@ -464,10 +352,8 @@ gcov_write_length (gcov_position_t position) GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) { - gcov_unsigned_t *buffer = gcov_write_words (2); - - buffer[0] = tag; - buffer[1] = length; + gcov_write_unsigned (tag); + gcov_write_unsigned (length); } /* Write a summary structure to the gcov file. Return nonzero on @@ -485,52 +371,28 @@ gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) #endif /*!IN_GCOV */ -/* Return a pointer to read BYTES bytes from the gcov file. Returns +/* Return a pointer to read COUNT bytes from the gcov file. Returns NULL on failure (read past EOF). */ -static const gcov_unsigned_t * -gcov_read_words (unsigned words) +static void * +gcov_read_bytes (void *buffer, unsigned count) { - const gcov_unsigned_t *result; - unsigned excess = gcov_var.length - gcov_var.offset; - if (gcov_var.mode <= 0) return NULL; - if (excess < words) - { - gcov_var.start += gcov_var.offset; - if (excess) - { -#if IN_LIBGCOV - memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); -#else - memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, - excess * 4); -#endif - } - gcov_var.offset = 0; - gcov_var.length = excess; -#if IN_LIBGCOV - excess = GCOV_BLOCK_SIZE; -#else - if (gcov_var.length + words > gcov_var.alloc) - gcov_allocate (gcov_var.length + words); - excess = gcov_var.alloc - gcov_var.length; -#endif - excess = fread (gcov_var.buffer + gcov_var.length, - 1, excess << 2, gcov_var.file) >> 2; - gcov_var.length += excess; - if (gcov_var.length < words) - { - gcov_var.overread += words - gcov_var.length; - gcov_var.length = 0; - return 0; - } - } - result = &gcov_var.buffer[gcov_var.offset]; - gcov_var.offset += words; - return result; + unsigned read = fread (buffer, count, 1, gcov_var.file); + if (read != 1) + return NULL; + + return buffer; +} + +/* Read WORDS gcov_unsigned_t values from gcov file. */ + +static gcov_unsigned_t * +gcov_read_words (void *buffer, unsigned words) +{ + return (gcov_unsigned_t *)gcov_read_bytes (buffer, GCOV_WORD_SIZE * words); } /* Read unsigned value from a coverage file. Sets error flag on file @@ -540,10 +402,12 @@ GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) { gcov_unsigned_t value; - const gcov_unsigned_t *buffer = gcov_read_words (1); + gcov_unsigned_t allocated_buffer[1]; + gcov_unsigned_t *buffer = gcov_read_words (&allocated_buffer, 1); if (!buffer) return 0; + value = from_file (buffer[0]); return value; } @@ -555,7 +419,8 @@ GCOV_LINKAGE gcov_type gcov_read_counter (void) { gcov_type value; - const gcov_unsigned_t *buffer = gcov_read_words (2); + gcov_unsigned_t allocated_buffer[2]; + gcov_unsigned_t *buffer = gcov_read_words (&allocated_buffer, 2); if (!buffer) return 0; @@ -632,7 +497,8 @@ gcov_read_string (void) if (!length) return 0; - return (const char *) gcov_read_words (length); + void *buffer = XNEWVEC (char *, length); + return (const char *) gcov_read_bytes (buffer, length); } #endif @@ -654,27 +520,7 @@ gcov_sync (gcov_position_t base, gcov_unsigned_t length) { gcov_nonruntime_assert (gcov_var.mode > 0); base += length; - if (base - gcov_var.start <= gcov_var.length) - gcov_var.offset = base - gcov_var.start; - else - { - gcov_var.offset = gcov_var.length = 0; - fseek (gcov_var.file, base << 2, SEEK_SET); - gcov_var.start = ftell (gcov_var.file) >> 2; - } -} -#endif - -#if IN_LIBGCOV -/* Move to a given position in a gcov file. */ - -GCOV_LINKAGE void -gcov_seek (gcov_position_t base) -{ - if (gcov_var.offset) - gcov_write_block (gcov_var.offset); - fseek (gcov_var.file, base << 2, SEEK_SET); - gcov_var.start = ftell (gcov_var.file) >> 2; + fseek (gcov_var.file, base, SEEK_SET); } #endif diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index c536554..f7584eb 100644 --- a/gcc/gcov-io.h +++ b/gcc/gcov-io.h @@ -243,22 +243,25 @@ typedef uint64_t gcov_type_unsigned; /* The record tags. Values [1..3f] are for tags which may be in either file. Values [41..9f] for those in the note file and [a1..ff] for the data file. The tag value zero is used as an explicit end of - file marker -- it is not required to be present. */ + file marker -- it is not required to be present. + All length values are in bytes. */ + +#define GCOV_WORD_SIZE 4 #define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000) -#define GCOV_TAG_FUNCTION_LENGTH (3) +#define GCOV_TAG_FUNCTION_LENGTH (3 * GCOV_WORD_SIZE) #define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000) #define GCOV_TAG_BLOCKS_LENGTH(NUM) (NUM) #define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000) -#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2) -#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH) - 1) / 2) +#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2 * GCOV_WORD_SIZE) +#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH / GCOV_WORD_SIZE) - 1) / 2) #define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000) #define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) -#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) -#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) +#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2 * GCOV_WORD_SIZE) +#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH / GCOV_WORD_SIZE) / 2) #define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) #define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) /* Obsolete */ -#define GCOV_TAG_SUMMARY_LENGTH (2) +#define GCOV_TAG_SUMMARY_LENGTH (2 * GCOV_WORD_SIZE) #define GCOV_TAG_AFDO_FILE_NAMES ((gcov_unsigned_t)0xaa000000) #define GCOV_TAG_AFDO_FUNCTION ((gcov_unsigned_t)0xac000000) #define GCOV_TAG_AFDO_WORKING_SET ((gcov_unsigned_t)0xaf000000) -- cgit v1.1 From f1693741cb2b2db519bb82155a3c0880fd820ea3 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 13 May 2021 11:09:53 +0200 Subject: i386: Fix up V2SFmode vcond* with -mxop [PR100581] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ix86_expand_sse_movcc has special TARGET_XOP handling and the recent addition of support of v*cond* patterns for V2SFmode results in ICEs because the expected pattern doesn't exist. We can handle it using 128-bit vpcmov (if we ignore the upper 64 bits like we ignore in other TARGET_MMX_WITH_SSE support). 2021-05-13 Uroš Bizjak gcc/ PR target/100581 * config/i386/i386-expand.c (ix86_expand_sse_movcc): Force mode sizes < 16 to a register when constructing vpcmov pattern. * config/i386/mmx.md (*xop_pcmov_): Use MMXMODE124 mode. gcc/testsuite/ PR target/100581 * g++.target/i386/pr100581.C: New test. --- gcc/config/i386/i386-expand.c | 3 ++- gcc/config/i386/mmx.md | 10 +++++----- gcc/testsuite/g++.target/i386/pr100581.C | 9 +++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.target/i386/pr100581.C (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index dd23008..92488b8 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -3661,7 +3661,8 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false) { op_true = force_reg (mode, op_true); - if (!nonimmediate_operand (op_false, mode)) + if (GET_MODE_SIZE (mode) < 16 + || !nonimmediate_operand (op_false, mode)) op_false = force_reg (mode, op_false); emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cmp, diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index d433c52..7fc2e5d 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -1816,11 +1816,11 @@ ;; XOP parallel XMM conditional moves (define_insn "*xop_pcmov_" - [(set (match_operand:MMXMODEI 0 "register_operand" "=x") - (if_then_else:MMXMODEI - (match_operand:MMXMODEI 3 "register_operand" "x") - (match_operand:MMXMODEI 1 "register_operand" "x") - (match_operand:MMXMODEI 2 "register_operand" "x")))] + [(set (match_operand:MMXMODE124 0 "register_operand" "=x") + (if_then_else:MMXMODE124 + (match_operand:MMXMODE124 3 "register_operand" "x") + (match_operand:MMXMODE124 1 "register_operand" "x") + (match_operand:MMXMODE124 2 "register_operand" "x")))] "TARGET_XOP && TARGET_MMX_WITH_SSE" "vpcmov\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "sse4arg")]) diff --git a/gcc/testsuite/g++.target/i386/pr100581.C b/gcc/testsuite/g++.target/i386/pr100581.C new file mode 100644 index 0000000..37cc9f1 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr100581.C @@ -0,0 +1,9 @@ +/* PR target/100581 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mxop" } */ + +typedef float __attribute__((__vector_size__(8))) v64f32; + +v64f32 af, bf, ff_a, ff_b; + +v64f32 f() { return ff_a > ff_b ? af : bf; } -- cgit v1.1 From 829c4bea06600ea4201462f91ce6d76ca21fdb35 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 13 May 2021 12:14:14 +0200 Subject: ix86: Support V{2, 4}DImode arithmetic right shifts for SSE2+ [PR98856] As mentioned in the PR, we don't support arithmetic right V2DImode or V4DImode on x86 without -mavx512vl or -mxop. The ISAs indeed don't have {,v}psraq instructions until AVX512VL, but we actually can emulate it quite easily. One case is arithmetic >> 63, we can just emit {,v}pxor; {,v}pcmpgt for that for SSE4.2+, or for SSE2 psrad $31; pshufd $0xf5. Then arithmetic >> by constant > 32, that can be done with {,v}psrad $31 and {,v}psrad $(cst-32) and two operand permutation, arithmetic >> 32 can be done as {,v}psrad $31 and permutation of that and the original operand. Arithmetic >> by constant < 32 can be done as {,v}psrad $cst and {,v}psrlq $cst and two operand permutation. And arithmetic >> by variable scalar amount can be done as arithmetic >> 63, logical >> by the amount, << by (64 - amount of the >> 63 result; note that the vector << 64 result in 0) and oring together. I had to improve the permutation generation so that it actually handles the needed permutations (or handles them better). 2021-05-13 Jakub Jelinek PR tree-optimization/98856 * config/i386/i386.c (ix86_shift_rotate_cost): Add CODE argument. Expect V2DI and V4DI arithmetic right shifts to be emulated. (ix86_rtx_costs, ix86_add_stmt_cost): Adjust ix86_shift_rotate_cost caller. * config/i386/i386-expand.c (expand_vec_perm_2perm_interleave, expand_vec_perm_2perm_pblendv): New functions. (ix86_expand_vec_perm_const_1): Use them. * config/i386/sse.md (ashr3): Rename to ... (ashr3): ... this. (ashr3): New define_expand with VI248_AVX512BW iterator. (ashrv4di3): New define_expand. (ashrv2di3): Change condition to TARGET_SSE2, handle !TARGET_XOP and !TARGET_AVX512VL expansion. * gcc.target/i386/sse2-psraq-1.c: New test. * gcc.target/i386/sse4_2-psraq-1.c: New test. * gcc.target/i386/avx-psraq-1.c: New test. * gcc.target/i386/avx2-psraq-1.c: New test. * gcc.target/i386/avx-pr82370.c: Adjust expected number of vpsrad instructions. * gcc.target/i386/avx2-pr82370.c: Likewise. * gcc.target/i386/avx512f-pr82370.c: Likewise. * gcc.target/i386/avx512bw-pr82370.c: Likewise. * gcc.dg/torture/vshuf-4.inc: Add two further permutations. * gcc.dg/torture/vshuf-8.inc: Likewise. --- gcc/config/i386/i386-expand.c | 248 +++++++++++++++++++++++ gcc/config/i386/i386.c | 29 ++- gcc/config/i386/sse.md | 246 +++++++++++++++++++++- gcc/testsuite/gcc.dg/torture/vshuf-4.inc | 4 +- gcc/testsuite/gcc.dg/torture/vshuf-8.inc | 4 +- gcc/testsuite/gcc.target/i386/avx-pr82370.c | 2 +- gcc/testsuite/gcc.target/i386/avx-psraq-1.c | 13 ++ gcc/testsuite/gcc.target/i386/avx2-pr82370.c | 4 +- gcc/testsuite/gcc.target/i386/avx2-psraq-1.c | 51 +++++ gcc/testsuite/gcc.target/i386/avx512bw-pr82370.c | 4 +- gcc/testsuite/gcc.target/i386/avx512f-pr82370.c | 4 +- gcc/testsuite/gcc.target/i386/sse2-psraq-1.c | 53 +++++ gcc/testsuite/gcc.target/i386/sse4_2-psraq-1.c | 13 ++ 13 files changed, 660 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/avx-psraq-1.c create mode 100644 gcc/testsuite/gcc.target/i386/avx2-psraq-1.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-psraq-1.c create mode 100644 gcc/testsuite/gcc.target/i386/sse4_2-psraq-1.c (limited to 'gcc') diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 92488b8..0fa8d45 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -18662,6 +18662,242 @@ expand_vec_perm_vperm2f128_vblend (struct expand_vec_perm_d *d) return true; } +/* A subroutine of ix86_expand_vec_perm_const_1. Try to implement + a two vector permutation using two single vector permutations and + {,v}{,p}unpckl{ps,pd,bw,wd,dq}. If two_insn, succeed only if one + of dfirst or dsecond is identity permutation. */ + +static bool +expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn) +{ + unsigned i, nelt = d->nelt, nelt2 = nelt / 2, lane = nelt; + struct expand_vec_perm_d dfirst, dsecond, dfinal; + bool ident1 = true, ident2 = true; + + if (d->one_operand_p) + return false; + + if (GET_MODE_SIZE (d->vmode) == 16) + { + if (!TARGET_SSE) + return false; + if (d->vmode != V4SFmode && d->vmode != V2DFmode && !TARGET_SSE2) + return false; + } + else if (GET_MODE_SIZE (d->vmode) == 32) + { + if (!TARGET_AVX) + return false; + if (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2) + return false; + lane = nelt2; + } + else + return false; + + for (i = 1; i < nelt; i++) + if ((d->perm[i] >= nelt) != ((d->perm[0] >= nelt) ^ (i & 1))) + return false; + + dfirst = *d; + dsecond = *d; + dfinal = *d; + dfirst.op1 = dfirst.op0; + dfirst.one_operand_p = true; + dsecond.op0 = dsecond.op1; + dsecond.one_operand_p = true; + + for (i = 0; i < nelt; i++) + if (d->perm[i] >= nelt) + { + dsecond.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i] - nelt; + if (d->perm[i] - nelt != i / 2 + (i >= lane ? lane / 2 : 0)) + ident2 = false; + dsecond.perm[i / 2 + (i >= lane ? lane : lane / 2)] + = d->perm[i] - nelt; + } + else + { + dfirst.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i]; + if (d->perm[i] != i / 2 + (i >= lane ? lane / 2 : 0)) + ident1 = false; + dfirst.perm[i / 2 + (i >= lane ? lane : lane / 2)] = d->perm[i]; + } + + if (two_insn && !ident1 && !ident2) + return false; + + if (!d->testing_p) + { + if (!ident1) + dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode); + if (!ident2) + dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode); + if (d->perm[0] >= nelt) + std::swap (dfinal.op0, dfinal.op1); + } + + bool ok; + rtx_insn *seq1 = NULL, *seq2 = NULL; + + if (!ident1) + { + start_sequence (); + ok = expand_vec_perm_1 (&dfirst); + seq1 = get_insns (); + end_sequence (); + + if (!ok) + return false; + } + + if (!ident2) + { + start_sequence (); + ok = expand_vec_perm_1 (&dsecond); + seq2 = get_insns (); + end_sequence (); + + if (!ok) + return false; + } + + if (d->testing_p) + return true; + + for (i = 0; i < nelt; i++) + { + dfinal.perm[i] = i / 2; + if (i >= lane) + dfinal.perm[i] += lane / 2; + if ((i & 1) != 0) + dfinal.perm[i] += nelt; + } + emit_insn (seq1); + emit_insn (seq2); + ok = expand_vselect_vconcat (dfinal.target, dfinal.op0, dfinal.op1, + dfinal.perm, dfinal.nelt, false); + gcc_assert (ok); + return true; +} + +/* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify + the permutation using two single vector permutations and the SSE4_1 pblendv + instruction. If two_insn, succeed only if one of dfirst or dsecond is + identity permutation. */ + +static bool +expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn) +{ + unsigned i, nelt = d->nelt; + struct expand_vec_perm_d dfirst, dsecond, dfinal; + machine_mode vmode = d->vmode; + bool ident1 = true, ident2 = true; + + /* Use the same checks as in expand_vec_perm_blend. */ + if (d->one_operand_p) + return false; + if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32) + ; + else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode)) + ; + else if (TARGET_SSE4_1 && GET_MODE_SIZE (vmode) == 16) + ; + else + return false; + + dfirst = *d; + dsecond = *d; + dfinal = *d; + dfirst.op1 = dfirst.op0; + dfirst.one_operand_p = true; + dsecond.op0 = dsecond.op1; + dsecond.one_operand_p = true; + + for (i = 0; i < nelt; ++i) + if (d->perm[i] >= nelt) + { + dfirst.perm[i] = 0xff; + dsecond.perm[i] = d->perm[i] - nelt; + if (d->perm[i] != i + nelt) + ident2 = false; + } + else + { + dsecond.perm[i] = 0xff; + dfirst.perm[i] = d->perm[i]; + if (d->perm[i] != i) + ident1 = false; + } + + if (two_insn && !ident1 && !ident2) + return false; + + /* For now. Ideally treat 0xff as a wildcard. */ + for (i = 0; i < nelt; ++i) + if (dfirst.perm[i] == 0xff) + { + if (GET_MODE_SIZE (vmode) == 32 + && dfirst.perm[i ^ (nelt / 2)] != 0xff) + dfirst.perm[i] = dfirst.perm[i ^ (nelt / 2)] ^ (nelt / 2); + else + dfirst.perm[i] = i; + } + else + { + if (GET_MODE_SIZE (vmode) == 32 + && dsecond.perm[i ^ (nelt / 2)] != 0xff) + dsecond.perm[i] = dsecond.perm[i ^ (nelt / 2)] ^ (nelt / 2); + else + dsecond.perm[i] = i; + } + + if (!d->testing_p) + { + if (!ident1) + dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode); + if (!ident2) + dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode); + } + + bool ok; + rtx_insn *seq1 = NULL, *seq2 = NULL; + + if (!ident1) + { + start_sequence (); + ok = expand_vec_perm_1 (&dfirst); + seq1 = get_insns (); + end_sequence (); + + if (!ok) + return false; + } + + if (!ident2) + { + start_sequence (); + ok = expand_vec_perm_1 (&dsecond); + seq2 = get_insns (); + end_sequence (); + + if (!ok) + return false; + } + + if (d->testing_p) + return true; + + for (i = 0; i < nelt; ++i) + dfinal.perm[i] = (d->perm[i] >= nelt ? i + nelt : i); + + emit_insn (seq1); + emit_insn (seq2); + ok = expand_vec_perm_blend (&dfinal); + gcc_assert (ok); + return true; +} + /* A subroutine of ix86_expand_vec_perm_const_1. Implement a V4DF permutation using two vperm2f128, followed by a vshufpd insn blending the two vectors together. */ @@ -19773,6 +20009,12 @@ ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d) if (expand_vec_perm_pblendv (d)) return true; + if (expand_vec_perm_2perm_interleave (d, true)) + return true; + + if (expand_vec_perm_2perm_pblendv (d, true)) + return true; + /* Try sequences of three instructions. */ if (expand_vec_perm_even_odd_pack (d)) @@ -19790,6 +20032,12 @@ ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d) if (expand_vec_perm_vperm2f128_vblend (d)) return true; + if (expand_vec_perm_2perm_interleave (d, false)) + return true; + + if (expand_vec_perm_2perm_pblendv (d, false)) + return true; + /* Try sequences of four instructions. */ if (expand_vec_perm_even_odd_trunc (d)) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 915f89f..6a1f574 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -19732,6 +19732,7 @@ ix86_division_cost (const struct processor_costs *cost, static int ix86_shift_rotate_cost (const struct processor_costs *cost, + enum rtx_code code, enum machine_mode mode, bool constant_op1, HOST_WIDE_INT op1_val, bool speed, @@ -19770,6 +19771,19 @@ ix86_shift_rotate_cost (const struct processor_costs *cost, count = 7; return ix86_vec_cost (mode, cost->sse_op * count); } + /* V*DImode arithmetic right shift is emulated. */ + else if (code == ASHIFTRT + && (mode == V2DImode || mode == V4DImode) + && !TARGET_XOP + && !TARGET_AVX512VL) + { + int count = 4; + if (constant_op1 && op1_val == 63 && TARGET_SSE4_2) + count = 2; + else if (constant_op1) + count = 3; + return ix86_vec_cost (mode, cost->sse_op * count); + } else return ix86_vec_cost (mode, cost->sse_op); } @@ -19939,13 +19953,15 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, case LSHIFTRT: case ROTATERT: bool skip_op0, skip_op1; - *total = ix86_shift_rotate_cost (cost, mode, CONSTANT_P (XEXP (x, 1)), + *total = ix86_shift_rotate_cost (cost, code, mode, + CONSTANT_P (XEXP (x, 1)), CONST_INT_P (XEXP (x, 1)) ? INTVAL (XEXP (x, 1)) : -1, speed, GET_CODE (XEXP (x, 1)) == AND, SUBREG_P (XEXP (x, 1)) - && GET_CODE (XEXP (XEXP (x, 1), 0)) == AND, + && GET_CODE (XEXP (XEXP (x, 1), + 0)) == AND, &skip_op0, &skip_op1); if (skip_op0 || skip_op1) { @@ -22383,11 +22399,16 @@ ix86_add_stmt_cost (class vec_info *vinfo, void *data, int count, case LROTATE_EXPR: case RROTATE_EXPR: { + tree op1 = gimple_assign_rhs1 (stmt_info->stmt); tree op2 = gimple_assign_rhs2 (stmt_info->stmt); stmt_cost = ix86_shift_rotate_cost - (ix86_cost, mode, + (ix86_cost, + (subcode == RSHIFT_EXPR + && !TYPE_UNSIGNED (TREE_TYPE (op1))) + ? ASHIFTRT : LSHIFTRT, mode, TREE_CODE (op2) == INTEGER_CST, - cst_and_fits_in_hwi (op2) ? int_cst_value (op2) : -1, + cst_and_fits_in_hwi (op2) + ? int_cst_value (op2) : -1, true, false, false, NULL, NULL); } break; diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 4072d0c..62f4e15f 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -12468,7 +12468,7 @@ (set_attr "prefix" "orig,vex") (set_attr "mode" "")]) -(define_insn "ashr3" +(define_insn "ashr3" [(set (match_operand:VI248_AVX512BW_AVX512VL 0 "register_operand" "=v,v") (ashiftrt:VI248_AVX512BW_AVX512VL (match_operand:VI248_AVX512BW_AVX512VL 1 "nonimmediate_operand" "v,vm") @@ -12482,6 +12482,126 @@ (const_string "0"))) (set_attr "mode" "")]) +(define_expand "ashr3" + [(set (match_operand:VI248_AVX512BW 0 "register_operand") + (ashiftrt:VI248_AVX512BW + (match_operand:VI248_AVX512BW 1 "nonimmediate_operand") + (match_operand:DI 2 "nonmemory_operand")))] + "TARGET_AVX512F") + +(define_expand "ashrv4di3" + [(set (match_operand:V4DI 0 "register_operand") + (ashiftrt:V4DI + (match_operand:V4DI 1 "nonimmediate_operand") + (match_operand:DI 2 "nonmemory_operand")))] + "TARGET_AVX2" +{ + if (!TARGET_AVX512VL) + { + if (CONST_INT_P (operands[2]) && UINTVAL (operands[2]) >= 63) + { + rtx zero = force_reg (V4DImode, CONST0_RTX (V4DImode)); + emit_insn (gen_avx2_gtv4di3 (operands[0], zero, operands[1])); + DONE; + } + if (operands[2] == const0_rtx) + { + emit_move_insn (operands[0], operands[1]); + DONE; + } + operands[1] = force_reg (V4DImode, operands[1]); + if (CONST_INT_P (operands[2])) + { + vec_perm_builder sel (8, 8, 1); + sel.quick_grow (8); + rtx arg0, arg1; + rtx op1 = lowpart_subreg (V8SImode, operands[1], V4DImode); + rtx target = gen_reg_rtx (V8SImode); + if (INTVAL (operands[2]) > 32) + { + arg0 = gen_reg_rtx (V8SImode); + arg1 = gen_reg_rtx (V8SImode); + emit_insn (gen_ashrv8si3 (arg1, op1, GEN_INT (31))); + emit_insn (gen_ashrv8si3 (arg0, op1, + GEN_INT (INTVAL (operands[2]) - 32))); + sel[0] = 1; + sel[1] = 9; + sel[2] = 3; + sel[3] = 11; + sel[4] = 5; + sel[5] = 13; + sel[6] = 7; + sel[7] = 15; + } + else if (INTVAL (operands[2]) == 32) + { + arg0 = op1; + arg1 = gen_reg_rtx (V8SImode); + emit_insn (gen_ashrv8si3 (arg1, op1, GEN_INT (31))); + sel[0] = 1; + sel[1] = 9; + sel[2] = 3; + sel[3] = 11; + sel[4] = 5; + sel[5] = 13; + sel[6] = 7; + sel[7] = 15; + } + else + { + arg0 = gen_reg_rtx (V4DImode); + arg1 = gen_reg_rtx (V8SImode); + emit_insn (gen_lshrv4di3 (arg0, operands[1], operands[2])); + emit_insn (gen_ashrv8si3 (arg1, op1, operands[2])); + arg0 = lowpart_subreg (V8SImode, arg0, V4DImode); + sel[0] = 0; + sel[1] = 9; + sel[2] = 2; + sel[3] = 11; + sel[4] = 4; + sel[5] = 13; + sel[6] = 6; + sel[7] = 15; + } + vec_perm_indices indices (sel, 2, 8); + bool ok = targetm.vectorize.vec_perm_const (V8SImode, target, + arg0, arg1, indices); + gcc_assert (ok); + emit_move_insn (operands[0], + lowpart_subreg (V4DImode, target, V8SImode)); + DONE; + } + + rtx zero = force_reg (V4DImode, CONST0_RTX (V4DImode)); + rtx zero_or_all_ones = gen_reg_rtx (V4DImode); + emit_insn (gen_avx2_gtv4di3 (zero_or_all_ones, zero, operands[1])); + rtx lshr_res = gen_reg_rtx (V4DImode); + emit_insn (gen_lshrv4di3 (lshr_res, operands[1], operands[2])); + rtx ashl_res = gen_reg_rtx (V4DImode); + rtx amount; + if (TARGET_64BIT) + { + amount = gen_reg_rtx (DImode); + emit_insn (gen_subdi3 (amount, force_reg (DImode, GEN_INT (64)), + operands[2])); + } + else + { + rtx temp = gen_reg_rtx (SImode); + emit_insn (gen_subsi3 (temp, force_reg (SImode, GEN_INT (64)), + lowpart_subreg (SImode, operands[2], + DImode))); + amount = gen_reg_rtx (V4SImode); + emit_insn (gen_vec_setv4si_0 (amount, CONST0_RTX (V4SImode), + temp)); + } + amount = lowpart_subreg (DImode, amount, GET_MODE (amount)); + emit_insn (gen_ashlv4di3 (ashl_res, zero_or_all_ones, amount)); + emit_insn (gen_iorv4di3 (operands[0], lshr_res, ashl_res)); + DONE; + } +}) + (define_insn "3" [(set (match_operand:VI248_AVX512BW_2 0 "register_operand" "=v,v") (any_lshift:VI248_AVX512BW_2 @@ -20329,10 +20449,132 @@ (ashiftrt:V2DI (match_operand:V2DI 1 "register_operand") (match_operand:DI 2 "nonmemory_operand")))] - "TARGET_XOP || TARGET_AVX512VL" + "TARGET_SSE2" { if (!TARGET_AVX512VL) { + if (TARGET_SSE4_2 + && CONST_INT_P (operands[2]) + && UINTVAL (operands[2]) >= 63) + { + rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode)); + emit_insn (gen_sse4_2_gtv2di3 (operands[0], zero, operands[1])); + DONE; + } + if (operands[2] == const0_rtx) + { + emit_move_insn (operands[0], operands[1]); + DONE; + } + if (CONST_INT_P (operands[2]) + && (!TARGET_XOP || UINTVAL (operands[2]) >= 63)) + { + vec_perm_builder sel (4, 4, 1); + sel.quick_grow (4); + rtx arg0, arg1; + rtx op1 = lowpart_subreg (V4SImode, operands[1], V2DImode); + rtx target = gen_reg_rtx (V4SImode); + if (UINTVAL (operands[2]) >= 63) + { + arg0 = arg1 = gen_reg_rtx (V4SImode); + emit_insn (gen_ashrv4si3 (arg0, op1, GEN_INT (31))); + sel[0] = 1; + sel[1] = 1; + sel[2] = 3; + sel[3] = 3; + } + else if (INTVAL (operands[2]) > 32) + { + arg0 = gen_reg_rtx (V4SImode); + arg1 = gen_reg_rtx (V4SImode); + emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31))); + emit_insn (gen_ashrv4si3 (arg0, op1, + GEN_INT (INTVAL (operands[2]) - 32))); + sel[0] = 1; + sel[1] = 5; + sel[2] = 3; + sel[3] = 7; + } + else if (INTVAL (operands[2]) == 32) + { + arg0 = op1; + arg1 = gen_reg_rtx (V4SImode); + emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31))); + sel[0] = 1; + sel[1] = 5; + sel[2] = 3; + sel[3] = 7; + } + else + { + arg0 = gen_reg_rtx (V2DImode); + arg1 = gen_reg_rtx (V4SImode); + emit_insn (gen_lshrv2di3 (arg0, operands[1], operands[2])); + emit_insn (gen_ashrv4si3 (arg1, op1, operands[2])); + arg0 = lowpart_subreg (V4SImode, arg0, V2DImode); + sel[0] = 0; + sel[1] = 5; + sel[2] = 2; + sel[3] = 7; + } + vec_perm_indices indices (sel, arg0 != arg1 ? 2 : 1, 4); + bool ok = targetm.vectorize.vec_perm_const (V4SImode, target, + arg0, arg1, indices); + gcc_assert (ok); + emit_move_insn (operands[0], + lowpart_subreg (V2DImode, target, V4SImode)); + DONE; + } + if (!TARGET_XOP) + { + rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode)); + rtx zero_or_all_ones; + if (TARGET_SSE4_2) + { + zero_or_all_ones = gen_reg_rtx (V2DImode); + emit_insn (gen_sse4_2_gtv2di3 (zero_or_all_ones, zero, + operands[1])); + } + else + { + rtx temp = gen_reg_rtx (V4SImode); + emit_insn (gen_ashrv4si3 (temp, lowpart_subreg (V4SImode, + operands[1], + V2DImode), + GEN_INT (31))); + zero_or_all_ones = gen_reg_rtx (V4SImode); + emit_insn (gen_sse2_pshufd_1 (zero_or_all_ones, temp, + const1_rtx, const1_rtx, + GEN_INT (3), GEN_INT (3))); + zero_or_all_ones = lowpart_subreg (V2DImode, zero_or_all_ones, + V4SImode); + } + rtx lshr_res = gen_reg_rtx (V2DImode); + emit_insn (gen_lshrv2di3 (lshr_res, operands[1], operands[2])); + rtx ashl_res = gen_reg_rtx (V2DImode); + rtx amount; + if (TARGET_64BIT) + { + amount = gen_reg_rtx (DImode); + emit_insn (gen_subdi3 (amount, force_reg (DImode, GEN_INT (64)), + operands[2])); + } + else + { + rtx temp = gen_reg_rtx (SImode); + emit_insn (gen_subsi3 (temp, force_reg (SImode, GEN_INT (64)), + lowpart_subreg (SImode, operands[2], + DImode))); + amount = gen_reg_rtx (V4SImode); + emit_insn (gen_vec_setv4si_0 (amount, CONST0_RTX (V4SImode), + temp)); + } + amount = lowpart_subreg (DImode, amount, GET_MODE (amount)); + emit_insn (gen_ashlv2di3 (ashl_res, zero_or_all_ones, amount)); + emit_insn (gen_iorv2di3 (operands[0], lshr_res, ashl_res)); + DONE; + } + rtx reg = gen_reg_rtx (V2DImode); rtx par; bool negate = false; diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-4.inc b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc index d041b33..fb35df8 100644 --- a/gcc/testsuite/gcc.dg/torture/vshuf-4.inc +++ b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc @@ -25,7 +25,9 @@ T (21, 2, 6, 3, 7) \ T (22, 1, 2, 3, 0) \ T (23, 2, 1, 0, 3) \ T (24, 2, 5, 6, 3) \ -T (25, 0, 1, 4, 5) +T (25, 0, 1, 4, 5) \ +T (26, 1, 5, 3, 7) \ +T (27, 0, 5, 2, 7) #define EXPTESTS \ T (116, 1, 2, 4, 3) \ T (117, 7, 3, 3, 0) \ diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-8.inc b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc index de358f3..d628039 100644 --- a/gcc/testsuite/gcc.dg/torture/vshuf-8.inc +++ b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc @@ -27,7 +27,9 @@ T (23, 6, 5, 4, 3, 2, 1, 0, 7) \ T (24, 0, 1, 2, 3, 8, 9, 10, 11) \ T (25, 0, 1, 2, 3, 12, 13, 14, 15) \ T (26, 0, 1, 8, 9, 10, 11, 12, 13) \ -T (27, 0, 8, 9, 10, 11, 12, 13, 14) +T (27, 0, 8, 9, 10, 11, 12, 13, 14) \ +T (28, 1, 9, 3, 11, 5, 13, 7, 15) \ +T (29, 0, 9, 2, 11, 4, 13, 6, 15) #define EXPTESTS \ T (116, 9, 3, 9, 4, 7, 0, 0, 6) \ T (117, 4, 14, 12, 8, 9, 6, 0, 10) \ diff --git a/gcc/testsuite/gcc.target/i386/avx-pr82370.c b/gcc/testsuite/gcc.target/i386/avx-pr82370.c index 4dc8a5b..dc12dbf 100644 --- a/gcc/testsuite/gcc.target/i386/avx-pr82370.c +++ b/gcc/testsuite/gcc.target/i386/avx-pr82370.c @@ -4,7 +4,7 @@ /* { dg-final { scan-assembler-times "vpslld\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 3 } } */ /* { dg-final { scan-assembler-times "vpsllq\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 3 } } */ /* { dg-final { scan-assembler-times "vpsllw\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 3 } } */ -/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 3 } } */ +/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 6 } } */ /* { dg-final { scan-assembler-times "vpsraq\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 0 } } */ /* { dg-final { scan-assembler-times "vpsraw\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 3 } } */ /* { dg-final { scan-assembler-times "vpsrld\[ \t]\+\\\$5, %xmm\[0-9]\+, %xmm\[0-9]\+" 3 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx-psraq-1.c b/gcc/testsuite/gcc.target/i386/avx-psraq-1.c new file mode 100644 index 0000000..2722088 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx-psraq-1.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mavx -mno-avx2" } */ +/* { dg-require-effective-target avx } */ + +#ifndef CHECK_H +#define CHECK_H "avx-check.h" +#endif + +#ifndef TEST +#define TEST avx_test +#endif + +#include "sse2-psraq-1.c" diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr82370.c b/gcc/testsuite/gcc.target/i386/avx2-pr82370.c index 6609ebb..df3dfd8 100644 --- a/gcc/testsuite/gcc.target/i386/avx2-pr82370.c +++ b/gcc/testsuite/gcc.target/i386/avx2-pr82370.c @@ -4,7 +4,7 @@ /* { dg-final { scan-assembler-times "vpslld\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllq\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllw\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ -/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ +/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 2 } } */ /* { dg-final { scan-assembler-times "vpsraq\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 0 } } */ /* { dg-final { scan-assembler-times "vpsraw\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsrld\[ \t]\+\\\$5, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ @@ -13,7 +13,7 @@ /* { dg-final { scan-assembler-times "vpslld\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllq\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllw\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ -/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ +/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 2 } } */ /* { dg-final { scan-assembler-times "vpsraq\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 0 } } */ /* { dg-final { scan-assembler-times "vpsraw\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsrld\[ \t]\+\\\$5, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx2-psraq-1.c b/gcc/testsuite/gcc.target/i386/avx2-psraq-1.c new file mode 100644 index 0000000..e9051bf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx2-psraq-1.c @@ -0,0 +1,51 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mavx2 -mno-avx512f" } */ +/* { dg-require-effective-target avx2 } */ + +#ifndef CHECK_H +#define CHECK_H "avx2-check.h" +#endif + +#ifndef TEST +#define TEST avx2_test +#endif + +#include CHECK_H + +typedef long long V __attribute__((vector_size (32))); + +#define TESTN(N) \ +static V \ +__attribute__((noipa)) \ +test##N (V x) \ +{ \ + return x >> N; \ +} + +#define TESTS TESTN (63) TESTN (49) TESTN (32) TESTN (31) TESTN (18) +TESTS + +struct +{ + int n; + V (*fn) (V); +} tests[] = { +#undef TESTN +#define TESTN(N) { N, test##N }, + TESTS +}; + +static void +TEST (void) +{ + V a = (V) { 0xdeadbeefcafebabeULL, 0x123456789abcdef0ULL, + 0x173a74be8a95134cULL, 0x817bae35ac0ebf12ULL }; + int i; + for (i = 0; tests[i].n; i++) + { + V c = tests[i].fn (a); + if (c[0] != a[0] >> tests[i].n || c[1] != a[1] >> tests[i].n + || c[2] != a[2] >> tests[i].n || c[3] != a[3] >> tests[i].n) + abort (); + } +} diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr82370.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr82370.c index 174f499..12c3b27 100644 --- a/gcc/testsuite/gcc.target/i386/avx512bw-pr82370.c +++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr82370.c @@ -4,7 +4,7 @@ /* { dg-final { scan-assembler-times "vpslld\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllq\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllw\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ -/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ +/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 2 } } */ /* { dg-final { scan-assembler-times "vpsraq\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 0 } } */ /* { dg-final { scan-assembler-times "vpsraw\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsrld\[ \t]\+\\\$5, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ @@ -13,7 +13,7 @@ /* { dg-final { scan-assembler-times "vpslld\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllq\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllw\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ -/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ +/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 2 } } */ /* { dg-final { scan-assembler-times "vpsraq\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 0 } } */ /* { dg-final { scan-assembler-times "vpsraw\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsrld\[ \t]\+\\\$5, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr82370.c b/gcc/testsuite/gcc.target/i386/avx512f-pr82370.c index 20ad8dc..b179f9b 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-pr82370.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-pr82370.c @@ -4,7 +4,7 @@ /* { dg-final { scan-assembler-times "vpslld\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllq\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllw\[ \t]\+\\\$7, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ -/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ +/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 2 } } */ /* { dg-final { scan-assembler-times "vpsraq\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 0 } } */ /* { dg-final { scan-assembler-times "vpsraw\[ \t]\+\\\$3, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsrld\[ \t]\+\\\$5, %xmm\[0-9]\+, %xmm\[0-9]\+" 1 } } */ @@ -13,7 +13,7 @@ /* { dg-final { scan-assembler-times "vpslld\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllq\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ /* { dg-final { scan-assembler-times "vpsllw\[ \t]\+\\\$7, %ymm\[0-9]\+, %ymm\[0-9]\+" 3 } } */ -/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ +/* { dg-final { scan-assembler-times "vpsrad\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 2 } } */ /* { dg-final { scan-assembler-times "vpsraq\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 0 } } */ /* { dg-final { scan-assembler-times "vpsraw\[ \t]\+\\\$3, %ymm\[0-9]\+, %ymm\[0-9]\+" 3 } } */ /* { dg-final { scan-assembler-times "vpsrld\[ \t]\+\\\$5, %ymm\[0-9]\+, %ymm\[0-9]\+" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/sse2-psraq-1.c b/gcc/testsuite/gcc.target/i386/sse2-psraq-1.c new file mode 100644 index 0000000..9a08ee4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-psraq-1.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -msse2 -mno-sse3" } */ +/* { dg-require-effective-target sse2 } */ + +#ifndef CHECK_H +#define CHECK_H "sse2-check.h" +#endif + +#ifndef TEST +#define TEST sse2_test +#endif + +#include CHECK_H + +typedef long long V __attribute__((vector_size (16))); + +#define TESTN(N) \ +static V \ +__attribute__((noipa)) \ +test##N (V x) \ +{ \ + return x >> N; \ +} + +#define TESTS TESTN (63) TESTN (49) TESTN (32) TESTN (31) TESTN (18) +TESTS + +struct +{ + int n; + V (*fn) (V); +} tests[] = { +#undef TESTN +#define TESTN(N) { N, test##N }, + TESTS +}; + +static void +TEST (void) +{ + V a = (V) { 0xdeadbeefcafebabeULL, 0x123456789abcdef0ULL }; + V b = (V) { 0x173a74be8a95134cULL, 0x817bae35ac0ebf12ULL }; + int i; + for (i = 0; tests[i].n; i++) + { + V c = tests[i].fn (a); + if (c[0] != a[0] >> tests[i].n || c[1] != a[1] >> tests[i].n) + abort (); + c = tests[i].fn (b); + if (c[0] != b[0] >> tests[i].n || c[1] != b[1] >> tests[i].n) + abort (); + } +} diff --git a/gcc/testsuite/gcc.target/i386/sse4_2-psraq-1.c b/gcc/testsuite/gcc.target/i386/sse4_2-psraq-1.c new file mode 100644 index 0000000..947b623 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse4_2-psraq-1.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -msse4.2 -mno-avx" } */ +/* { dg-require-effective-target sse4 } */ + +#ifndef CHECK_H +#define CHECK_H "sse4_2-check.h" +#endif + +#ifndef TEST +#define TEST sse4_2_test +#endif + +#include "sse2-psraq-1.c" -- cgit v1.1 From a451598b2c02e1ca3c62fea272d73a9f31922252 Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Thu, 13 May 2021 11:42:58 +0100 Subject: arm: correctly handle inequality comparisons against max constants [PR100563] Normally we expect the gimple optimizers to fold away comparisons that are always true, but at some lower optimization levels this is not always the case, so the back-end has to be able to generate correct code in these cases. In this example, we have a comparison of the form (unsigned long long) op <= ~0ULL which, of course is always true. Normally, in the arm back-end we handle these expansions where the immediate cannot be handled directly by adding 1 to the constant and then adjusting the comparison operator: (unsigned long long) op < CONST + 1 but we cannot do that when the constant is already the largest value. Fortunately, we observe that the comparisons we need to handle this way are either always true or always false, so instead of forming a comparison against the maximum value, we can replace it with a comparison against the minimum value (which just happens to also be a constant we can handle. So op1 <= ~0ULL -> op1 >= 0U op1 > ~0ULL -> op1 < 0U op1 <= LONG_LONG_INT_MAX -> op1 >= (-LONG_LONG_INT_MAX - 1) op1 > LONG_LONG_INT_MAX -> op1 < (-LONG_LONG_INT_MAX - 1) gcc: PR target/100563 * config/arm/arm.c (arm_canonicalize_comparison): Correctly canonicalize DImode inequality comparisons against the maximum integral value. gcc/testsuite: * gcc.dg/pr100563.c: New test. --- gcc/config/arm/arm.c | 29 +++++++++++++++++++++++++---- gcc/testsuite/gcc.dg/pr100563.c | 9 +++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr100563.c (limited to 'gcc') diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 2962071..d0c0c50 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -5563,9 +5563,20 @@ arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1, return; *op1 = GEN_INT (i + 1); *code = *code == GT ? GE : LT; - return; } - break; + else + { + /* GT maxval is always false, LE maxval is always true. + We can't fold that away here as we must make a + comparison, but we can fold them to comparisons + with the same result that can be handled: + op0 GT maxval -> op0 LT minval + op0 LE maxval -> op0 GE minval + where minval = (-maxval - 1). */ + *op1 = GEN_INT (-maxval - 1); + *code = *code == GT ? LT : GE; + } + return; case GTU: case LEU: @@ -5578,9 +5589,19 @@ arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1, return; *op1 = GEN_INT (i + 1); *code = *code == GTU ? GEU : LTU; - return; } - break; + else + { + /* GTU ~0 is always false, LEU ~0 is always true. + We can't fold that away here as we must make a + comparison, but we can fold them to comparisons + with the same result that can be handled: + op0 GTU ~0 -> op0 LTU 0 + op0 LEU ~0 -> op0 GEU 0. */ + *op1 = const0_rtx; + *code = *code == GTU ? LTU : GEU; + } + return; default: gcc_unreachable (); diff --git a/gcc/testsuite/gcc.dg/pr100563.c b/gcc/testsuite/gcc.dg/pr100563.c new file mode 100644 index 0000000..812eb9e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr100563.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-Og" } */ +unsigned long long e(void); +void f(int); +void a() { + short b = -1, c = (int)&b; + unsigned long long d = e(); + f(b >= d); +} -- cgit v1.1 From efd471a980662f113dad8de0c0ef8593d0d38419 Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Thu, 13 May 2021 14:52:05 +0100 Subject: testsuite: suppress cast warnings in pr100563.c [PR100563] Fix a warning when building on machines that don't have 32-bit pointers gcc/testsuite: PR target/100563 * gcc.dg/pr100563.c (dg-options): Add -wno-pointer-to-int-cast. --- gcc/testsuite/gcc.dg/pr100563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/pr100563.c b/gcc/testsuite/gcc.dg/pr100563.c index 812eb9e..f6a5fcd 100644 --- a/gcc/testsuite/gcc.dg/pr100563.c +++ b/gcc/testsuite/gcc.dg/pr100563.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Og" } */ +/* { dg-options "-Og -Wno-pointer-to-int-cast" } */ unsigned long long e(void); void f(int); void a() { -- cgit v1.1 From d80aeff0bf2f455e9099def756f612bfbcd2cb0d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 13 May 2021 16:53:48 +0200 Subject: openmp: Add testcases to verify OpenMP 5.0 2.14 and OpenMP 5.1 2.17 rules [PR99928] In preparation of PR99928 patch review, I've prepared testcases with clauses that need more interesting handling on combined/composite constructs, in particular firstprivate, lastprivate, firstprivate+lastprivate, linear (explicit on non-iv, explicit on simd iv, implicit on simd iv, implicit on simd iv declared in the construct), reduction (scalars, array sections of array variables, array sections with pointer bases) and in_reduction. OpenMP 5.0 had the wording broken for reduction, the intended rule to use map(tofrom:) on target when combined with it was bound only on inscan modifier presence which makes no sense, as then inscan may not be used, this has been fixed in 5.1 and I'm just assuming 5.1 wording for that. There are various cases where e.g. from historical or optimization reasons GCC slightly deviates from the rules, but in most cases it is something that shouldn't be really observable, e.g. whether #pragma omp parallel for firstprivate(x) is handled as #pragma omp parallel shared(x) #pragma omp for firstprivate(x) or #pragma omp parallel firstprivate(x) #pragma omp for shouldn't be possible to distinguish in user code. I've added FIXMEs in the testcases about that, but maybe we just should keep it as is (alternative would be to do it in standard compliant way and transform into whatever we like after gimplification (e.g. early during omplower)). Some cases we for historical reasons implement even with clauses on constructs which in the standard don't accept them that way and then handling those magically in omp lowering/expansion, in particular e.g. #pragma omp parallel for firstprivate(x) lastprivate(x) we treat as #pragma omp parallel firstprivate(x) lastprivate(x) #pragma omp for even when lastprivate is not valid on parallel. Maybe one day we could change that if we make sure we don't regress generated code quality. I've also found a bug in OpenMP 5.0/5.1, #pragma omp parallel sections firstprivate(x) lastprivate(x) incorrectly says that it should be handled as #pragma omp parallel firstprivate(x) #pragma omp sections lastprivate(x) which when written that way results in error; filed as https://github.com/OpenMP/spec/issues/2758 to be fixed in OpenMP 5.2. GCC handles it the way it used to do and users expect, so nothing to fix on the GCC side. Also, we don't support yet in_reduction clause on target construct, which means the -11.c testcase can't include any tests about in_reduction handling on all the composite constructs that include target. The work found two kinds of bugs on the GCC side, one is the known thing that we implement still the 4.5 behavior and don't mark for lastprivate/linear/reduction the list item as map(tofrom:) as mentioned in PR99928. These cases are xfailed in the tests. And another one is with r21 and r28 in -{8,9,10}.c tests - we don't add reduction clause on teams for #pragma omp {target ,}teams distribute simd reduction(+:r) even when the spec says that teams shouldn't receive reduction only when combined with loop construct. In make check-gcc check-g++ RUNTESTFLAGS='--target_board=unix\{-m32,-m64\} gomp.exp=pr99928*' testing this shows: # of expected passes 5648 # of expected failures 872 and with Tobias' patch applied: # of expected passes 5648 # of unexpected successes 384 # of expected failures 488 2021-05-13 Jakub Jelinek PR middle-end/99928 * c-c++-common/gomp/pr99928-1.c: New test. * c-c++-common/gomp/pr99928-2.c: New test. * c-c++-common/gomp/pr99928-3.c: New test. * c-c++-common/gomp/pr99928-4.c: New test. * c-c++-common/gomp/pr99928-5.c: New test. * c-c++-common/gomp/pr99928-6.c: New test. * c-c++-common/gomp/pr99928-7.c: New test. * c-c++-common/gomp/pr99928-8.c: New test. * c-c++-common/gomp/pr99928-9.c: New test. * c-c++-common/gomp/pr99928-10.c: New test. * c-c++-common/gomp/pr99928-11.c: New test. --- gcc/testsuite/c-c++-common/gomp/pr99928-1.c | 206 ++++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-10.c | 231 +++++++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-11.c | 28 ++++ gcc/testsuite/c-c++-common/gomp/pr99928-2.c | 208 ++++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-3.c | 119 ++++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-4.c | 76 +++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-5.c | 107 +++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-6.c | 107 +++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-7.c | 103 ++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-8.c | 219 +++++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/pr99928-9.c | 219 +++++++++++++++++++++++++ 11 files changed, 1623 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-1.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-10.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-11.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-2.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-3.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-4.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-5.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-6.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-7.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-8.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr99928-9.c (limited to 'gcc') diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-1.c b/gcc/testsuite/c-c++-common/gomp/pr99928-1.c new file mode 100644 index 0000000..37181fd --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-1.c @@ -0,0 +1,206 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int f00, f01, f02, f03, f04, f05, f06, f07, f08, f09; +int f12, f13, f14, f15, f16, f17, f18, f19; +int f20, f21, f22, f23, f24, f25, f26, f27, f28, f29; + +void +foo (void) +{ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*firstprivate\\(f00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f00\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f00\\)" "gimple" } } *//* FIXME. */ + #pragma omp distribute parallel for firstprivate (f00) + for (int i = 0; i < 64; i++) + f00++; + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*firstprivate\\(f01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f01\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f01\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f01\\)" "gimple" } } */ + #pragma omp distribute parallel for simd firstprivate (f01) + for (int i = 0; i < 64; i++) + f01++; + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*firstprivate\\(f02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f02\\)" "gimple" } } */ + #pragma omp distribute simd firstprivate (f02) + for (int i = 0; i < 64; i++) + f02++; +} + +void +bar (void) +{ + int f10 = 0, f11 = 0; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*firstprivate\\(f03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f03\\)" "gimple" } } */ + #pragma omp for simd firstprivate (f03) + for (int i = 0; i < 64; i++) + f03++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(f04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(f04\\)" "gimple" } } */ + #pragma omp master taskloop firstprivate (f04) + for (int i = 0; i < 64; i++) + f04++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(f05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(f05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f05\\)" "gimple" } } */ + #pragma omp master taskloop simd firstprivate (f05) + for (int i = 0; i < 64; i++) + f05++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f06\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f06\\)" "gimple" } } *//* FIXME. */ + #pragma omp parallel for firstprivate (f06) + for (int i = 0; i < 64; i++) + f06++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f07\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f07\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f07\\)" "gimple" } } */ + #pragma omp parallel for simd firstprivate (f07) + for (int i = 0; i < 64; i++) + f07++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f08\\)" "gimple" } } */ + #pragma omp parallel loop firstprivate (f08) + for (int i = 0; i < 64; i++) + f08++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(f09\\)" "gimple" } } */ + #pragma omp parallel master firstprivate (f09) + f09++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(f10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(f10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(f10\\)" "gimple" } } */ + #pragma omp parallel master taskloop firstprivate (f10) + for (int i = 0; i < 64; i++) + f10++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(f11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(f11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(f11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f11\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd firstprivate (f11) + for (int i = 0; i < 64; i++) + f11++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*firstprivate\\(f12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp section \[^\n\r]*firstprivate\\(f12\\)" "gimple" } } */ + #pragma omp parallel sections firstprivate (f12) + { + f12++; + #pragma omp section + f12++; + } + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f13\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f13\\)" "gimple" } } */ + #pragma omp target parallel firstprivate (f13) + f13++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f14\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f14\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f14\\)" "gimple" } } *//* FIXME. */ + #pragma omp target parallel for firstprivate (f14) + for (int i = 0; i < 64; i++) + f14++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f15\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f15\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f15\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f15\\)" "gimple" } } */ + #pragma omp target parallel for simd firstprivate (f15) + for (int i = 0; i < 64; i++) + f15++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f16\\)" "gimple" } } */ + #pragma omp target parallel loop firstprivate (f16) + for (int i = 0; i < 64; i++) + f16++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f17\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f17\\)" "gimple" } } */ + #pragma omp target teams firstprivate (f17) + f17++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f18\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f18\\)" "gimple" } } *//* FIXME: This should be on distribute instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f18\\)" "gimple" } } *//* FIXME. */ + #pragma omp target teams distribute firstprivate (f18) + for (int i = 0; i < 64; i++) + f18++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } *//* FIXME: This should be on distribute instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f19\\)" "gimple" } } *//* FIXME. */ + #pragma omp target teams distribute parallel for firstprivate (f19) + for (int i = 0; i < 64; i++) + f19++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f20\\)" "gimple" } } */ + #pragma omp target teams distribute parallel for simd firstprivate (f20) + for (int i = 0; i < 64; i++) + f20++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f21\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f21\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f21\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f21\\)" "gimple" } } */ + #pragma omp target teams distribute simd firstprivate (f21) + for (int i = 0; i < 64; i++) + f21++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(f22\\)" "gimple" } } *//* NOTE: This is an implementation detail. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f22\\)" "gimple" } } */ + #pragma omp target teams loop firstprivate (f22) + for (int i = 0; i < 64; i++) + f22++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*firstprivate\\(f23\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f23\\)" "gimple" } } */ + #pragma omp target simd firstprivate (f23) + for (int i = 0; i < 64; i++) + f23++; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(f24\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f24\\)" "gimple" } } */ + #pragma omp taskloop simd firstprivate (f24) + for (int i = 0; i < 64; i++) + f24++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f25\\)" "gimple" } } *//* FIXME: This should be on distribute instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f25\\)" "gimple" } } *//* FIXME. */ + #pragma omp teams distribute firstprivate (f25) + for (int i = 0; i < 64; i++) + f25++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f26\\)" "gimple" } } *//* FIXME: This should be on distribute instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f26\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f26\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f26\\)" "gimple" } } *//* FIXME. */ + #pragma omp teams distribute parallel for firstprivate (f26) + for (int i = 0; i < 64; i++) + f26++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f27\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f27\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(f27\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f27\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f27\\)" "gimple" } } */ + #pragma omp teams distribute parallel for simd firstprivate (f27) + for (int i = 0; i < 64; i++) + f27++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f28\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f28\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f28\\)" "gimple" } } */ + #pragma omp teams distribute simd firstprivate (f28) + for (int i = 0; i < 64; i++) + f28++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(f29\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*firstprivate\\(f29\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(f29\\)" "gimple" } } *//* NOTE: This is an implementation detail. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(f29\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(f29\\)" "gimple" } } */ + #pragma omp teams loop firstprivate (f29) + for (int i = 0; i < 64; i++) + f29++; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-10.c b/gcc/testsuite/c-c++-common/gomp/pr99928-10.c new file mode 100644 index 0000000..4acff45 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-10.c @@ -0,0 +1,231 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int *r00, *r01, *r02, *r03, *r04, *r05; +int *r13, *r14, *r15, *r16, *r17, *r18, *r19; +int *r20, *r21, *r22, *r23, *r24; +int *baz (void); + +void +foo (void) +{ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r00 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r00 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r00 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp distribute parallel for reduction(+:r00[1:2]) + for (int i = 0; i < 64; i++) + r00[1]++; + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r01 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r01 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r01 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r01 \\+ 4" "gimple" } } */ + #pragma omp distribute parallel for simd reduction(+:r01[1:3]) + for (int i = 0; i < 64; i++) + r01[1]++; + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r02 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r02 \\+ 4" "gimple" } } */ + #pragma omp distribute simd reduction(+:r02[1:4]) + for (int i = 0; i < 64; i++) + r02[1]++; +} + +void +bar (void) +{ + int *r06 = baz (), *r07 = baz (), *r08 = baz (), *r09 = baz (); + int *r10 = baz (), *r11 = baz (), *r12 = baz (); + int *r25 = baz (), *r26 = baz (), *r27 = baz (), *r28 = baz (), *r29 = baz (); + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r03 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r03 \\+ 4" "gimple" } } */ + #pragma omp for simd reduction(+:r03[1:5]) + for (int i = 0; i < 64; i++) + r03[1]++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r04 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r04 \\+ 4" "gimple" } } */ + #pragma omp master taskloop reduction(+:r04[1:6]) + for (int i = 0; i < 64; i++) + r04[1]++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r05 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r05 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r05 \\+ 4" "gimple" } } */ + #pragma omp master taskloop simd reduction(+:r05[1:7]) + for (int i = 0; i < 64; i++) + r05[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r06 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r06 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp parallel for reduction(+:r06[1:8]) + for (int i = 0; i < 64; i++) + r06[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r07 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r07 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r07 \\+ 4" "gimple" } } */ + #pragma omp parallel for simd reduction(+:r07[1:9]) + for (int i = 0; i < 64; i++) + r07[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(r08\\)" "gimple" } } *//* FIXME: Should be shared, but firstprivate is an optimization. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r08 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r08 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp parallel loop reduction(+:r08[1:10]) + for (int i = 0; i < 64; i++) + r08[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r09 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r09 \\+ 4" "gimple" } } */ + #pragma omp parallel master reduction(+:r09[1:11]) + r09[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(r10\\)" "gimple" } } *//* FIXME: Should be shared, but firstprivate is an optimization. */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r10 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r10 \\+ 4" "gimple" } } */ + #pragma omp parallel master taskloop reduction(+:r10[1:12]) + for (int i = 0; i < 64; i++) + r10[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(r11\\)" "gimple" } } *//* FIXME: Should be shared, but firstprivate is an optimization. */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r11 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r11 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r11 \\+ 4" "gimple" } } */ + #pragma omp parallel master taskloop simd reduction(+:r11[1:13]) + for (int i = 0; i < 64; i++) + r11[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r12 \\+ 4" "gimple" } } *//* FIXME: This should be on sections instead. */ + /* { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r12 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp section \[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r12 \\+ 4" "gimple" } } */ + #pragma omp parallel sections reduction(+:r12[1:14]) + { + r12[1]++; + #pragma omp section + r12[1]++; + } + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 60\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r13 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r13\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r13 \\+ 4" "gimple" } } */ + #pragma omp target parallel reduction(+:r13[1:15]) + r13[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 64\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r14 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r14" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r14 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r14 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp target parallel for reduction(+:r14[1:16]) + for (int i = 0; i < 64; i++) + r14[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 68\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r15 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r15\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r15 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r15 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r15 \\+ 4" "gimple" } } */ + #pragma omp target parallel for simd reduction(+:r15[1:17]) + for (int i = 0; i < 64; i++) + r15[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 72\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r16 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r16\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(r16\\)" "gimple" } } *//* FIXME: Should be shared, but firstprivate is an optimization. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r16 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r16 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target parallel loop reduction(+:r16[1:18]) + for (int i = 0; i < 64; i++) + r16[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 76\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r17 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r17\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r17 \\+ 4" "gimple" } } */ + #pragma omp target teams reduction(+:r17[1:19]) + r17[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 80\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r18 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r18\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r18 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r18 \\+ 4" "gimple" } } */ + #pragma omp target teams distribute reduction(+:r18[1:20]) + for (int i = 0; i < 64; i++) + r18[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 84\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r19 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r19\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r19 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r19 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r19 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r19 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp target teams distribute parallel for reduction(+:r19[1:21]) + for (int i = 0; i < 64; i++) + r19[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 88\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r20 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r20\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r20 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r20 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r20 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r20 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r20 \\+ 4" "gimple" } } */ + #pragma omp target teams distribute parallel for simd reduction(+:r20[1:22]) + for (int i = 0; i < 64; i++) + r20[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 92\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r21 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r21\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r21 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r21 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r21 \\+ 4" "gimple" } } */ + #pragma omp target teams distribute simd reduction(+:r21[1:23]) + for (int i = 0; i < 64; i++) + r21[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 96\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r22 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r22\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(r22\\)" "gimple" } } *//* FIXME: Should be shared, but firstprivate is an optimization. */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r22 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(r22\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r22 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r22 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target teams loop reduction(+:r22[1:24]) + for (int i = 0; i < 64; i++) + r22[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:\\\*_\[0-9]* \\\[len: 100\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(firstprivate:r23 \\\[pointer assign, bias: 4\\\]\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r23\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r23 \\+ 4" "gimple" } } */ + #pragma omp target simd reduction(+:r23[1:25]) + for (int i = 0; i < 64; i++) + r23[1]++; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r24 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r24 \\+ 4" "gimple" } } */ + #pragma omp taskloop simd reduction(+:r24[1:26]) + for (int i = 0; i < 64; i++) + r24[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r25 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r25 \\+ 4" "gimple" } } */ + #pragma omp teams distribute reduction(+:r25[1:27]) + for (int i = 0; i < 64; i++) + r25[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r26 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r26 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r26 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r26 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp teams distribute parallel for reduction(+:r26[1:28]) + for (int i = 0; i < 64; i++) + r26[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r27 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r27 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r27 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r27 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r27 \\+ 4" "gimple" } } */ + #pragma omp teams distribute parallel for simd reduction(+:r27[1:29]) + for (int i = 0; i < 64; i++) + r27[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r28 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r28 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r28 \\+ 4" "gimple" } } */ + #pragma omp teams distribute simd reduction(+:r28[1:30]) + for (int i = 0; i < 64; i++) + r28[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*firstprivate\\(r29\\)" "gimple" } } *//* FIXME: Should be shared, but firstprivate is an optimization. */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r29 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(r29\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r29 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*\\)r29 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp teams loop reduction(+:r29[1:31]) + for (int i = 0; i < 64; i++) + r29[1]++; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-11.c b/gcc/testsuite/c-c++-common/gomp/pr99928-11.c new file mode 100644 index 0000000..66c2feb --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-11.c @@ -0,0 +1,28 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int r00, r01, r02; + +void +bar (void) +{ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*in_reduction\\(\\+:r00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*in_reduction\\(\\+:r00\\)" "gimple" } } */ + #pragma omp master taskloop in_reduction(+:r00) + for (int i = 0; i < 64; i++) + r00++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*in_reduction\\(\\+:r01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*in_reduction\\(\\+:r01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*in_reduction\\(\\+:r01\\)" "gimple" } } */ + #pragma omp master taskloop simd in_reduction(+:r01) + for (int i = 0; i < 64; i++) + r01++; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*in_reduction\\(\\+:r02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*in_reduction\\(\\+:r02\\)" "gimple" } } */ + #pragma omp taskloop simd in_reduction(+:r02) + for (int i = 0; i < 64; i++) + r02++; + /* FIXME: We don't support in_reduction clause on target yet, once we do, should + add testcase coverage for all combined/composite constructs with target as leaf construct. */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-2.c b/gcc/testsuite/c-c++-common/gomp/pr99928-2.c new file mode 100644 index 0000000..313374c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-2.c @@ -0,0 +1,208 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int l00, l01, l02, l03, l04, l05, l06, l07; +int l10, l11, l12, l13, l14, l15, l16, l17, l18; + +void +foo (void) +{ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l00\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l00\\)" "gimple" } } *//* FIXME. */ + #pragma omp distribute parallel for lastprivate (l00) + for (int i = 0; i < 64; i++) + l00 = i; + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } */ + #pragma omp distribute parallel for simd lastprivate (l01) + for (int i = 0; i < 64; i++) + l01 = i; + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l02\\)" "gimple" } } */ + #pragma omp distribute simd lastprivate (l02) + for (int i = 0; i < 64; i++) + l02 = i; +} + +void +bar (void) +{ + int j00, j01, j02, j03; + int l08 = 0, l09 = 0, l19 = 0, l20 = 0, l21 = 0, l22 = 0; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } */ + #pragma omp for simd lastprivate (l03) + for (int i = 0; i < 64; i++) + l03 = i; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(l04\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } */ + #pragma omp master taskloop lastprivate (l04) + for (int i = 0; i < 64; i++) + l04 = i; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(l05\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l05\\)" "gimple" } } */ + #pragma omp master taskloop simd lastprivate (l05) + for (int i = 0; i < 64; i++) + l05 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } *//* FIXME. */ + #pragma omp parallel for lastprivate (l06) + for (int i = 0; i < 64; i++) + l06 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l07\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l07\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l07\\)" "gimple" } } */ + #pragma omp parallel for simd lastprivate (l07) + for (int i = 0; i < 64; i++) + l07 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp parallel loop lastprivate (j00) + for (j00 = 0; j00 < 64; j00++) + ; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(l08\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } */ + #pragma omp parallel master taskloop lastprivate (l08) + for (int i = 0; i < 64; i++) + l08 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(l09\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd lastprivate (l09) + for (int i = 0; i < 64; i++) + l09 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l10\\)" "gimple" } } *//* FIXME: This should be on sections instead. */ + /* { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*lastprivate\\(l10\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp section \[^\n\r]*lastprivate\\(l10\\)" "gimple" } } */ + #pragma omp parallel sections lastprivate (l10) + { + l10 = 1; + #pragma omp section + l10 = 2; + } + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l11" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l11\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } *//* FIXME. */ + #pragma omp target parallel for lastprivate (l11) + for (int i = 0; i < 64; i++) + l11 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l12" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l12\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l12\\)" "gimple" } } */ + #pragma omp target parallel for simd lastprivate (l12) + for (int i = 0; i < 64; i++) + l12 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j01" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j01\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target parallel loop lastprivate (j01) + for (j01 = 0; j01 < 64; j01++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l13" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l13\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l13\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l13\\)" "gimple" } } */ + #pragma omp target teams distribute lastprivate (l13) + for (int i = 0; i < 64; i++) + l13 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l14" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l14\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l14\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l14\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l14\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l14\\)" "gimple" } } *//* FIXME. */ + #pragma omp target teams distribute parallel for lastprivate (l14) + for (int i = 0; i < 64; i++) + l14 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l15" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l15\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l15\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l15\\)" "gimple" } } */ + #pragma omp target teams distribute parallel for simd lastprivate (l15) + for (int i = 0; i < 64; i++) + l15 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l16" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l16\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l16\\)" "gimple" } } */ + #pragma omp target teams distribute simd lastprivate (l16) + for (int i = 0; i < 64; i++) + l16 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j02" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j02\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j02\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target teams loop lastprivate (j02) + for (j02 = 0; j02 < 64; j02++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l17" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l17\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l17\\)" "gimple" } } */ + #pragma omp target simd lastprivate (l17) + for (int i = 0; i < 64; i++) + l17 = i; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(l18\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l18\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l18\\)" "gimple" } } */ + #pragma omp taskloop simd lastprivate (l18) + for (int i = 0; i < 64; i++) + l18 = i; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l19\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l19\\)" "gimple" } } */ + #pragma omp teams distribute lastprivate (l19) + for (int i = 0; i < 64; i++) + l19 = i; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l20\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l20\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l20\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l20\\)" "gimple" } } *//* FIXME. */ + #pragma omp teams distribute parallel for lastprivate (l20) + for (int i = 0; i < 64; i++) + l20 = i; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l21\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l21\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l21\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l21\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l21\\)" "gimple" } } */ + #pragma omp teams distribute parallel for simd lastprivate (l21) + for (int i = 0; i < 64; i++) + l21 = i; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(l22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(l22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l22\\)" "gimple" } } */ + #pragma omp teams distribute simd lastprivate (l22) + for (int i = 0; i < 64; i++) + l22 = i; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j03\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp teams loop lastprivate (j03) + for (j03 = 0; j03 < 64; j03++) + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-3.c b/gcc/testsuite/c-c++-common/gomp/pr99928-3.c new file mode 100644 index 0000000..67f590b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-3.c @@ -0,0 +1,119 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int l00, l01, l02, l03, l04, l07, l08, l09; +int l10, l11; + +void +bar (void) +{ + int l05 = 0, l06 = 0; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*firstprivate\\(l00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(l00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l00\\)" "gimple" } } */ + #pragma omp for simd firstprivate (l00) lastprivate (l00) + for (int i = 0; i < 64; i++) + l00 = i; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } */ + #pragma omp master taskloop firstprivate (l01) lastprivate (l01) + for (int i = 0; i < 64; i++) + l01 = i; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l02\\)" "gimple" } } */ + #pragma omp master taskloop simd firstprivate (l02) lastprivate (l02) + for (int i = 0; i < 64; i++) + l02 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l03\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l03\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } *//* FIXME. */ + #pragma omp parallel for firstprivate (l03) lastprivate (l03) + for (int i = 0; i < 64; i++) + l03 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l04\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l04\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } */ + #pragma omp parallel for simd firstprivate (l04) lastprivate (l04) + for (int i = 0; i < 64; i++) + l04 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l05\\)" "gimple" } } */ + #pragma omp parallel master taskloop firstprivate (l05) lastprivate (l05) + for (int i = 0; i < 64; i++) + l05 = i; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd firstprivate (l06) lastprivate (l06) + for (int i = 0; i < 64; i++) + l06 = i; + /* FIXME: OpenMP 5.0/5.1 broken here, conceptually it should be shared on parallel and + firstprivate+lastprivate on sections, in GCC implementation we put firstprivate+lastprivate + on parallel for historic reasons, but OpenMP 5.0/5.1 mistakenly say firstprivate + should be on parallel and lastprivate on sections. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l07\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l07\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*firstprivate\\(l07\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*lastprivate\\(l07\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp section \[^\n\r]*firstprivate\\(l07\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp section \[^\n\r]*lastprivate\\(l07\\)" "gimple" } } */ + #pragma omp parallel sections firstprivate (l07) lastprivate (l07) + { + l07 = 1; + #pragma omp section + l07 = 2; + } + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l08" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l08\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } *//* FIXME. */ + #pragma omp target parallel for firstprivate (l08) lastprivate (l08) + for (int i = 0; i < 64; i++) + l08 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l09" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l09\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } */ + #pragma omp target parallel for simd firstprivate (l09) lastprivate (l09) + for (int i = 0; i < 64; i++) + l09 = i; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l10" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l10\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l10\\)" "gimple" } } */ + #pragma omp target simd firstprivate (l10) lastprivate (l10) + for (int i = 0; i < 64; i++) + l10 = i; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l11\\)" "gimple" } } */ + #pragma omp taskloop simd firstprivate (l11) lastprivate (l11) + for (int i = 0; i < 64; i++) + l11 = i; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-4.c b/gcc/testsuite/c-c++-common/gomp/pr99928-4.c new file mode 100644 index 0000000..c03afc4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-4.c @@ -0,0 +1,76 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int l00, l01, l05, l06, l07, l08; + +void +bar (void) +{ + int l02 = 0, l03 = 0, l04 = 0; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*firstprivate\\(l00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(l00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l00:1\\)" "gimple" } } */ + #pragma omp for simd linear (l00) + for (int i = 0; i < 64; i++) + l00++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l01:1\\)" "gimple" } } */ + #pragma omp master taskloop simd linear (l01) + for (int i = 0; i < 64; i++) + l01++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*linear\\(l02:1\\)" "gimple" } } */ + #pragma omp parallel for linear (l02) + for (int i = 0; i < 64; i++) + l02++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l03\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l03\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l03\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l03:1\\)" "gimple" } } */ + #pragma omp parallel for simd linear (l03) + for (int i = 0; i < 64; i++) + l03++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*firstprivate\\(l04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l04:1\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd linear (l04) + for (int i = 0; i < 64; i++) + l04++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l05" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l05\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(l05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*linear\\(l05:1\\)" "gimple" } } */ + #pragma omp target parallel for linear (l05) + for (int i = 0; i < 64; i++) + l05++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l06" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l06\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l06\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l06\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(l06\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l06:1\\)" "gimple" } } */ + #pragma omp target parallel for simd linear (l06) + for (int i = 0; i < 64; i++) + l06++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l07" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l07\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l07:1\\)" "gimple" } } */ + #pragma omp target simd linear (l07) + for (int i = 0; i < 64; i++) + l07++; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(l08:1\\)" "gimple" } } */ + #pragma omp taskloop simd linear (l08) + for (int i = 0; i < 64; i++) + l08++; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-5.c b/gcc/testsuite/c-c++-common/gomp/pr99928-5.c new file mode 100644 index 0000000..6eca9c8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-5.c @@ -0,0 +1,107 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int j00, j01, j02, j03, j04, j06, j07, j08, j09; +int j10; + +void +foo (void) +{ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j00:1\\)" "gimple" } } */ + #pragma omp distribute parallel for simd linear (j00) + for (j00 = 0; j00 < 64; j00++) + ; + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j01:1\\)" "gimple" } } */ + #pragma omp distribute simd linear (j01) + for (j01 = 0; j01 < 64; j01++) + ; +} + +void +bar (void) +{ + int j05, j11, j12; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j02:1\\)" "gimple" } } */ + #pragma omp for simd linear (j02) + for (j02 = 0; j02 < 64; j02++) + ; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j03\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j03:1\\)" "gimple" } } */ + #pragma omp master taskloop simd linear (j03) + for (j03 = 0; j03 < 64; j03++) + ; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j04\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j04\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j04:1\\)" "gimple" } } */ + #pragma omp parallel for simd linear (j04) + for (j04 = 0; j04 < 64; j04++) + ; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j05\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j05:1\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd linear (j05) + for (j05 = 0; j05 < 64; j05++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j06" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j06\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j06:1\\)" "gimple" } } */ + #pragma omp target parallel for simd linear (j06) + for (j06 = 0; j06 < 64; j06++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j07" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j07\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j07:1\\)" "gimple" } } */ + #pragma omp target simd linear (j07) + for (j07 = 0; j07 < 64; j07++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j08" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j08\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j08:1\\)" "gimple" } } */ + #pragma omp target teams distribute parallel for simd linear (j08) + for (j08 = 0; j08 < 64; j08++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j09" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j09\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j09:1\\)" "gimple" } } */ + #pragma omp target teams distribute simd linear (j09) + for (j09 = 0; j09 < 64; j09++) + ; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j10\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(j10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j10:1\\)" "gimple" } } */ + #pragma omp taskloop simd linear (j10) + for (j10 = 0; j10 < 64; j10++) + ; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j11:1\\)" "gimple" } } */ + #pragma omp teams distribute parallel for simd linear (j11) + for (j11 = 0; j11 < 64; j11++) + ; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j12:1\\)" "gimple" } } */ + #pragma omp teams distribute simd linear (j12) + for (j12 = 0; j12 < 64; j12++) + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-6.c b/gcc/testsuite/c-c++-common/gomp/pr99928-6.c new file mode 100644 index 0000000..9934047 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-6.c @@ -0,0 +1,107 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int j00, j01, j02, j03, j04, j06, j07, j08, j09; +int j10; + +void +foo (void) +{ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j00:1\\)" "gimple" } } */ + #pragma omp distribute parallel for simd + for (j00 = 0; j00 < 64; j00++) + ; + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j01:1\\)" "gimple" } } */ + #pragma omp distribute simd + for (j01 = 0; j01 < 64; j01++) + ; +} + +void +bar (void) +{ + int j05, j11, j12; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j02:1\\)" "gimple" } } */ + #pragma omp for simd + for (j02 = 0; j02 < 64; j02++) + ; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j03\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j03:1\\)" "gimple" } } */ + #pragma omp master taskloop simd + for (j03 = 0; j03 < 64; j03++) + ; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j04\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j04\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j04:1\\)" "gimple" } } */ + #pragma omp parallel for simd + for (j04 = 0; j04 < 64; j04++) + ; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j05\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j05:1\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd + for (j05 = 0; j05 < 64; j05++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j06" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j06\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j06:1\\)" "gimple" } } */ + #pragma omp target parallel for simd + for (j06 = 0; j06 < 64; j06++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j07" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j07\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j07:1\\)" "gimple" } } */ + #pragma omp target simd + for (j07 = 0; j07 < 64; j07++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j08" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j08\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j08:1\\)" "gimple" } } */ + #pragma omp target teams distribute parallel for simd + for (j08 = 0; j08 < 64; j08++) + ; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:j09" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j09\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j09:1\\)" "gimple" } } */ + #pragma omp target teams distribute simd + for (j09 = 0; j09 < 64; j09++) + ; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*shared\\(j10\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*lastprivate\\(j10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j10:1\\)" "gimple" } } */ + #pragma omp taskloop simd + for (j10 = 0; j10 < 64; j10++) + ; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j11:1\\)" "gimple" } } */ + #pragma omp teams distribute parallel for simd + for (j11 = 0; j11 < 64; j11++) + ; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(j12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*lastprivate\\(j12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j12:1\\)" "gimple" } } */ + #pragma omp teams distribute simd + for (j12 = 0; j12 < 64; j12++) + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-7.c b/gcc/testsuite/c-c++-common/gomp/pr99928-7.c new file mode 100644 index 0000000..5db1101 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-7.c @@ -0,0 +1,103 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +void +foo (void) +{ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j00:1\\)" "gimple" } } */ + #pragma omp distribute parallel for simd + for (int j00 = 0; j00 < 64; j00++) + ; + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*lastprivate\\(j01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j01:1\\)" "gimple" } } */ + #pragma omp distribute simd + for (int j01 = 0; j01 < 64; j01++) + ; +} + +void +bar (void) +{ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j02:1\\)" "gimple" } } */ + #pragma omp for simd + for (int j02 = 0; j02 < 64; j02++) + ; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp taskloop\[^\n\r]*lastprivate\\(j03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j03:1\\)" "gimple" } } */ + #pragma omp master taskloop simd + for (int j03 = 0; j03 < 64; j03++) + ; + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*lastprivate\\(j04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j04:1\\)" "gimple" } } */ + #pragma omp parallel for simd + for (int j04 = 0; j04 < 64; j04++) + ; + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*shared\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*lastprivate\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp taskloop\[^\n\r]*lastprivate\\(j05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j05:1\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd + for (int j05 = 0; j05 < 64; j05++) + ; + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*map\\(tofrom:j06" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*shared\\(j06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j06\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j06:1\\)" "gimple" } } */ + #pragma omp target parallel for simd + for (int j06 = 0; j06 < 64; j06++) + ; + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*map\\(tofrom:j07" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j07\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j07:1\\)" "gimple" } } */ + #pragma omp target simd + for (int j07 = 0; j07 < 64; j07++) + ; + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*map\\(tofrom:j08" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp teams\[^\n\r]*shared\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*shared\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j08:1\\)" "gimple" } } */ + #pragma omp target teams distribute parallel for simd + for (int j08 = 0; j08 < 64; j08++) + ; + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*map\\(tofrom:j09" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(j09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp teams\[^\n\r]*shared\\(j09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*lastprivate\\(j09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j09:1\\)" "gimple" } } */ + #pragma omp target teams distribute simd + for (int j09 = 0; j09 < 64; j09++) + ; + /* { dg-final { scan-tree-dump-not "omp taskloop\[^\n\r]*lastprivate\\(j10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j10:1\\)" "gimple" } } */ + #pragma omp taskloop simd + for (int j10 = 0; j10 < 64; j10++) + ; + /* { dg-final { scan-tree-dump-not "omp teams\[^\n\r]*shared\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*shared\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp parallel\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*lastprivate\\(j11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j11:1\\)" "gimple" } } */ + #pragma omp teams distribute parallel for simd + for (int j11 = 0; j11 < 64; j11++) + ; + /* { dg-final { scan-tree-dump-not "omp teams\[^\n\r]*shared\\(j12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*lastprivate\\(j12\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*linear\\(j12:1\\)" "gimple" } } */ + #pragma omp teams distribute simd + for (int j12 = 0; j12 < 64; j12++) + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-8.c b/gcc/testsuite/c-c++-common/gomp/pr99928-8.c new file mode 100644 index 0000000..755da3b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-8.c @@ -0,0 +1,219 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int r00, r01, r02, r03, r04, r05; +int r13, r14, r15, r16, r17, r18, r19; +int r20, r21, r22, r23, r24; + +void +foo (void) +{ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r00\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r00\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r00\\)" "gimple" } } *//* FIXME. */ + #pragma omp distribute parallel for reduction(+:r00) + for (int i = 0; i < 64; i++) + r00++; + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r01\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r01\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r01\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r01\\)" "gimple" } } */ + #pragma omp distribute parallel for simd reduction(+:r01) + for (int i = 0; i < 64; i++) + r01++; + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r02\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r02\\)" "gimple" } } */ + #pragma omp distribute simd reduction(+:r02) + for (int i = 0; i < 64; i++) + r02++; +} + +void +bar (void) +{ + int r06 = 0, r07 = 0, r08 = 0, r09 = 0; + int r10 = 0, r11 = 0, r12 = 0; + int r25 = 0, r26 = 0, r27 = 0, r28 = 0, r29 = 0; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:r03\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r03\\)" "gimple" } } */ + #pragma omp for simd reduction(+:r03) + for (int i = 0; i < 64; i++) + r03++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:r04\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:r04\\)" "gimple" } } */ + #pragma omp master taskloop reduction(+:r04) + for (int i = 0; i < 64; i++) + r04++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:r05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:r05\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r05\\)" "gimple" } } */ + #pragma omp master taskloop simd reduction(+:r05) + for (int i = 0; i < 64; i++) + r05++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r06\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r06\\)" "gimple" } } *//* FIXME. */ + #pragma omp parallel for reduction(+:r06) + for (int i = 0; i < 64; i++) + r06++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r07\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r07\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r07\\)" "gimple" } } */ + #pragma omp parallel for simd reduction(+:r07) + for (int i = 0; i < 64; i++) + r07++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:r08\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r08\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp parallel loop reduction(+:r08) + for (int i = 0; i < 64; i++) + r08++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r09\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:r09\\)" "gimple" } } */ + #pragma omp parallel master reduction(+:r09) + r09++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:r10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:r10\\)" "gimple" } } */ + #pragma omp parallel master taskloop reduction(+:r10) + for (int i = 0; i < 64; i++) + r10++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:r11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:r11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r11\\)" "gimple" } } */ + #pragma omp parallel master taskloop simd reduction(+:r11) + for (int i = 0; i < 64; i++) + r11++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r12\\)" "gimple" } } *//* FIXME: This should be on sections instead. */ + /* { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*reduction\\(\\+:r12\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp section \[^\n\r]*reduction\\(\\+:r12\\)" "gimple" } } */ + #pragma omp parallel sections reduction(+:r12) + { + r12++; + #pragma omp section + r12++; + } + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r13" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r13\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r13\\)" "gimple" } } */ + #pragma omp target parallel reduction(+:r13) + r13++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r14" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r14\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r14\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r14\\)" "gimple" } } *//* FIXME. */ + #pragma omp target parallel for reduction(+:r14) + for (int i = 0; i < 64; i++) + r14++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r15" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r15\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r15\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r15\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r15\\)" "gimple" } } */ + #pragma omp target parallel for simd reduction(+:r15) + for (int i = 0; i < 64; i++) + r15++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r16" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r16\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:r16\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r16\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target parallel loop reduction(+:r16) + for (int i = 0; i < 64; i++) + r16++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r17" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r17\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r17\\)" "gimple" } } */ + #pragma omp target teams reduction(+:r17) + r17++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r18" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r18\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r18\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r18\\)" "gimple" } } */ + #pragma omp target teams distribute reduction(+:r18) + for (int i = 0; i < 64; i++) + r18++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r19" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r19\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r19\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r19\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r19\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r19\\)" "gimple" } } *//* FIXME. */ + #pragma omp target teams distribute parallel for reduction(+:r19) + for (int i = 0; i < 64; i++) + r19++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r20" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r20\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r20\\)" "gimple" } } */ + #pragma omp target teams distribute parallel for simd reduction(+:r20) + for (int i = 0; i < 64; i++) + r20++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r21" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r21\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r21\\)" "gimple" } } */ + #pragma omp target teams distribute simd reduction(+:r21) + for (int i = 0; i < 64; i++) + r21++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r22" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r22\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(r22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*reduction\\(\\+:r22\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r22\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:r22\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r22\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target teams loop reduction(+:r22) + for (int i = 0; i < 64; i++) + r22++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r23" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r23\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r23\\)" "gimple" } } */ + #pragma omp target simd reduction(+:r23) + for (int i = 0; i < 64; i++) + r23++; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:r24\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r24\\)" "gimple" } } */ + #pragma omp taskloop simd reduction(+:r24) + for (int i = 0; i < 64; i++) + r24++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r25\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r25\\)" "gimple" } } */ + #pragma omp teams distribute reduction(+:r25) + for (int i = 0; i < 64; i++) + r25++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r26\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r26\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r26\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r26\\)" "gimple" } } *//* FIXME. */ + #pragma omp teams distribute parallel for reduction(+:r26) + for (int i = 0; i < 64; i++) + r26++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r27\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r27\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:r27\\)" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:r27\\)" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r27\\)" "gimple" } } */ + #pragma omp teams distribute parallel for simd reduction(+:r27) + for (int i = 0; i < 64; i++) + r27++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:r28\\)" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:r28\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r28\\)" "gimple" } } */ + #pragma omp teams distribute simd reduction(+:r28) + for (int i = 0; i < 64; i++) + r28++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(r29\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*reduction\\(\\+:r29\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r29\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:r29\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:r29\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp teams loop reduction(+:r29) + for (int i = 0; i < 64; i++) + r29++; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-9.c b/gcc/testsuite/c-c++-common/gomp/pr99928-9.c new file mode 100644 index 0000000..a766b72 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr99928-9.c @@ -0,0 +1,219 @@ +/* PR middle-end/99928 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +int r00[4], r01[4], r02[4], r03[4], r04[4], r05[4]; +int r13[4], r14[4], r15[4], r16[4], r17[4], r18[4], r19[4]; +int r20[4], r21[4], r22[4], r23[4], r24[4]; + +void +foo (void) +{ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r00 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r00 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r00 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp distribute parallel for reduction(+:r00[1:2]) + for (int i = 0; i < 64; i++) + r00[1]++; + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r01 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r01 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r01 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r01 \\+ 4" "gimple" } } */ + #pragma omp distribute parallel for simd reduction(+:r01[1:2]) + for (int i = 0; i < 64; i++) + r01[1]++; + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r02 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r02 \\+ 4" "gimple" } } */ + #pragma omp distribute simd reduction(+:r02[1:2]) + for (int i = 0; i < 64; i++) + r02[1]++; +} + +void +bar (void) +{ + int r06[4] = {}, r07[4] = {}, r08[4] = {}, r09[4] = {}; + int r10[4] = {}, r11[4] = {}, r12[4] = {}; + int r25[4] = {}, r26[4] = {}, r27[4] = {}, r28[4] = {}, r29[4] = {}; + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r03 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r03 \\+ 4" "gimple" } } */ + #pragma omp for simd reduction(+:r03[1:2]) + for (int i = 0; i < 64; i++) + r03[1]++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r04 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r04 \\+ 4" "gimple" } } */ + #pragma omp master taskloop reduction(+:r04[1:2]) + for (int i = 0; i < 64; i++) + r04[1]++; + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r05 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r05 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r05 \\+ 4" "gimple" } } */ + #pragma omp master taskloop simd reduction(+:r05[1:2]) + for (int i = 0; i < 64; i++) + r05[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r06 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r06 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp parallel for reduction(+:r06[1:2]) + for (int i = 0; i < 64; i++) + r06[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r07 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r07 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r07 \\+ 4" "gimple" } } */ + #pragma omp parallel for simd reduction(+:r07[1:2]) + for (int i = 0; i < 64; i++) + r07[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r08\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r08 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r08 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp parallel loop reduction(+:r08[1:2]) + for (int i = 0; i < 64; i++) + r08[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r09 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r09 \\+ 4" "gimple" } } */ + #pragma omp parallel master reduction(+:r09[1:2]) + r09[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r10\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r10 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r10 \\+ 4" "gimple" } } */ + #pragma omp parallel master taskloop reduction(+:r10[1:2]) + for (int i = 0; i < 64; i++) + r10[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r11\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp master\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r11 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r11 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r11 \\+ 4" "gimple" } } */ + #pragma omp parallel master taskloop simd reduction(+:r11[1:2]) + for (int i = 0; i < 64; i++) + r11[1]++; + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r12 \\+ 4" "gimple" } } *//* FIXME: This should be on sections instead. */ + /* { dg-final { scan-tree-dump-not "omp sections\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r12 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump-not "omp section \[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r12 \\+ 4" "gimple" } } */ + #pragma omp parallel sections reduction(+:r12[1:2]) + { + r12[1]++; + #pragma omp section + r12[1]++; + } + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r13\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r13\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r13 \\+ 4" "gimple" } } */ + #pragma omp target parallel reduction(+:r13[1:2]) + r13[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r14\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r14" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r14 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r14 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp target parallel for reduction(+:r14[1:2]) + for (int i = 0; i < 64; i++) + r14[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r15\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r15\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r15 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r15 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r15 \\+ 4" "gimple" } } */ + #pragma omp target parallel for simd reduction(+:r15[1:2]) + for (int i = 0; i < 64; i++) + r15[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r16\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r16\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r16 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r16 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target parallel loop reduction(+:r16[1:2]) + for (int i = 0; i < 64; i++) + r16[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r17\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r17\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r17 \\+ 4" "gimple" } } */ + #pragma omp target teams reduction(+:r17[1:2]) + r17[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r18\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r18\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r18 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r18 \\+ 4" "gimple" } } */ + #pragma omp target teams distribute reduction(+:r18[1:2]) + for (int i = 0; i < 64; i++) + r18[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r19\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r19\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r19 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r19 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r19 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r19 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp target teams distribute parallel for reduction(+:r19[1:2]) + for (int i = 0; i < 64; i++) + r19[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r20\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r20\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r20 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r20 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r20 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r20 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r20 \\+ 4" "gimple" } } */ + #pragma omp target teams distribute parallel for simd reduction(+:r20[1:2]) + for (int i = 0; i < 64; i++) + r20[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r21\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r21\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r21 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r21 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r21 \\+ 4" "gimple" } } */ + #pragma omp target teams distribute simd reduction(+:r21[1:2]) + for (int i = 0; i < 64; i++) + r21[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r22\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(r22\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r22 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r22\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r22 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r22 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp target teams loop reduction(+:r22[1:2]) + for (int i = 0; i < 64; i++) + r22[1]++; + /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:r23\\\[1\\\] \\\[len: 8\\\]" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(r23\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r23 \\+ 4" "gimple" } } */ + #pragma omp target simd reduction(+:r23[1:2]) + for (int i = 0; i < 64; i++) + r23[1]++; + /* { dg-final { scan-tree-dump "omp taskloop\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r24 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r24 \\+ 4" "gimple" } } */ + #pragma omp taskloop simd reduction(+:r24[1:2]) + for (int i = 0; i < 64; i++) + r24[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r25 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r25 \\+ 4" "gimple" } } */ + #pragma omp teams distribute reduction(+:r25[1:2]) + for (int i = 0; i < 64; i++) + r25[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r26 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r26 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r26 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r26 \\+ 4" "gimple" } } *//* FIXME. */ + #pragma omp teams distribute parallel for reduction(+:r26[1:2]) + for (int i = 0; i < 64; i++) + r26[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r27 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r27 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r27 \\+ 4" "gimple" } } *//* FIXME: This should be on for instead. */ + /* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r27 \\+ 4" "gimple" } } *//* FIXME. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r27 \\+ 4" "gimple" } } */ + #pragma omp teams distribute parallel for simd reduction(+:r27[1:2]) + for (int i = 0; i < 64; i++) + r27[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r28 \\+ 4" "gimple" { xfail *-*-* } } } */ + /* { dg-final { scan-tree-dump-not "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r28 \\+ 4" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r28 \\+ 4" "gimple" } } */ + #pragma omp teams distribute simd reduction(+:r28[1:2]) + for (int i = 0; i < 64; i++) + r28[1]++; + /* { dg-final { scan-tree-dump "omp teams\[^\n\r]*shared\\(r29\\)" "gimple" } } */ + /* { dg-final { scan-tree-dump "omp distribute\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r29 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*shared\\(r29\\)" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp for\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r29 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + /* { dg-final { scan-tree-dump "omp simd\[^\n\r]*reduction\\(\\+:MEM\[^\n\r]*&r29 \\+ 4" "gimple" } } *//* NOTE: This is implementation detail. */ + #pragma omp teams loop reduction(+:r29[1:2]) + for (int i = 0; i < 64; i++) + r29[1]++; +} -- cgit v1.1 From 957c437363f139313b2c0b2c93ca985df1d98ad2 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 13 May 2021 10:38:09 -0600 Subject: PR c/100550 - ICE: in fold_convert_loc with function call VLA argument gcc/c/ChangeLog: PR c/100550 * c-decl.c (get_parm_array_spec): Avoid erroneous VLA bounds. gcc/testsuite/ChangeLog: PR c/100550 * gcc.dg/Wvla-parameter-9.c: New test. --- gcc/c/c-decl.c | 3 +++ gcc/testsuite/gcc.dg/Wvla-parameter-9.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/Wvla-parameter-9.c (limited to 'gcc') diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 3ea4708..53b2b5b 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -5856,6 +5856,9 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs) spec += buf; break; } + else if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts))) + /* Avoid invalid NELTS. */ + return attrs; /* Each variable VLA bound is represented by a dollar sign. */ spec += "$"; diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-9.c b/gcc/testsuite/gcc.dg/Wvla-parameter-9.c new file mode 100644 index 0000000..6c8987a --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-9.c @@ -0,0 +1,30 @@ +/* PR c/100550 - ICE: in fold_convert_loc with function call VLA argument + { dg-do compile } + { dg-options "-Wall" } */ + +struct S { int i; }; + +extern void v; +extern void *pv; +extern struct S s; +void vf (void); + +/* Verify that a function redeclaration with an invalid VLA doesn't ICE. */ + +void f0 (int[]); +void f0 (int[undeclared]); // { dg-error "undeclared" } + +void f1 (int[]); +void f1 (int[-1]); // { dg-error "size" } + +void f2 (int[]); +void f2 (int[v]); // { dg-error "size" } + +void f3 (int[]); +void f3 (int b[s]); // { dg-error "size" } + +void f4 (int[]); +void f4 (int c[pv]); // { dg-error "size" } + +void f5 (int[]); +void f5 (int d[vf ()]); // { dg-error "size" } -- cgit v1.1 From 1f152f2996b7b4f7ccf8181f26dfd3acbea836f0 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 13 May 2021 11:05:15 +0200 Subject: Remove unused variable. Addresses the following clang warning: gcc/tree-ssa-dom.c:652:33: warning: private field 'm_simplifier' is not used [-Wunused-private-field] gcc/ChangeLog: * tree-ssa-dom.c: Remove m_simplifier. --- gcc/tree-ssa-dom.c | 1 - 1 file changed, 1 deletion(-) (limited to 'gcc') diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 11b86b2..075b1cc 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -649,7 +649,6 @@ private: void test_for_singularity (gimple *, avail_exprs_stack *); - dom_jump_threader_simplifier *m_simplifier; jump_threader *m_threader; evrp_range_analyzer *m_evrp_range_analyzer; }; -- cgit v1.1 From 9feb5822b713c6a12cb290ba0406ba2362d4c09c Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 13 May 2021 13:59:59 +0200 Subject: attributes: target_clone expects a string argument PR middle-end/100504 gcc/c-family/ChangeLog: * c-attribs.c (handle_target_clones_attribute): Expect a string argument to target_clone argument. gcc/testsuite/ChangeLog: * gcc.target/i386/pr100504.c: New test. --- gcc/c-family/c-attribs.c | 7 ++++++- gcc/testsuite/gcc.target/i386/pr100504.c | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr100504.c (limited to 'gcc') diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index c1f652d..f54388e 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -5288,7 +5288,12 @@ handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args), /* Ensure we have a function type. */ if (TREE_CODE (*node) == FUNCTION_DECL) { - if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node))) + if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("%qE attribute argument not a string constant", name); + *no_add_attrs = true; + } + else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node))) { warning (OPT_Wattributes, "%qE attribute ignored due to conflict " "with %qs attribute", name, "always_inline"); diff --git a/gcc/testsuite/gcc.target/i386/pr100504.c b/gcc/testsuite/gcc.target/i386/pr100504.c new file mode 100644 index 0000000..2910dfb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100504.c @@ -0,0 +1,7 @@ +/* PR middle-end/100504 */ +/* { dg-do compile } */ + +__attribute__((target_clones(0))) +foo() +{ /* { dg-error ".target_clones. attribute argument not a string constant" } */ +} -- cgit v1.1 From e554887df0934325464fd3e811022ee048328bb5 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 13 May 2021 11:32:33 -0600 Subject: Fix compilation error in ILP32. gcc/testsuite/ChangeLog: * g++.dg/pr100574.C: Use size_t as operator new argument type. --- gcc/testsuite/g++.dg/pr100574.C | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 gcc/testsuite/g++.dg/pr100574.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/pr100574.C b/gcc/testsuite/g++.dg/pr100574.C new file mode 100644 index 0000000..42ba040 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr100574.C @@ -0,0 +1,64 @@ +/* PR middle-end/100574 - ICE: in size_remaining, at builtins.c:413 with + -O3 -ftracer -fno-tree-dominator-opts -fno-tree-fre + { dg-do compile { target c++11 } } + { dg-options "-O3 -ftracer -fno-tree-dominator-opts -fno-tree-fre" } */ + +void *operator new (__SIZE_TYPE__, void *__p) { return __p; } + +template struct allocator_traits; +template class allocator {}; +template struct allocator_traits > +{ + using allocator_type = allocator<_Tp>; + using pointer = _Tp *; + using size_type = long; + template using rebind_alloc = allocator<_Up>; + static pointer allocate(allocator_type, size_type); + template static void construct(_Up __p) { new (__p) _Up(); } +}; + +struct __alloc_traits : allocator_traits> { + struct rebind { + typedef rebind_alloc other; + }; +}; + +struct _Vector_base { + struct : __alloc_traits::rebind::other { + } _M_impl; + long _M_allocate___n; +}; + +template class vector : _Vector_base { + long max_size(); +public: + void push_back() { _M_realloc_insert(); } + template void _M_realloc_insert(); +}; + +template +template +void vector<_Tp, _Alloc>::_M_realloc_insert() { + __alloc_traits::pointer __trans_tmp_5; + long __len(__len || max_size()), __elems_before; + __trans_tmp_5 = _M_allocate___n + ? __alloc_traits::allocate(_M_impl, _M_allocate___n) + : __alloc_traits::pointer(); + __alloc_traits::construct(__trans_tmp_5 + __elems_before); +} + +enum { MIDIST_PITCHBEND }; +struct DataBlock { + vector data; +}; + +char ReadTrackChunk_status; + +void ReadTrackChunk() +{ + DataBlock block; + while (!0) + switch (ReadTrackChunk_status) + case MIDIST_PITCHBEND: + block.data.push_back(); +} -- cgit v1.1 From ca9bb74a5f856ccdceb4797f18b0a4ac8f49d069 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Thu, 13 May 2021 23:26:32 +0200 Subject: tree-sra: Avoid refreshing into const base decls (PR 100453) When SRA transforms an assignment where the RHS is an aggregate decl that it creates replacements for, the (least efficient) fallback method of dealing with them is to store all the replacements back into the original decl and then let the original assignment takes itc sourse. That of course should not need to be done for TREE_READONLY bases which cannot change contents. The SRA code handled this situation in one of two necessary places but only for DECL_IN_CONSTANT_POOL const decls, this patch modifies both to check TREE_READONLY. gcc/ChangeLog: 2021-05-12 Martin Jambor PR tree-optimization/100453 * tree-sra.c (sra_modify_assign): All const base accesses do not need refreshing, not just those from decl_pool. (sra_modify_assign): Do not refresh into a const base decl. gcc/testsuite/ChangeLog: 2021-05-12 Martin Jambor PR tree-optimization/100453 * gcc.dg/tree-ssa/pr100453.c: New test. --- gcc/testsuite/gcc.dg/tree-ssa/pr100453.c | 18 ++++++++++++++++++ gcc/tree-sra.c | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr100453.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr100453.c b/gcc/testsuite/gcc.dg/tree-ssa/pr100453.c new file mode 100644 index 0000000..0cf0ad2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr100453.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +struct a { + int b : 4; +} d; +static int c, e; +static const struct a f; +static void g(const struct a h) { + for (; c < 1; c++) + d = h; + e = h.b; + c = h.b; +} +int main() { + g(f); + return 0; +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 8dfc923..186cd62 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -4244,7 +4244,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) || stmt_ends_bb_p (stmt)) { /* No need to copy into a constant-pool, it comes pre-initialized. */ - if (access_has_children_p (racc) && !constant_decl_p (racc->base)) + if (access_has_children_p (racc) && !TREE_READONLY (racc->base)) generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0, gsi, false, false, loc); if (access_has_children_p (lacc)) @@ -4333,7 +4333,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) } /* Restore the aggregate RHS from its components so the prevailing aggregate copy does the right thing. */ - if (access_has_children_p (racc)) + if (access_has_children_p (racc) && !TREE_READONLY (racc->base)) generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0, gsi, false, false, loc); /* Re-load the components of the aggregate copy destination. -- cgit v1.1 From 2efe245bb88bf4574e322ef7e6d2df83d9e13237 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 13 May 2021 16:05:50 -0600 Subject: Avoid -Wuninitialized false negatives with sanitization and VLAs. Resolves: PR tree-optimization/93100 - gcc -fsanitize=address inhibits -Wuninitialized PR middle-end/98583 - missing -Wuninitialized reading from a second VLA in its own block gcc/ChangeLog: PR tree-optimization/93100 PR middle-end/98583 * tree-ssa-uninit.c (check_defs): Exclude intrinsic functions that don't modify referenced objects. gcc/testsuite/ChangeLog: PR tree-optimization/93100 PR middle-end/98583 * g++.dg/warn/uninit-pr93100.C: New test. * gcc.dg/uninit-pr93100.c: New test. * gcc.dg/uninit-pr98583.c: New test. --- gcc/testsuite/g++.dg/warn/uninit-pr93100.C | 59 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/uninit-pr93100.c | 74 ++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/uninit-pr98583.c | 31 +++++++++++++ gcc/tree-ssa-uninit.c | 11 +++++ 4 files changed, 175 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/uninit-pr93100.C create mode 100644 gcc/testsuite/gcc.dg/uninit-pr93100.c create mode 100644 gcc/testsuite/gcc.dg/uninit-pr98583.c (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C new file mode 100644 index 0000000..c9cd3ef --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C @@ -0,0 +1,59 @@ +/* PR tree-optimization/98508 - Sanitizer disable -Wall and -Wextra + { dg-do compile } + { dg-options "-O0 -Wall -fsanitize=address" } */ + +struct S +{ + int a; +}; + +void warn_init_self_O0 () +{ + S s = S (s); // { dg-warning "\\\[-Wuninitialized" } + (void)&s; +} + + +void warn_init_self_use_O0 () +{ + S s = S (s); // { dg-warning "\\\[-Wuninitialized" } + + void sink (void*); + sink (&s); +} + + +#pragma GCC optimize ("1") + +void warn_init_self_O1 () +{ + S s = S (s); // { dg-warning "\\\[-Wuninitialized" } + (void)&s; +} + + +void warn_init_self_use_O1 () +{ + S s = S (s); // { dg-warning "\\\[-Wuninitialized" } + + void sink (void*); + sink (&s); +} + + +#pragma GCC optimize ("2") + +void warn_init_self_O2 () +{ + S s = S (s); // { dg-warning "\\\[-Wuninitialized" } + (void)&s; +} + + +void warn_init_self_use_O2 () +{ + S s = S (s); // { dg-warning "\\\[-Wuninitialized" } + + void sink (void*); + sink (&s); +} diff --git a/gcc/testsuite/gcc.dg/uninit-pr93100.c b/gcc/testsuite/gcc.dg/uninit-pr93100.c new file mode 100644 index 0000000..61b7e43 --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pr93100.c @@ -0,0 +1,74 @@ +/* PR tree-optimization/93100 - gcc -fsanitize=address inhibits -Wuninitialized + { dg-do compile } + { dg-options "-Wall -fsanitize=address" } */ + +struct A +{ + _Bool b; + int i; +}; + +void warn_A_b_O0 (void) +{ + struct A a; + + if (a.b) // { dg-warning "\\\[-Wuninitialized" } + { + (void)&a; + } +} + +void warn_A_i_O0 (void) +{ + struct A a; + + if (a.i) // { dg-warning "\\\[-Wuninitialized" } + { + (void)&a; + } +} + +#pragma GCC optimize ("1") + +void warn_A_b_O1 (void) +{ + struct A a; + + if (a.b) // { dg-warning "\\\[-Wuninitialized" } + { + (void)&a; + } +} + +void warn_A_i_O1 (void) +{ + struct A a; + + if (a.i) // { dg-warning "\\\[-Wuninitialized" } + { + (void)&a; + } +} + + +#pragma GCC optimize ("2") + +void warn_A_b_O2 (void) +{ + struct A a; + + if (a.b) // { dg-warning "\\\[-Wuninitialized" } + { + (void)&a; + } +} + +void warn_A_i_O2 (void) +{ + struct A a; + + if (a.i) // { dg-warning "\\\[-Wuninitialized" } + { + (void)&a; + } +} diff --git a/gcc/testsuite/gcc.dg/uninit-pr98583.c b/gcc/testsuite/gcc.dg/uninit-pr98583.c new file mode 100644 index 0000000..638b029 --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pr98583.c @@ -0,0 +1,31 @@ +/* PR middle-end/98583 - missing -Wuninitialized reading from a second VLA + in its own block + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +void f (int*); +void g (int); + +void h1 (int n) +{ + int a[n]; + f (a); + + int b[n]; + g (b[1]); // { dg-warning "\\\[-Wuninitialized" } +} + +void h2 (int n, int i, int j) +{ + if (i) + { + int a[n]; + f (a); + } + + if (j) + { + int b[n]; + g (b[1]); // { dg-warning "\\\[-Wmaybe-uninitialized" } + } +} diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 0800f59..f55ce19 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -209,6 +209,16 @@ check_defs (ao_ref *ref, tree vdef, void *data_) { check_defs_data *data = (check_defs_data *)data_; gimple *def_stmt = SSA_NAME_DEF_STMT (vdef); + + /* The ASAN_MARK intrinsic doesn't modify the variable. */ + if (is_gimple_call (def_stmt) + && gimple_call_internal_p (def_stmt, IFN_ASAN_MARK)) + return false; + + /* End of VLA scope is not a kill. */ + if (gimple_call_builtin_p (def_stmt, BUILT_IN_STACK_RESTORE)) + return false; + /* If this is a clobber then if it is not a kill walk past it. */ if (gimple_clobber_p (def_stmt)) { @@ -216,6 +226,7 @@ check_defs (ao_ref *ref, tree vdef, void *data_) return true; return false; } + /* Found a may-def on this path. */ data->found_may_defs = true; return true; -- cgit v1.1 From 5380e3c137b2bb63acd789cd09d01a4edc0a01c3 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 13 May 2021 16:20:45 -0600 Subject: PR middle-end/100574 - ICE in size_remaining, at builtins.c gcc/ChangeLog: PR middle-end/100574 * builtins.c (access_ref::get_ref): Improve detection of PHIs with all null arguments. --- gcc/builtins.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/builtins.c b/gcc/builtins.c index 2f0efae..e1b2848 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -362,15 +362,6 @@ access_ref::get_ref (vec *all_refs, same_ref.offrng[1] = phi_arg_ref.offrng[1]; } - if (phi_ref.sizrng[0] < 0) - { - /* Fail if none of the PHI's arguments resulted in updating PHI_REF - (perhaps because they have all been already visited by prior - recursive calls). */ - psnlim->leave_phi (ref); - return NULL_TREE; - } - if (!same_ref.ref && same_ref.offrng[0] != 0) /* Clear BASE0 if not all the arguments refer to the same object and if not all their offsets are zero-based. This allows the final @@ -390,6 +381,15 @@ access_ref::get_ref (vec *all_refs, phi_ref.parmarray = parmarray; } + if (phi_ref.sizrng[0] < 0) + { + /* Fail if none of the PHI's arguments resulted in updating PHI_REF + (perhaps because they have all been already visited by prior + recursive calls). */ + psnlim->leave_phi (ref); + return NULL_TREE; + } + /* Avoid changing *THIS. */ if (pref && pref != this) *pref = phi_ref; -- cgit v1.1 From f9af11c7f156bede9aa28410073acbab7b0fa0fe Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 14 May 2021 00:16:30 +0000 Subject: Daily bump. --- gcc/ChangeLog | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/c-family/ChangeLog | 6 +++ gcc/c/ChangeLog | 5 +++ gcc/testsuite/ChangeLog | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 204 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e39086..2215bec 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,102 @@ +2021-05-13 Martin Sebor + + PR middle-end/100574 + * builtins.c (access_ref::get_ref): Improve detection of PHIs with + all null arguments. + +2021-05-13 Martin Sebor + + PR tree-optimization/93100 + PR middle-end/98583 + * tree-ssa-uninit.c (check_defs): Exclude intrinsic functions that + don't modify referenced objects. + +2021-05-13 Martin Jambor + + PR tree-optimization/100453 + * tree-sra.c (sra_modify_assign): All const base accesses do not + need refreshing, not just those from decl_pool. + (sra_modify_assign): Do not refresh into a const base decl. + +2021-05-13 Martin Liska + + * tree-ssa-dom.c: Remove m_simplifier. + +2021-05-13 Richard Earnshaw + + PR target/100563 + * config/arm/arm.c (arm_canonicalize_comparison): Correctly + canonicalize DImode inequality comparisons against the + maximum integral value. + +2021-05-13 Jakub Jelinek + + PR tree-optimization/98856 + * config/i386/i386.c (ix86_shift_rotate_cost): Add CODE argument. + Expect V2DI and V4DI arithmetic right shifts to be emulated. + (ix86_rtx_costs, ix86_add_stmt_cost): Adjust ix86_shift_rotate_cost + caller. + * config/i386/i386-expand.c (expand_vec_perm_2perm_interleave, + expand_vec_perm_2perm_pblendv): New functions. + (ix86_expand_vec_perm_const_1): Use them. + * config/i386/sse.md (ashr3): Rename to ... + (ashr3): ... this. + (ashr3): New define_expand with VI248_AVX512BW iterator. + (ashrv4di3): New define_expand. + (ashrv2di3): Change condition to TARGET_SSE2, handle !TARGET_XOP + and !TARGET_AVX512VL expansion. + +2021-05-13 Uroš Bizjak + + PR target/100581 + * config/i386/i386-expand.c (ix86_expand_sse_movcc): Force mode + sizes < 16 to a register when constructing vpcmov pattern. + * config/i386/mmx.md (*xop_pcmov_): Use MMXMODE124 mode. + +2021-05-13 marxin + + * gcov-io.c (gcov_write_block): Remove. + (gcov_write_words): Likewise. + (gcov_read_words): Re-implement using gcov_read_bytes. + (gcov_allocate): Remove. + (GCOV_BLOCK_SIZE): Likewise. + (struct gcov_var): Remove most of the fields. + (gcov_position): Implement with ftell. + (gcov_rewrite): Remove setting of start and offset fields. + (from_file): Re-format. + (gcov_open): Remove setbuf call. It should not be needed. + (gcov_close): Remove internal buffer handling. + (gcov_magic): Use __builtin_bswap32. + (gcov_write_counter): Use directly gcov_write_unsigned. + (gcov_write_string): Use direct fwrite and do not round + to 4 bytes. + (gcov_seek): Use directly fseek. + (gcov_write_tag): Use gcov_write_unsigned directly. + (gcov_write_length): Likewise. + (gcov_write_tag_length): Likewise. + (gcov_read_bytes): Use directly fread. + (gcov_read_unsigned): Use gcov_read_words. + (gcov_read_counter): Likewise. + (gcov_read_string): Use gcov_read_bytes. + * gcov-io.h (GCOV_WORD_SIZE): Adjust to reflect + that size is not in bytes, but words (4B). + (GCOV_TAG_FUNCTION_LENGTH): Likewise. + (GCOV_TAG_ARCS_LENGTH): Likewise. + (GCOV_TAG_ARCS_NUM): Likewise. + (GCOV_TAG_COUNTER_LENGTH): Likewise. + (GCOV_TAG_COUNTER_NUM): Likewise. + (GCOV_TAG_SUMMARY_LENGTH): Likewise. + +2021-05-13 liuhongt + + PR target/94680 + * config/i386/sse.md (ssedoublevecmode): Add attribute for + V64QI/V32HI/V16SI/V4DI. + (ssehalfvecmode): Add attribute for V2DI/V2DF. + (*vec_concatv4si_0): Extend to VI124_128. + (*vec_concat_0): New pre-reload splitter. + * config/i386/predicates.md (movq_parallel): New predicate. + 2021-05-13 Alexandre Oliva * targhooks.c (default_zero_call_used_regs): Retry using diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 92e74b6..552c3b2 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210513 +20210514 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 3860677..d33ad4a 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2021-05-13 Martin Liska + + PR middle-end/100504 + * c-attribs.c (handle_target_clones_attribute): Expect a string + argument to target_clone argument. + 2021-05-11 Joseph Myers * c-lex.c (interpret_float): Handle digit separators for C2X. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 0690d93..a75832b 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2021-05-13 Martin Sebor + + PR c/100550 + * c-decl.c (get_parm_array_spec): Avoid erroneous VLA bounds. + 2021-05-12 Marcel Vollweiler * c-parser.c (c_parser_omp_clause_map): Support map-type-modifier diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 82ef74c..9dfab7b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,96 @@ +2021-05-13 Martin Sebor + + PR tree-optimization/93100 + PR middle-end/98583 + * g++.dg/warn/uninit-pr93100.C: New test. + * gcc.dg/uninit-pr93100.c: New test. + * gcc.dg/uninit-pr98583.c: New test. + +2021-05-13 Martin Jambor + + PR tree-optimization/100453 + * gcc.dg/tree-ssa/pr100453.c: New test. + +2021-05-13 Martin Sebor + + * g++.dg/pr100574.C: Use size_t as operator new argument type. + +2021-05-13 Martin Liska + + PR middle-end/100504 + * gcc.target/i386/pr100504.c: New test. + +2021-05-13 Martin Sebor + + PR c/100550 + * gcc.dg/Wvla-parameter-9.c: New test. + +2021-05-13 Jakub Jelinek + + PR middle-end/99928 + * c-c++-common/gomp/pr99928-1.c: New test. + * c-c++-common/gomp/pr99928-2.c: New test. + * c-c++-common/gomp/pr99928-3.c: New test. + * c-c++-common/gomp/pr99928-4.c: New test. + * c-c++-common/gomp/pr99928-5.c: New test. + * c-c++-common/gomp/pr99928-6.c: New test. + * c-c++-common/gomp/pr99928-7.c: New test. + * c-c++-common/gomp/pr99928-8.c: New test. + * c-c++-common/gomp/pr99928-9.c: New test. + * c-c++-common/gomp/pr99928-10.c: New test. + * c-c++-common/gomp/pr99928-11.c: New test. + +2021-05-13 Richard Earnshaw + + PR target/100563 + * gcc.dg/pr100563.c (dg-options): Add -wno-pointer-to-int-cast. + +2021-05-13 Richard Earnshaw + + * gcc.dg/pr100563.c: New test. + +2021-05-13 Jakub Jelinek + + PR tree-optimization/98856 + * gcc.target/i386/sse2-psraq-1.c: New test. + * gcc.target/i386/sse4_2-psraq-1.c: New test. + * gcc.target/i386/avx-psraq-1.c: New test. + * gcc.target/i386/avx2-psraq-1.c: New test. + * gcc.target/i386/avx-pr82370.c: Adjust expected number of vpsrad + instructions. + * gcc.target/i386/avx2-pr82370.c: Likewise. + * gcc.target/i386/avx512f-pr82370.c: Likewise. + * gcc.target/i386/avx512bw-pr82370.c: Likewise. + * gcc.dg/torture/vshuf-4.inc: Add two further permutations. + * gcc.dg/torture/vshuf-8.inc: Likewise. + +2021-05-13 Uroš Bizjak + + PR target/100581 + * g++.target/i386/pr100581.C: New test. + +2021-05-13 Eric Botcazou + + PR testsuite/100569 + * gnat.dg/lto21.adb: Prune new LTO warning. + +2021-05-13 Martin Liska + + PR testsuite/100569 + * gcc.dg/atomic/c11-atomic-exec-2.c: Prune new LTO warning. + * gcc.dg/torture/pr94947-1.c: Likewise. + +2021-05-13 liuhongt + + * gcc.target/i386/avx-pr94680.c: Fix typo in testcase. + +2021-05-13 liuhongt + + PR target/94680 + * gcc.target/i386/avx-pr94680.c: New test. + * gcc.target/i386/avx512f-pr94680.c: New test. + * gcc.target/i386/sse2-pr94680.c: New test. + 2021-05-12 Martin Sebor PR middle-end/100571 -- cgit v1.1 From 149061188c7c6ddf27663c8c00b7574fc8d0fd23 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 29 Apr 2021 21:38:14 -0400 Subject: c++: Check attributes on friend declarations [PR99032] This patch implements [dcl.attr.grammar]/5: "If an attribute-specifier-seq appertains to a friend declaration ([class.friend]), that declaration shall be a definition." This restriction applies to C++11-style attributes as well as GNU attributes with the exception that we allow GNU attributes that require a type, such as vector_size to continue accepting code as in attrib63.C. There are various forms of friend declarations, we have friend templates, C++11 extended friend declarations, and so on. In some cases we already ignore the attribute and warn that it was ignored. But certain cases weren't diagnosed, and with this patch we'll give a hard error. I tried hard not to emit both a warning and error and I think it worked out. Jason provided the cp_parser_decl_specifier_seq hunk to detect using standard attributes in the middle of decl-specifiers, which is invalid. Co-authored-by: Jason Merrill gcc/cp/ChangeLog: PR c++/99032 * cp-tree.h (any_non_type_attribute_p): Declare. * decl.c (grokdeclarator): Diagnose when an attribute appertains to a friend declaration that is not a definition. * decl2.c (any_non_type_attribute_p): New. * parser.c (cp_parser_decl_specifier_seq): Diagnose standard attributes in the middle of decl-specifiers. (cp_parser_elaborated_type_specifier): Diagnose when an attribute appertains to a friend declaration that is not a definition. (cp_parser_member_declaration): Likewise. gcc/testsuite/ChangeLog: PR c++/99032 * g++.dg/cpp0x/friend7.C: New test. * g++.dg/cpp0x/gen-attrs-4.C: Add dg-error. * g++.dg/cpp0x/gen-attrs-39-1.C: Likewise. * g++.dg/cpp0x/gen-attrs-74.C: New test. * g++.dg/ext/attrib63.C: New test. --- gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 5 ++++ gcc/cp/decl2.c | 14 ++++++++++ gcc/cp/parser.c | 23 ++++++++++++++++- gcc/testsuite/g++.dg/cpp0x/friend7.C | 40 +++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C | 3 ++- gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C | 3 ++- gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C | 10 ++++++++ gcc/testsuite/g++.dg/ext/attrib63.C | 16 ++++++++++++ 9 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/friend7.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C create mode 100644 gcc/testsuite/g++.dg/ext/attrib63.C (limited to 'gcc') diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 122dadf..580db91 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6763,6 +6763,7 @@ extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *, tree, tree, tree); extern tree splice_template_attributes (tree *, tree); extern bool any_dependent_type_attributes_p (tree); +extern bool any_non_type_attribute_p (tree); extern tree cp_reconstruct_complex_type (tree, tree); extern bool attributes_naming_typedef_ok (tree); extern void cplus_decl_attributes (tree *, tree, int); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bc3928d..17511f0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13741,6 +13741,11 @@ grokdeclarator (const cp_declarator *declarator, if (friendp) { + if (attrlist && !funcdef_flag + /* Hack to allow attributes like vector_size on a friend. */ + && any_non_type_attribute_p (*attrlist)) + error_at (id_loc, "attribute appertains to a friend " + "declaration that is not a definition"); /* Friends are treated specially. */ if (ctype == current_class_type) ; /* We already issued a permerror. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 89f874a..8e4dd6b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1331,6 +1331,20 @@ any_dependent_type_attributes_p (tree attrs) return false; } +/* True if ATTRS contains any attribute that does not require a type. */ + +bool +any_non_type_attribute_p (tree attrs) +{ + for (tree a = attrs; a; a = TREE_CHAIN (a)) + { + const attribute_spec *as = lookup_attribute_spec (get_attribute_name (a)); + if (as && !as->type_required) + return true; + } + return false; +} + /* Return true iff ATTRS are acceptable attributes to be applied in-place to a typedef which gives a previously unnamed class or enum a name for linkage purposes. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 41df5dd..c0b5795 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -15146,6 +15146,16 @@ cp_parser_decl_specifier_seq (cp_parser* parser, if (!found_decl_spec) break; + if (decl_specs->std_attributes) + { + error_at (decl_specs->locations[ds_std_attribute], + "standard attributes in middle of decl-specifiers"); + inform (decl_specs->locations[ds_std_attribute], + "standard attributes must precede the decl-specifiers to " + "apply to the declaration, or follow them to apply to " + "the type"); + } + decl_specs->any_specifiers_p = true; /* After we see one decl-specifier, further decl-specifiers are always optional. */ @@ -19764,11 +19774,15 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, && ! processing_explicit_instantiation) warning (OPT_Wattributes, "attributes ignored on template instantiation"); + else if (is_friend && attributes) + error ("attribute appertains to a friend declaration that is not " + "a definition"); else if (is_declaration && cp_parser_declares_only_class_p (parser)) cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); else warning (OPT_Wattributes, - "attributes ignored on elaborated-type-specifier that is not a forward declaration"); + "attributes ignored on elaborated-type-specifier that is " + "not a forward declaration"); } if (tag_type == enum_type) @@ -26054,6 +26068,13 @@ cp_parser_member_declaration (cp_parser* parser) error_at (decl_spec_token_start->location, "friend declaration does not name a class or " "function"); + /* Give an error if an attribute cannot appear here, as per + [dcl.attr.grammar]/5. But not when declares_class_or_enum: + we ignore attributes in elaborated-type-specifiers. */ + else if (!declares_class_or_enum && decl_specifiers.attributes) + error_at (decl_spec_token_start->location, + "attribute appertains to a friend declaration " + "that is not a definition"); else make_friend_class (current_class_type, type, /*complain=*/true); diff --git a/gcc/testsuite/g++.dg/cpp0x/friend7.C b/gcc/testsuite/g++.dg/cpp0x/friend7.C new file mode 100644 index 0000000..734b367 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/friend7.C @@ -0,0 +1,40 @@ +// PR c++/99032 +// { dg-do compile { target c++11 } } + +class X { }; +template +void foo (T1, T2); + +struct S { + [[deprecated]] friend void f(); // { dg-error "attribute appertains" } + [[deprecated]] friend void f2() { } + __attribute__((deprecated)) friend void f3(); // { dg-error "attribute appertains" } + friend void f3 [[deprecated]] (); // { dg-error "attribute appertains" } + friend void f4 [[deprecated]] () { } + [[deprecated]] friend void; // { dg-error "attribute appertains" } + __attribute__((deprecated)) friend int; // { dg-error "attribute appertains" } + friend __attribute__((deprecated)) int; // { dg-error "attribute appertains" } + friend int __attribute__((deprecated)); // { dg-error "attribute appertains" } + [[deprecated]] friend X; // { dg-error "attribute appertains" } + [[deprecated]] friend class N; // { dg-warning "attribute ignored" } + friend class [[deprecated]] N2; // { dg-error "attribute appertains" } + friend class __attribute__((deprecated)) N3; // { dg-error "attribute appertains" } + [[deprecated]] friend void foo<>(int, int); // { dg-error "attribute appertains" } + [[deprecated]] friend void ::foo(int, int); // { dg-error "attribute appertains" } + // { dg-bogus "should have" "PR100339" { xfail *-*-* } .-1 } +}; + +template +class node { }; + +template +struct A { + [[deprecated]] friend T; // { dg-error "attribute appertains" } + [[deprecated]] friend class node; // { dg-warning "attribute ignored" } + template + [[deprecated]] friend class A; // { dg-warning "attribute ignored" } + template + [[deprecated]] friend void bar () { } + template + [[deprecated]] friend void baz (); // { dg-error "attribute appertains" } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C index 453fc01..4010ba7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C @@ -2,7 +2,8 @@ int fragile_block(void) { typedef - [[gnu::aligned (16)]] // { dg-warning "ignored" } + [[gnu::aligned (16)]] // { dg-error "standard attributes in middle of decl-specifiers" } +// { dg-warning "attribute ignored" "" { target *-*-* } .-1 } struct { int i; } XmmUint16; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C index b401c69..c120aed 100644 --- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C @@ -13,7 +13,8 @@ int one_third [[noreturn]] [[gnu::unused]] (void); int [[gnu::unused]] one_half(); // { dg-warning "ignored" } static -[[noreturn]] // { dg-warning "ignored" } +[[noreturn]] // { dg-error "standard attributes in middle of decl-specifiers" } +// { dg-warning "attribute ignored" "" { target *-*-* } .-1 } void two [[gnu::unused]] (void) {} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C new file mode 100644 index 0000000..7e17bc8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++11 } } +// A C++11 attribute cannot appear in the middle of the decl-specifier-seq, +// only before it (in which case it appertains to the declaration) or at +// the end (in which case it appertains to the type). + +struct S { + friend [[deprecated]] void; // { dg-error "standard attributes in middle of decl-specifiers" } + friend [[deprecated]] int fn(); // { dg-error "standard attributes in middle of decl-specifiers" } + // { dg-warning "attribute ignored" "" { target *-*-* } .-1 } +}; diff --git a/gcc/testsuite/g++.dg/ext/attrib63.C b/gcc/testsuite/g++.dg/ext/attrib63.C new file mode 100644 index 0000000..e515a2b --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attrib63.C @@ -0,0 +1,16 @@ +// { dg-do compile } + +#define vector __attribute__((vector_size(16))) +class A { + friend vector float f(); + __attribute__((deprecated)) friend void f2(); // { dg-error "attribute appertains" } + friend __attribute__((deprecated, vector_size(16))) float f3(); // { dg-error "attribute appertains" } + friend __attribute__((vector_size(16), deprecated)) float f4(); // { dg-error "attribute appertains" } +}; + +vector float vf; +vector float +f () +{ + return vf; +} -- cgit v1.1 From 3489257a33d69d9d3778b585558adb7dc33eec6d Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 10 May 2021 15:51:12 +0200 Subject: Port gnat-style to Sphinx. gcc/ada/ChangeLog: * doc/Makefile: Add gnat-style target. * doc/share/conf.py: Likewise. * doc/gnat-style.rst: New file. --- gcc/ada/doc/Makefile | 2 +- gcc/ada/doc/gnat-style.rst | 691 +++++++++++++++++++++++++++++++++++++++++++++ gcc/ada/doc/share/conf.py | 4 +- 3 files changed, 695 insertions(+), 2 deletions(-) create mode 100644 gcc/ada/doc/gnat-style.rst (limited to 'gcc') diff --git a/gcc/ada/doc/Makefile b/gcc/ada/doc/Makefile index 9a435eb..4adfd36 100644 --- a/gcc/ada/doc/Makefile +++ b/gcc/ada/doc/Makefile @@ -14,7 +14,7 @@ ALLSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) \ -c $(SOURCEDIR)/share \ -d $(BUILDDIR)/$*/doctrees \ $(SOURCEDIR) -DOC_LIST=gnat_rm gnat_ugn +DOC_LIST=gnat_rm gnat_ugn gnat-style FMT_LIST=html pdf txt info .PHONY: help clean diff --git a/gcc/ada/doc/gnat-style.rst b/gcc/ada/doc/gnat-style.rst new file mode 100644 index 0000000..527e7ba --- /dev/null +++ b/gcc/ada/doc/gnat-style.rst @@ -0,0 +1,691 @@ +GNAT Coding Style: A Guide for GNAT Developers +============================================== + +General +------- + +Most of GNAT is written in Ada using a consistent style to ensure +readability of the code. This document has been written to help +maintain this consistent style, while having a large group of developers +work on the compiler. + +For the coding style in the C parts of the compiler and run time, +see the GNU Coding Guidelines. + +This document is structured after the Ada Reference Manual. +Those familiar with that document should be able to quickly +lookup style rules for particular constructs. + +Lexical Elements +---------------- + +Character Set and Separators +**************************** + +.. index:: Character set +.. index:: ASCII +.. index:: Separators +.. index:: End-of-line +.. index:: Line length +.. index:: Indentation + +* The character set used should be plain 7-bit ASCII. + The only separators allowed are space and the end-of-line sequence. + No other control character or format effector (such as ``HT``, + ``VT``, ``FF`` ) + should be used. + The normal end-of-line sequence is used, which may be + ``LF``, ``CR/LF`` or ``CR``, + depending on the host system. An optional ``SUB`` + ( ``16#1A#`` ) may be present as the + last character in the file on hosts using that character as file terminator. + +* Files that are checked in or distributed should be in host format. + +* A line should never be longer than 79 characters, not counting the line + separator. + +* Lines must not have trailing blanks. + +* Indentation is 3 characters per level for ``if`` statements, loops, and + ``case`` statements. + For exact information on required spacing between lexical + elements, see file style.adb. + + .. index:: style.adb file + +Identifiers +*********** + +* Identifiers will start with an upper case letter, and each letter following + an underscore will be upper case. + + .. index:: Casing (for identifiers) + + Short acronyms may be all upper case. + All other letters are lower case. + An exception is for identifiers matching a foreign language. In particular, + we use all lower case where appropriate for C. + +* Use underscores to separate words in an identifier. + + .. index:: Underscores + +* Try to limit your use of abbreviations in identifiers. + It is ok to make a few abbreviations, explain what they mean, and then + use them frequently, but don't use lots of obscure abbreviations. An + example is the ``ALI`` word which stands for Ada Library + Information and is by convention always written in upper-case when + used in entity names. + + .. code-block:: ada + + procedure Find_ALI_Files; + +* Don't use the variable name ``I``, use ``J`` instead; ``I`` is too + easily confused with ``1`` in some fonts. Similarly don't use the + variable ``O``, which is too easily mistaken for the number ``0``. + +Numeric Literals +**************** + +* Numeric literals should include underscores where helpful for + readability. + + .. index:: Underscores + + .. code-block:: ada + + 1_000_000 + 16#8000_0000# + 3.14159_26535_89793_23846 + +Reserved Words +************** + +* Reserved words use all lower case. + + .. index:: Casing (for reserved words) + + .. code-block:: ada + + return else + +* The words ``Access``, ``Delta`` and ``Digits`` are + capitalized when used as attribute_designator. + +Comments +******** + +* A comment starts with ``--`` followed by two spaces. + The only exception to this rule (i.e. one space is tolerated) is when the + comment ends with a single space followed by ``--``. + It is also acceptable to have only one space between ``--`` and the start + of the comment when the comment is at the end of a line, + after some Ada code. + +* Every sentence in a comment should start with an upper-case letter (including + the first letter of the comment). + + .. index:: Casing (in comments) + +* When declarations are commented with 'hanging' comments, i.e. + comments after the declaration, there is no blank line before the + comment, and if it is absolutely necessary to have blank lines within + the comments, e.g. to make paragraph separations within a single comment, + these blank lines *do* have a ``--`` (unlike the + normal rule, which is to use entirely blank lines for separating + comment paragraphs). The comment starts at same level of indentation + as code it is commenting. + + .. index:: Blank lines (in comments) + .. index:: Indentation + + .. code-block:: ada + + z : Integer; + -- Integer value for storing value of z + -- + -- The previous line was a blank line. + +* Comments that are dubious or incomplete, or that comment on possibly + wrong or incomplete code, should be preceded or followed by ``???``. + +* Comments in a subprogram body must generally be surrounded by blank lines. + An exception is a comment that follows a line containing a single keyword + ( ``begin``, ``else``, ``loop`` ): + + .. code-block:: ada + + begin + -- Comment for the next statement + + A := 5; + + -- Comment for the B statement + + B := 6; + end; + +* In sequences of statements, comments at the end of the lines should be + aligned. + + .. index:: Alignment (in comments) + + .. code-block:: ada + + My_Identifier := 5; -- First comment + Other_Id := 6; -- Second comment + +* Short comments that fit on a single line are *not* ended with a + period. Comments taking more than a line are punctuated in the normal + manner. + +* Comments should focus on *why* instead of *what*. + Descriptions of what subprograms do go with the specification. + +* Comments describing a subprogram spec should specifically mention the + formal argument names. General rule: write a comment that does not + depend on the names of things. The names are supplementary, not + sufficient, as comments. + +* *Do not* put two spaces after periods in comments. + +Declarations and Types +---------------------- + +* In entity declarations, colons must be surrounded by spaces. Colons + should be aligned. + + .. index:: Alignment (in declarations) + + .. code-block:: ada + + Entity1 : Integer; + My_Entity : Integer; + +* Declarations should be grouped in a logical order. + Related groups of declarations may be preceded by a header comment. + +* All local subprograms in a subprogram or package body should be declared + before the first local subprogram body. + +* Do not declare local entities that hide global entities. + + .. index:: Hiding of outer entities + +* Do not declare multiple variables in one declaration that spans lines. + Start a new declaration on each line, instead. + +* The defining_identifiers of global declarations serve as + comments of a sort. So don't choose terse names, but look for names + that give useful information instead. + +* Local names can be shorter, because they are used only within + one context, where comments explain their purpose. + +* When starting an initialization or default expression on the line that follows + the declaration line, use 2 characters for indentation. + + .. code-block:: ada + + Entity1 : Integer := + Function_Name (Parameters, For_Call); + +* If an initialization or default expression needs to be continued on subsequent + lines, the continuations should be indented from the start of the expression. + + .. code-block:: ada + + Entity1 : Integer := Long_Function_Name + (parameters for call); + +Expressions and Names +--------------------- + +* Every operator must be surrounded by spaces. An exception is that + this rule does not apply to the exponentiation operator, for which + there are no specific layout rules. The reason for this exception + is that sometimes it makes clearer reading to leave out the spaces + around exponentiation. + + .. index:: Operators + + .. code-block:: ada + + E := A * B**2 + 3 * (C - D); + +* Use parentheses where they clarify the intended association of operands + with operators: + + .. index:: Parenthesization of expressions + + .. code-block:: ada + + (A / B) * C + +Statements +---------- + +Simple and Compound Statements +****************************** + +* Use only one statement or label per line. + +* A longer sequence_of_statements may be divided in logical + groups or separated from surrounding code using a blank line. + + +If Statements +************* + +* When the ``if``, ``elsif`` or ``else`` keywords fit on the + same line with the condition and the ``then`` keyword, then the + statement is formatted as follows: + + .. index:: Alignment (in an if statement) + + .. code-block:: ada + + if condition then + ... + elsif condition then + ... + else + ... + end if; + + When the above layout is not possible, ``then`` should be aligned + with ``if``, and conditions should preferably be split before an + ``and`` or ``or`` keyword a follows: + + .. code-block:: ada + + if long_condition_that_has_to_be_split + and then continued_on_the_next_line + then + ... + end if; + + The ``elsif``, ``else`` and ``end if`` always line up with + the ``if`` keyword. The preferred location for splitting the line + is before ``and`` or ``or``. The continuation of a condition is + indented with two spaces or as many as needed to make nesting clear. + As an exception, if conditions are closely related either of the + following is allowed: + + .. code-block:: ada + + if x = lakdsjfhlkashfdlkflkdsalkhfsalkdhflkjdsahf + or else + x = asldkjhalkdsjfhhfd + or else + x = asdfadsfadsf + then + ... + end if; + + if x = lakdsjfhlkashfdlkflkdsalkhfsalkdhflkjdsahf or else + x = asldkjhalkdsjfhhfd or else + x = asdfadsfadsf + then + ... + end if; + +* Conditions should use short-circuit forms ( ``and then``, + ``or else`` ), except when the operands are boolean variables + or boolean constants. + + .. index:: Short-circuit forms + +* Complex conditions in ``if`` statements are indented two characters: + + .. index:: Indentation (in if statements) + + .. code-block:: ada + + if this_complex_condition + and then that_other_one + and then one_last_one + then + ... + end if; + + There are some cases where complex conditionals can be laid out + in manners that do not follow these rules to preserve better + parallelism between branches, e.g. + + .. code-block:: ada + + if xyz.abc (gef) = 'c' + or else + xyz.abc (gef) = 'x' + then + ... + end if; + +* Every ``if`` block is preceded and followed by a blank line, except + where it begins or ends a sequence_of_statements. + + .. index:: Blank lines (in an if statement) + + .. code-block:: ada + + A := 5; + + if A = 5 then + null; + end if; + + A := 6; + +Case Statements +*************** + +* Layout is as below. For long ``case`` statements, the extra indentation + can be saved by aligning the ``when`` clauses with the opening ``case``. + + .. code-block:: ada + + case expression is + when condition => + ... + when condition => + ... + end case; + +Loop Statements +*************** + +* When possible, have ``for`` or ``while`` on one line with the + condition and the ``loop`` keyword. + + .. code-block:: ada + + for J in S'Range loop + ... + end loop; + + If the condition is too long, split the condition (see 'If + statements' above) and align ``loop`` with the ``for`` or + ``while`` keyword. + + .. index:: Alignment (in a loop statement) + + .. code-block:: ada + + while long_condition_that_has_to_be_split + and then continued_on_the_next_line + loop + ... + end loop; + + If the loop_statement has an identifier, it is laid out as follows: + + .. code-block:: ada + + Outer : while not condition loop + ... + end Outer; + +Block Statements +**************** + +* The ``declare`` (optional), ``begin`` and ``end`` words + are aligned, except when the block_statement is named. There + is a blank line before the ``begin`` keyword: + + .. index:: Alignment (in a block statement) + + .. code-block:: ada + + Some_Block : declare + ... + + begin + ... + end Some_Block; + +Subprograms +----------- + +Subprogram Declarations +*********************** + +* Do not write the ``in`` for parameters. + + .. code-block:: ada + + function Length (S : String) return Integer; + +* When the declaration line for a procedure or a function is too long to fit + the entire declaration (including the keyword procedure or function) on a + single line, then fold it, putting a single parameter on a line, aligning + the colons, as in: + + .. code-block:: ada + + procedure Set_Heading + (Source : String; + Count : Natural; + Pad : Character := Space; + Fill : Boolean := True); + + In the case of a function, if the entire spec does not fit on one line, then + the return may appear after the last parameter, as in: + + .. code-block:: ada + + function Head + (Source : String; + Count : Natural; + Pad : Character := Space) return String; + + Or it may appear on its own as a separate line. This form is preferred when + putting the return on the same line as the last parameter would result in + an overlong line. The return type may optionally be aligned with the types + of the parameters (usually we do this aligning if it results only in a small + number of extra spaces, and otherwise we don't attempt to align). So two + alternative forms for the above spec are: + + .. code-block:: ada + + function Head + (Source : String; + Count : Natural; + Pad : Character := Space) + return String; + + function Head + (Source : String; + Count : Natural; + Pad : Character := Space) + return String; + +Subprogram Bodies +***************** + +* Function and procedure bodies should usually be sorted alphabetically. Do + not attempt to sort them in some logical order by functionality. For a + sequence of subprogram specs, a general alphabetical sorting is also + usually appropriate, but occasionally it makes sense to group by major + function, with appropriate headers. + +* All subprograms have a header giving the function name, with the following + format: + + .. code-block:: ada + + ----------------- + -- My_Function -- + ----------------- + + procedure My_Function is + begin + ... + end My_Function; + + Note that the name in the header is preceded by a single space, + not two spaces as for other comments. These headers are used on + nested subprograms as well as outer level subprograms. They may + also be used as headers for sections of comments, or collections + of declarations that are related. + +* Every subprogram body must have a preceding subprogram_declaration, + which includes proper client documentation so that you do not need to + read the subprogram body in order to understand what the subprogram does and + how to call it. All subprograms should be documented, without exceptions. + + .. index:: Blank lines (in subprogram bodies) + +* A sequence of declarations may optionally be separated from the following + begin by a blank line. Just as we optionally allow blank lines in general + between declarations, this blank line should be present only if it improves + readability. Generally we avoid this blank line if the declarative part is + small (one or two lines) and the body has no blank lines, and we include it + if the declarative part is long or if the body has blank lines. + +* If the declarations in a subprogram contain at least one nested + subprogram body, then just before the ``begin`` of the enclosing + subprogram, there is a comment line and a blank line: + + .. code-block:: ada + + -- Start of processing for Enclosing_Subprogram + + begin + ... + end Enclosing_Subprogram; + +* When nested subprograms are present, variables that are referenced by any + nested subprogram should precede the nested subprogram specs. For variables + that are not referenced by nested procedures, the declarations can either also + be before any of the nested subprogram specs (this is the old style, more + generally used). Or then can come just before the begin, with a header. The + following example shows the two possible styles: + + .. code-block:: ada + + procedure Style1 is + Var_Referenced_In_Nested : Integer; + Var_Referenced_Only_In_Style1 : Integer; + + proc Nested; + -- Comments ... + + ------------ + -- Nested -- + ------------ + + procedure Nested is + begin + ... + end Nested; + + -- Start of processing for Style1 + + begin + ... + end Style1; + + procedure Style2 is + Var_Referenced_In_Nested : Integer; + + proc Nested; + -- Comments ... + + ------------ + -- Nested -- + ------------ + + procedure Nested is + begin + ... + end Nested; + + -- Local variables + + Var_Referenced_Only_In_Style2 : Integer; + + -- Start of processing for Style2 + + begin + ... + end Style2; + + For new code, we generally prefer Style2, but we do not insist on + modifying all legacy occurrences of Style1, which is still much + more common in the sources. + +Packages and Visibility Rules +----------------------------- + +* All program units and subprograms have their name at the end: + + .. code-block:: ada + + package P is + ... + end P; + +* We will use the style of ``use`` -ing ``with`` -ed packages, with + the context clauses looking like: + + .. index:: use clauses + + .. code-block:: ada + + with A; use A; + with B; use B; + +* Names declared in the visible part of packages should be + unique, to prevent name clashes when the packages are ``use`` d. + + .. index:: Name clash avoidance + + .. code-block:: ada + + package Entity is + type Entity_Kind is ...; + ... + end Entity; + +* After the file header comment, the context clause and unit specification + should be the first thing in a program_unit. + +* Preelaborate, Pure and Elaborate_Body pragmas should be added right after the + package name, indented an extra level and using the parameterless form: + + .. code-block:: ada + + package Preelaborate_Package is + pragma Preelaborate; + ... + end Preelaborate_Package; + +Program Structure and Compilation Issues +---------------------------------------- + +* Every GNAT source file must be compiled with the ``-gnatg`` + switch to check the coding style. + (Note that you should look at + style.adb to see the lexical rules enforced by ``-gnatg`` ). + + .. index:: -gnatg option (to gcc) + .. index:: style.adb file + +* Each source file should contain only one compilation unit. + +* Filenames should be 8 or fewer characters, followed by the ``.adb`` + extension for a body or ``.ads`` for a spec. + + .. index:: File name length + +* Unit names should be distinct when 'krunch'ed to 8 characters + (see krunch.ads) and the filenames should match the unit name, + except that they are all lower case. + + .. index:: krunch.ads file + +.. toctree:: + share/gnu_free_documentation_license diff --git a/gcc/ada/doc/share/conf.py b/gcc/ada/doc/share/conf.py index 705a678..755c3a6 100644 --- a/gcc/ada/doc/share/conf.py +++ b/gcc/ada/doc/share/conf.py @@ -20,7 +20,9 @@ DOCS = { 'gnat_rm': { 'title': 'GNAT Reference Manual'}, 'gnat_ugn': { - 'title': 'GNAT User\'s Guide for Native Platforms'}} + 'title': 'GNAT User\'s Guide for Native Platforms'}, + 'gnat-style': { + 'title': 'GNAT Coding Style: A Guide for GNAT Developers'}} # Then retrieve the source directory root_source_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -- cgit v1.1 From 543c0cbca0ca4e9dbe703a9ea4b8eb79744157b6 Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Wed, 12 May 2021 10:52:51 +0100 Subject: aarch64: Merge sqdmlal2 and sqdmlsl2 expanders The various sqdmlal2 and sqdmlsl2 expanders perform almost identical functions and can be merged using code iterators and attributes to reduce the code in the MD file. No behavioural change is expected. gcc/ChangeLog: * config/aarch64/aarch64-simd.md (aarch64_sqdmlal2): Merge into... (aarch64_sqdmll2): ... This. (aarch64_sqdmlsl2): Delete. (aarch64_sqdmlal2_lane): Merge this... (aarch64_sqdmlsl2_lane): ... And this... (aarch64_sqdmll2_lane): ... Into this. (aarch64_sqdmlal2_laneq): Merge this... (aarch64_sqdmlsl2_laneq): ... And this... (aarch64_sqdmll2_laneq): ... Into this. (aarch64_sqdmlal2_n): Merge this... (aarch64_sqdmlsl2_n): ... And this... (aarch64_sqdmll2_n): ... Into this. --- gcc/config/aarch64/aarch64-simd.md | 104 ++++++++++--------------------------- 1 file changed, 28 insertions(+), 76 deletions(-) (limited to 'gcc') diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 9962089..802cca3 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -5356,29 +5356,19 @@ [(set_attr "type" "neon_sat_mla__scalar_long")] ) -(define_expand "aarch64_sqdmlal2" +(define_expand "aarch64_sqdmll2" [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") + (SBINQOPS: + (match_operand: 1 "register_operand") + (match_dup 1)) (match_operand:VQ_HSI 2 "register_operand") (match_operand:VQ_HSI 3 "register_operand")] "TARGET_SIMD" { rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlal2_internal (operands[0], operands[1], - operands[2], operands[3], p)); - DONE; -}) - -(define_expand "aarch64_sqdmlsl2" - [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") - (match_operand:VQ_HSI 2 "register_operand") - (match_operand:VQ_HSI 3 "register_operand")] - "TARGET_SIMD" -{ - rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlsl2_internal (operands[0], operands[1], - operands[2], operands[3], p)); + emit_insn (gen_aarch64_sqdmll2_internal (operands[0], + operands[1], operands[2], + operands[3], p)); DONE; }) @@ -5436,63 +5426,37 @@ [(set_attr "type" "neon_sat_mla__scalar_long")] ) -(define_expand "aarch64_sqdmlal2_lane" - [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") - (match_operand:VQ_HSI 2 "register_operand") - (match_operand: 3 "register_operand") - (match_operand:SI 4 "immediate_operand")] - "TARGET_SIMD" -{ - rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlal2_lane_internal (operands[0], operands[1], - operands[2], operands[3], - operands[4], p)); - DONE; -}) - -(define_expand "aarch64_sqdmlal2_laneq" - [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") - (match_operand:VQ_HSI 2 "register_operand") - (match_operand: 3 "register_operand") - (match_operand:SI 4 "immediate_operand")] - "TARGET_SIMD" -{ - rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlal2_laneq_internal (operands[0], operands[1], - operands[2], operands[3], - operands[4], p)); - DONE; -}) - -(define_expand "aarch64_sqdmlsl2_lane" +(define_expand "aarch64_sqdmll2_lane" [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") + (SBINQOPS: + (match_operand: 1 "register_operand") + (match_dup 1)) (match_operand:VQ_HSI 2 "register_operand") (match_operand: 3 "register_operand") (match_operand:SI 4 "immediate_operand")] "TARGET_SIMD" { rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlsl2_lane_internal (operands[0], operands[1], - operands[2], operands[3], - operands[4], p)); + emit_insn (gen_aarch64_sqdmll2_lane_internal (operands[0], + operands[1], operands[2], + operands[3], operands[4], p)); DONE; }) -(define_expand "aarch64_sqdmlsl2_laneq" +(define_expand "aarch64_sqdmll2_laneq" [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") + (SBINQOPS: + (match_operand: 1 "register_operand") + (match_dup 1)) (match_operand:VQ_HSI 2 "register_operand") (match_operand: 3 "register_operand") (match_operand:SI 4 "immediate_operand")] "TARGET_SIMD" { rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlsl2_laneq_internal (operands[0], operands[1], - operands[2], operands[3], - operands[4], p)); + emit_insn (gen_aarch64_sqdmll2_laneq_internal (operands[0], + operands[1], operands[2], + operands[3], operands[4], p)); DONE; }) @@ -5515,31 +5479,19 @@ [(set_attr "type" "neon_sat_mla__scalar_long")] ) -(define_expand "aarch64_sqdmlal2_n" - [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") - (match_operand:VQ_HSI 2 "register_operand") - (match_operand: 3 "register_operand")] - "TARGET_SIMD" -{ - rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlal2_n_internal (operands[0], operands[1], - operands[2], operands[3], - p)); - DONE; -}) - -(define_expand "aarch64_sqdmlsl2_n" +(define_expand "aarch64_sqdmll2_n" [(match_operand: 0 "register_operand") - (match_operand: 1 "register_operand") + (SBINQOPS: + (match_operand: 1 "register_operand") + (match_dup 1)) (match_operand:VQ_HSI 2 "register_operand") (match_operand: 3 "register_operand")] "TARGET_SIMD" { rtx p = aarch64_simd_vect_par_cnst_half (mode, , true); - emit_insn (gen_aarch64_sqdmlsl2_n_internal (operands[0], operands[1], - operands[2], operands[3], - p)); + emit_insn (gen_aarch64_sqdmll2_n_internal (operands[0], + operands[1], operands[2], + operands[3], p)); DONE; }) -- cgit v1.1 From 40a2f88838e5119799649a74692cbf38d774b706 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 14 May 2021 11:40:58 +0200 Subject: opts: add Warning keyword for 2 options gcc/c-family/ChangeLog: * c.opt: Add Warning keyword for 2 options. --- gcc/c-family/c.opt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index f1b4c3f..5fcf961 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -592,7 +592,7 @@ C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration) This switch is deprecated; use -Werror=implicit-function-declaration instead. Wexceptions -C++ ObjC++ Var(warn_exceptions) Init(1) +C++ ObjC++ Var(warn_exceptions) Init(1) Warning Warn when an exception handler is shadowed by another handler. Wextra @@ -1741,7 +1741,7 @@ C++ ObjC Var(flag_module_version_ignore) Integer ; undocumented, Very dangerous, but occasionally useful Winvalid-imported-macros -C++ ObjC++ Var(warn_imported_macros) +C++ ObjC++ Var(warn_imported_macros) Warning Warn about macros that have conflicting header units definitions. flang-info-include-translate -- cgit v1.1 From 80b4ce1a5190ebe764b1009afae57dcef45f92c2 Mon Sep 17 00:00:00 2001 From: Michael de Lang Date: Fri, 14 May 2021 12:09:45 +0200 Subject: TSAN: add new test gcc/testsuite/ChangeLog: * g++.dg/tsan/pthread_cond_clockwait.C: New test. --- gcc/testsuite/g++.dg/tsan/pthread_cond_clockwait.C | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 gcc/testsuite/g++.dg/tsan/pthread_cond_clockwait.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/tsan/pthread_cond_clockwait.C b/gcc/testsuite/g++.dg/tsan/pthread_cond_clockwait.C new file mode 100644 index 0000000..82d6a5c --- /dev/null +++ b/gcc/testsuite/g++.dg/tsan/pthread_cond_clockwait.C @@ -0,0 +1,31 @@ +// Test pthread_cond_clockwait not generating false positives with tsan +// { dg-do run { target { { *-*-linux* *-*-gnu* *-*-uclinux* } && pthread } } } +// { dg-options "-fsanitize=thread -lpthread" } + +#include + +pthread_cond_t cv; +pthread_mutex_t mtx; + +void *fn(void *vp) { + pthread_mutex_lock(&mtx); + pthread_cond_signal(&cv); + pthread_mutex_unlock(&mtx); + return NULL; +} + +int main() { + pthread_mutex_lock(&mtx); + + pthread_t tid; + pthread_create(&tid, NULL, fn, NULL); + + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + ts.tv_sec += 10; + pthread_cond_clockwait(&cv, &mtx, CLOCK_MONOTONIC, &ts); + pthread_mutex_unlock(&mtx); + + pthread_join(tid, NULL); + return 0; +} -- cgit v1.1 From 4d0385dfe0b9b86d71895f72f936ab3638ba6b3b Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 14 May 2021 12:14:22 +0200 Subject: Fix my name in ChangeLog files. --- gcc/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2215bec..3b937d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -53,7 +53,7 @@ sizes < 16 to a register when constructing vpcmov pattern. * config/i386/mmx.md (*xop_pcmov_): Use MMXMODE124 mode. -2021-05-13 marxin +2021-05-13 Martin Liska * gcov-io.c (gcov_write_block): Remove. (gcov_write_words): Likewise. -- cgit v1.1 From 36ecd44bd2aa2623e12af6b7c8cf433a4f29aa57 Mon Sep 17 00:00:00 2001 From: "prathamesh.kulkarni" Date: Fri, 14 May 2021 16:03:43 +0530 Subject: arm/PR66791: Replace calls to vtst builtin with it's boolean logic equivalent. gcc/ChangeLog: 2021-05-14 Prathamesh Kulkarni PR target/66791 * config/arm/arm_neon.h (vtst_s8): Replace call to vtst builtin with it's boolean logic equivalent. (vtst_s16): Likewise. (vtst_s32): Likewise. (vtst_u8): Likewise. (vtst_u16): Likewise. (vtst_u32): Likewise. (vtst_p8): Likewise. (vtst_p16): Likewise. (vtstq_s8): Likewise. (vtstq_s16): Likewise. (vtstq_s32): Likewise. (vtstq_u8): Likewise. (vtstq_u16): Likewise. (vtstq_u32): Likewise. (vtstq_p8): Likewise. (vtstq_p16): Likewise. * config/arm/arm_neon_builtins.def: Remove entry for vtst. * config/arm/neon.md (neon_vtst): Remove pattern. --- gcc/config/arm/arm_neon.h | 32 ++++++++++++++++---------------- gcc/config/arm/arm_neon_builtins.def | 1 - gcc/config/arm/neon.md | 10 ---------- 3 files changed, 16 insertions(+), 27 deletions(-) (limited to 'gcc') diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h index dc28b92..dcd533f 100644 --- a/gcc/config/arm/arm_neon.h +++ b/gcc/config/arm/arm_neon.h @@ -2919,112 +2919,112 @@ __extension__ extern __inline uint8x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_s8 (int8x8_t __a, int8x8_t __b) { - return (uint8x8_t)__builtin_neon_vtstv8qi (__a, __b); + return (uint8x8_t) ((__a & __b) != 0); } __extension__ extern __inline uint16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_s16 (int16x4_t __a, int16x4_t __b) { - return (uint16x4_t)__builtin_neon_vtstv4hi (__a, __b); + return (uint16x4_t) ((__a & __b) != 0); } __extension__ extern __inline uint32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_s32 (int32x2_t __a, int32x2_t __b) { - return (uint32x2_t)__builtin_neon_vtstv2si (__a, __b); + return (uint32x2_t) ((__a & __b) != 0); } __extension__ extern __inline uint8x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_u8 (uint8x8_t __a, uint8x8_t __b) { - return (uint8x8_t)__builtin_neon_vtstv8qi ((int8x8_t) __a, (int8x8_t) __b); + return (uint8x8_t) ((__a & __b) != 0); } __extension__ extern __inline uint16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_u16 (uint16x4_t __a, uint16x4_t __b) { - return (uint16x4_t)__builtin_neon_vtstv4hi ((int16x4_t) __a, (int16x4_t) __b); + return (uint16x4_t) ((__a & __b) != 0); } __extension__ extern __inline uint32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_u32 (uint32x2_t __a, uint32x2_t __b) { - return (uint32x2_t)__builtin_neon_vtstv2si ((int32x2_t) __a, (int32x2_t) __b); + return (uint32x2_t) ((__a & __b) != 0); } __extension__ extern __inline uint8x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_p8 (poly8x8_t __a, poly8x8_t __b) { - return (uint8x8_t)__builtin_neon_vtstv8qi ((int8x8_t) __a, (int8x8_t) __b); + return (uint8x8_t) ((__a & __b) != 0); } __extension__ extern __inline uint16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtst_p16 (poly16x4_t __a, poly16x4_t __b) { - return (uint16x4_t)__builtin_neon_vtstv4hi ((int16x4_t) __a, (int16x4_t) __b); + return (uint16x4_t) ((__a & __b) != 0); } __extension__ extern __inline uint8x16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_s8 (int8x16_t __a, int8x16_t __b) { - return (uint8x16_t)__builtin_neon_vtstv16qi (__a, __b); + return (uint8x16_t) ((__a & __b) != 0); } __extension__ extern __inline uint16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_s16 (int16x8_t __a, int16x8_t __b) { - return (uint16x8_t)__builtin_neon_vtstv8hi (__a, __b); + return (uint16x8_t) ((__a & __b) != 0); } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_s32 (int32x4_t __a, int32x4_t __b) { - return (uint32x4_t)__builtin_neon_vtstv4si (__a, __b); + return (uint32x4_t) ((__a & __b) != 0); } __extension__ extern __inline uint8x16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_u8 (uint8x16_t __a, uint8x16_t __b) { - return (uint8x16_t)__builtin_neon_vtstv16qi ((int8x16_t) __a, (int8x16_t) __b); + return (uint8x16_t) ((__a & __b) != 0); } __extension__ extern __inline uint16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_u16 (uint16x8_t __a, uint16x8_t __b) { - return (uint16x8_t)__builtin_neon_vtstv8hi ((int16x8_t) __a, (int16x8_t) __b); + return (uint16x8_t) ((__a & __b) != 0); } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_u32 (uint32x4_t __a, uint32x4_t __b) { - return (uint32x4_t)__builtin_neon_vtstv4si ((int32x4_t) __a, (int32x4_t) __b); + return (uint32x4_t) ((__a & __b) != 0); } __extension__ extern __inline uint8x16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_p8 (poly8x16_t __a, poly8x16_t __b) { - return (uint8x16_t)__builtin_neon_vtstv16qi ((int8x16_t) __a, (int8x16_t) __b); + return (uint8x16_t) ((__a & __b) != 0); } __extension__ extern __inline uint16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vtstq_p16 (poly16x8_t __a, poly16x8_t __b) { - return (uint16x8_t)__builtin_neon_vtstv8hi ((int16x8_t) __a, (int16x8_t) __b); + return (uint16x8_t) ((__a & __b) != 0); } __extension__ extern __inline int8x8_t diff --git a/gcc/config/arm/arm_neon_builtins.def b/gcc/config/arm/arm_neon_builtins.def index 97e4f9c..70438ac 100644 --- a/gcc/config/arm/arm_neon_builtins.def +++ b/gcc/config/arm/arm_neon_builtins.def @@ -142,7 +142,6 @@ VAR2 (UNOP, vcgez, v4hf, v8hf) VAR2 (UNOP, vcgtz, v4hf, v8hf) VAR2 (UNOP, vclez, v4hf, v8hf) VAR2 (UNOP, vcltz, v4hf, v8hf) -VAR6 (BINOP, vtst, v8qi, v4hi, v2si, v16qi, v8hi, v4si) VAR6 (BINOP, vabds, v8qi, v4hi, v2si, v16qi, v8hi, v4si) VAR6 (BINOP, vabdu, v8qi, v4hi, v2si, v16qi, v8hi, v4si) VAR2 (BINOP, vabdf, v2sf, v4sf) diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 2a1e304..641d26f 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -2578,16 +2578,6 @@ DONE; }) -(define_insn "neon_vtst" - [(set (match_operand:VDQIW 0 "s_register_operand" "=w") - (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") - (match_operand:VDQIW 2 "s_register_operand" "w")] - UNSPEC_VTST))] - "TARGET_NEON" - "vtst.\t%0, %1, %2" - [(set_attr "type" "neon_tst")] -) - (define_insn "neon_vtst_combine" [(set (match_operand:VDQIW 0 "s_register_operand" "=w") (plus:VDQIW -- cgit v1.1 From f05627d404038368b99e92ac4df4c29f4ae4a5fa Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 14 May 2021 13:24:12 +0200 Subject: testsuite: Add testcase for already fixed PR [PR88872] 2021-05-14 Jakub Jelinek * g++.dg/cpp1y/pr88872.C: New test. --- gcc/testsuite/g++.dg/cpp1y/pr88872.C | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr88872.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/cpp1y/pr88872.C b/gcc/testsuite/g++.dg/cpp1y/pr88872.C new file mode 100644 index 0000000..3719e39 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr88872.C @@ -0,0 +1,24 @@ +// PR c++/88872 +// { dg-do compile { target c++14 } } + +struct a { + template constexpr a(b) : c() {} + int c; +}; +void d(); +template constexpr a operator"" _n() { return d; } +struct e; +struct f { + e operator[](int); +}; +struct g { + void h(); + f i; +}; +template struct j { + void k() { [](auto) { constexpr auto l = 2_n; }(keywords); } + int keywords; +}; +using m = j; +class e : public m {}; +void g::h() { i[0].k(); } -- cgit v1.1 From d25809dbfe43917b3bed9454620fcc24f04c1e03 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 14 May 2021 14:56:28 +0200 Subject: testsuite: Add testcase for already fixed PR [PR90019] 2021-05-14 Jakub Jelinek PR c++/90019 * g++.dg/cpp0x/sfinae68.C: New test. --- gcc/testsuite/g++.dg/cpp0x/sfinae68.C | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/sfinae68.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae68.C b/gcc/testsuite/g++.dg/cpp0x/sfinae68.C new file mode 100644 index 0000000..d292b68 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae68.C @@ -0,0 +1,23 @@ +// PR c++/90019 +// { dg-do compile { target c++11 } } + +template +struct enable_if { }; +template +struct enable_if { typedef T type; }; +template +using __enable_if_t = typename enable_if::type; +template +using enable_if_t = typename enable_if::type; + +template ...> void foo() {} +template ...> void foo() {} +template ...> void bar() {} +template ...> void bar() {} + +void test() +{ + bar<0>(); + bar<0,0>(); + foo<0>(); +} -- cgit v1.1 From 3cafe627d6c8bce7e7f46bdbdef3d14e9701ce9d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 14 May 2021 15:34:12 +0200 Subject: testsuite: Add testcase for already fixed PR [PR94616] 2021-05-14 Jakub Jelinek PR c++/94616 * g++.dg/cpp0x/pr94616.C: New test. --- gcc/testsuite/g++.dg/cpp0x/pr94616.C | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr94616.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/cpp0x/pr94616.C b/gcc/testsuite/g++.dg/cpp0x/pr94616.C new file mode 100644 index 0000000..a8fe700 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr94616.C @@ -0,0 +1,23 @@ +// PR c++/94616 +// { dg-do compile { target c++11 } } + +struct Bar { + Bar(int n) { if (n > 0) throw 2; } + ~Bar() {} +}; + +struct Foo { + Bar b1 = 0; + Bar b2 = 1; + Foo() {} + ~Foo() {} +}; + +int +main() +{ + try { + Foo f; + } catch(int) { + } +} -- cgit v1.1 From 4206171605de65df9674a14dd9db75bf4f4ed037 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 14 May 2021 16:29:49 +0200 Subject: testsuite: Add testcase for already fixed PR [PR95226] 2021-05-14 Jakub Jelinek PR c++/95226 * g++.dg/cpp1y/pr95226.C: New test. --- gcc/testsuite/g++.dg/cpp1y/pr95226.C | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr95226.C (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/cpp1y/pr95226.C b/gcc/testsuite/g++.dg/cpp1y/pr95226.C new file mode 100644 index 0000000..614c83c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr95226.C @@ -0,0 +1,17 @@ +// PR c++/95226 +// { dg-do run { target c++14 } } + +#include + +struct T { + unsigned a; + float b {8.}; +}; + +int main() +{ + T t = {1}; + std::vector tt = {{1}, {2}}; + if (t.a != 1 || t.b != 8.0f || tt[0].a != 1 || tt[0].b != 8.0f || tt[1].a != 2 || tt[1].b != 8.0f) + __builtin_abort (); +} -- cgit v1.1 From ff3809b459db881e80f627e81ec946e7bbd7041d Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Fri, 14 May 2021 10:05:42 +0100 Subject: aarch64: Make sqdmlal2 patterns match canonical RTL The sqdmlal2 patterns are hidden beneath the SBINQOPS iterator and unfortunately they don't match canonical RTL because the simple accumulate operand comes in the first arm of the SS_PLUS. This patch splits the SS_PLUS and SS_MINUS forms with the SS_PLUS operands set up to match the canonical form, where the complex operand comes first. gcc/ChangeLog: * config/aarch64/aarch64-simd.md (aarch64_sqdmll2_lane_internal): Split into... (aarch64_sqdmlsl2_lane_internal): ... This... (aarch64_sqdmlal2_lane_internal): ... And this. (aarch64_sqdmll2_laneq_internal): Split into ... (aarch64_sqdmlsl2_laneq_internal): ... This... (aarch64_sqdmlal2_laneq_internal): ... And this. (aarch64_sqdmll2_n_internal): Split into... (aarch64_sqdmlsl2_n_internal): ... This... (aarch64_sqdmlal2_n_internal): ... And this. --- gcc/config/aarch64/aarch64-simd.md | 89 ++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 802cca3..e59bc7b 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -5374,9 +5374,9 @@ ;; vqdml[sa]l2_lane -(define_insn "aarch64_sqdmll2_lane_internal" +(define_insn "aarch64_sqdmlsl2_lane_internal" [(set (match_operand: 0 "register_operand" "=w") - (SBINQOPS: + (ss_minus: (match_operand: 1 "register_operand" "0") (ss_ashift: (mult: @@ -5395,14 +5395,40 @@ { operands[4] = aarch64_endian_lane_rtx (mode, INTVAL (operands[4])); return - "sqdmll2\\t%0, %2, %3.[%4]"; + "sqdmlsl2\\t%0, %2, %3.[%4]"; + } + [(set_attr "type" "neon_sat_mla__scalar_long")] +) + +(define_insn "aarch64_sqdmlal2_lane_internal" + [(set (match_operand: 0 "register_operand" "=w") + (ss_plus: + (ss_ashift: + (mult: + (sign_extend: + (vec_select: + (match_operand:VQ_HSI 2 "register_operand" "w") + (match_operand:VQ_HSI 5 "vect_par_cnst_hi_half" ""))) + (sign_extend: + (vec_duplicate: + (vec_select: + (match_operand: 3 "register_operand" "") + (parallel [(match_operand:SI 4 "immediate_operand" "i")]) + )))) + (const_int 1)) + (match_operand: 1 "register_operand" "0")))] + "TARGET_SIMD" + { + operands[4] = aarch64_endian_lane_rtx (mode, INTVAL (operands[4])); + return + "sqdmlal2\\t%0, %2, %3.[%4]"; } [(set_attr "type" "neon_sat_mla__scalar_long")] ) -(define_insn "aarch64_sqdmll2_laneq_internal" +(define_insn "aarch64_sqdmlsl2_laneq_internal" [(set (match_operand: 0 "register_operand" "=w") - (SBINQOPS: + (ss_minus: (match_operand: 1 "register_operand" "0") (ss_ashift: (mult: @@ -5421,7 +5447,33 @@ { operands[4] = aarch64_endian_lane_rtx (mode, INTVAL (operands[4])); return - "sqdmll2\\t%0, %2, %3.[%4]"; + "sqdmlsl2\\t%0, %2, %3.[%4]"; + } + [(set_attr "type" "neon_sat_mla__scalar_long")] +) + +(define_insn "aarch64_sqdmlal2_laneq_internal" + [(set (match_operand: 0 "register_operand" "=w") + (ss_plus: + (ss_ashift: + (mult: + (sign_extend: + (vec_select: + (match_operand:VQ_HSI 2 "register_operand" "w") + (match_operand:VQ_HSI 5 "vect_par_cnst_hi_half" ""))) + (sign_extend: + (vec_duplicate: + (vec_select: + (match_operand: 3 "register_operand" "") + (parallel [(match_operand:SI 4 "immediate_operand" "i")]) + )))) + (const_int 1)) + (match_operand: 1 "register_operand" "0")))] + "TARGET_SIMD" + { + operands[4] = aarch64_endian_lane_rtx (mode, INTVAL (operands[4])); + return + "sqdmlal2\\t%0, %2, %3.[%4]"; } [(set_attr "type" "neon_sat_mla__scalar_long")] ) @@ -5460,9 +5512,9 @@ DONE; }) -(define_insn "aarch64_sqdmll2_n_internal" +(define_insn "aarch64_sqdmlsl2_n_internal" [(set (match_operand: 0 "register_operand" "=w") - (SBINQOPS: + (ss_minus: (match_operand: 1 "register_operand" "0") (ss_ashift: (mult: @@ -5475,7 +5527,26 @@ (match_operand: 3 "register_operand" "")))) (const_int 1))))] "TARGET_SIMD" - "sqdmll2\\t%0, %2, %3.[0]" + "sqdmlsl2\\t%0, %2, %3.[0]" + [(set_attr "type" "neon_sat_mla__scalar_long")] +) + +(define_insn "aarch64_sqdmlal2_n_internal" + [(set (match_operand: 0 "register_operand" "=w") + (ss_plus: + (ss_ashift: + (mult: + (sign_extend: + (vec_select: + (match_operand:VQ_HSI 2 "register_operand" "w") + (match_operand:VQ_HSI 4 "vect_par_cnst_hi_half" ""))) + (sign_extend: + (vec_duplicate: + (match_operand: 3 "register_operand" "")))) + (const_int 1)) + (match_operand: 1 "register_operand" "0")))] + "TARGET_SIMD" + "sqdmlal2\\t%0, %2, %3.[0]" [(set_attr "type" "neon_sat_mla__scalar_long")] ) -- cgit v1.1 From 1ff863ab01640d181c3afb73c99701664efa7e7a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 13 May 2021 20:53:50 -0400 Subject: intl: add comments to _, N_, and G_ gcc/ChangeLog: * intl.h: Add comments. --- gcc/intl.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gcc') diff --git a/gcc/intl.h b/gcc/intl.h index 829364a..0d91e3f 100644 --- a/gcc/intl.h +++ b/gcc/intl.h @@ -47,14 +47,18 @@ extern const char *fake_ngettext (const char *singular, const char *plural, #endif +/* Used to immediately translate the argument. */ #ifndef _ # define _(msgid) gettext (msgid) #endif +/* Used to mark strings that will be translated later. */ #ifndef N_ # define N_(msgid) msgid #endif +/* Like N_, but for GCC diagnostic format strings. See ABOUT-GCC-NLS for + details. */ #ifndef G_ # define G_(gmsgid) gmsgid #endif -- cgit v1.1 From 2f1bb00ba340e53663651be7874011fd54e1d085 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 5 Apr 2021 11:47:50 -0400 Subject: c++: simplify enclosing_instantiation_of [PR95870] Comparing DECL_SOURCE_LOCATION like the GCC 11 patch for PR 95870 will also work for user-defined functions, if we update their location when instantiating. Another option would be to use LAMBDA_EXPR_REGEN_INFO for lambdas, but this way is even simpler. gcc/cp/ChangeLog: PR c++/95870 * pt.c (enclosing_instantiation_of): Just compare DECL_SOURCE_LOCATION. (regenerate_decl_from_template): Copy DECL_SOURCE_LOCATION. --- gcc/cp/pt.c | 54 ++++++++++++------------------------------------------ 1 file changed, 12 insertions(+), 42 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d7d6a3f..bf99635 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -14437,55 +14437,22 @@ most_general_lambda (tree t) } /* We're instantiating a variable from template function TCTX. Return the - corresponding current enclosing scope. This gets complicated because lambda - functions in templates are regenerated rather than instantiated, but generic - lambda functions are subsequently instantiated. */ + corresponding current enclosing scope. We can match them up using + DECL_SOURCE_LOCATION because lambdas only ever have one source location, and + the DECL_SOURCE_LOCATION for a function instantiation is updated to match + the template definition in regenerate_decl_from_template. */ static tree -enclosing_instantiation_of (tree otctx) +enclosing_instantiation_of (tree tctx) { - tree tctx = otctx; tree fn = current_function_decl; - int lambda_count = 0; - for (; tctx && (lambda_fn_in_template_p (tctx) - || regenerated_lambda_fn_p (tctx)); - tctx = decl_function_context (tctx)) - ++lambda_count; - - if (!tctx) - { - /* Match using DECL_SOURCE_LOCATION, which is unique for all lambdas. - - For GCC 11 the above condition limits this to the previously failing - case where all enclosing functions are lambdas (95870). FIXME. */ - for (tree ofn = fn; ofn; ofn = decl_function_context (ofn)) - if (DECL_SOURCE_LOCATION (ofn) == DECL_SOURCE_LOCATION (otctx)) - return ofn; - gcc_unreachable (); - } + /* We shouldn't ever need to do this for other artificial functions. */ + gcc_assert (!DECL_ARTIFICIAL (tctx) || LAMBDA_FUNCTION_P (tctx)); for (; fn; fn = decl_function_context (fn)) - { - tree ofn = fn; - int flambda_count = 0; - for (; fn && regenerated_lambda_fn_p (fn); - fn = decl_function_context (fn)) - ++flambda_count; - if ((fn && DECL_TEMPLATE_INFO (fn)) - ? most_general_template (fn) != most_general_template (tctx) - : fn != tctx) - continue; - if (flambda_count != lambda_count) - { - gcc_assert (flambda_count > lambda_count); - for (; flambda_count > lambda_count; --flambda_count) - ofn = decl_function_context (ofn); - } - gcc_assert (DECL_NAME (ofn) == DECL_NAME (otctx) - || DECL_CONV_FN_P (ofn)); - return ofn; - } + if (DECL_SOURCE_LOCATION (fn) == DECL_SOURCE_LOCATION (tctx)) + return fn; gcc_unreachable (); } @@ -25492,6 +25459,9 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args) int args_depth; int parms_depth; + /* Use the source location of the definition. */ + DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl); + args_depth = TMPL_ARGS_DEPTH (args); parms_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)); if (args_depth > parms_depth) -- cgit v1.1 From 62e1bd651f60cfe3daaad91b41b7612bc7fa7460 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Fri, 14 May 2021 19:19:26 +0200 Subject: Fortran/OpenMP: Handle implicit SAVE for variables in main gcc/fortran/ChangeLog: * resolve.c (resolve_symbol): Handle implicit SAVE of main-program for vars in 'omp threadprivate' and 'omp declare target'. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/implicit-save.f90: New test. --- gcc/fortran/resolve.c | 6 ++++-- gcc/testsuite/gfortran.dg/gomp/implicit-save.f90 | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/gomp/implicit-save.f90 (limited to 'gcc') diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 5a81387..83b41a3 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -16039,7 +16039,8 @@ resolve_symbol (gfc_symbol *sym) && !(sym->ns->save_all && !sym->attr.automatic) && sym->module == NULL && (sym->ns->proc_name == NULL - || sym->ns->proc_name->attr.flavor != FL_MODULE)) + || (sym->ns->proc_name->attr.flavor != FL_MODULE + && !sym->ns->proc_name->attr.is_main_program))) gfc_error ("Threadprivate at %L isn't SAVEd", &sym->declared_at); /* Check omp declare target restrictions. */ @@ -16050,7 +16051,8 @@ resolve_symbol (gfc_symbol *sym) && (!sym->attr.in_common && sym->module == NULL && (sym->ns->proc_name == NULL - || sym->ns->proc_name->attr.flavor != FL_MODULE))) + || (sym->ns->proc_name->attr.flavor != FL_MODULE + && !sym->ns->proc_name->attr.is_main_program)))) gfc_error ("!$OMP DECLARE TARGET variable %qs at %L isn't SAVEd", sym->name, &sym->declared_at); diff --git a/gcc/testsuite/gfortran.dg/gomp/implicit-save.f90 b/gcc/testsuite/gfortran.dg/gomp/implicit-save.f90 new file mode 100644 index 0000000..2af9647 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/implicit-save.f90 @@ -0,0 +1,11 @@ +subroutine foo + integer :: n = 5, m = 7 + !$omp declare target to(n) + !$omp threadprivate (m) +end + +program main + integer :: i, j + !$omp declare target to(i) + !$omp threadprivate (j) +end -- cgit v1.1 From 0e3702f8daeec5897982d185650b78a5c1c53c25 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Fri, 14 May 2021 19:21:47 +0200 Subject: Fortran/OpenMP: Support 'omp parallel master' gcc/fortran/ChangeLog: * dump-parse-tree.c (show_omp_node, show_code_node): Handle EXEC_OMP_PARALLEL_MASTER. * frontend-passes.c (gfc_code_walker): Likewise. * gfortran.h (enum gfc_statement): Add ST_OMP_PARALLEL_MASTER and ST_OMP_END_PARALLEL_MASTER. (enum gfc_exec_op): Add EXEC_OMP_PARALLEL_MASTER.. * match.h (gfc_match_omp_parallel_master): Handle it. * openmp.c (gfc_match_omp_parallel_master, resolve_omp_clauses, omp_code_to_statement, gfc_resolve_omp_directive): Likewise. * parse.c (decode_omp_directive, case_exec_markers, gfc_ascii_statement, parse_omp_structured_block, parse_executable): Likewise. * resolve.c (gfc_resolve_blocks, gfc_resolve_code): Likewise. * st.c (gfc_free_statement): Likewise. * trans-openmp.c (gfc_trans_omp_parallel_master, gfc_trans_omp_workshare, gfc_trans_omp_directive): Likewise. * trans.c (trans_code): Likewise. libgomp/ChangeLog: * testsuite/libgomp.fortran/parallel-master.f90: New test. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/parallel-master-1.f90: New test. * gfortran.dg/gomp/parallel-master-2.f90: New test. --- gcc/fortran/dump-parse-tree.c | 3 +++ gcc/fortran/frontend-passes.c | 1 + gcc/fortran/gfortran.h | 6 ++++-- gcc/fortran/match.h | 1 + gcc/fortran/openmp.c | 11 ++++++++++ gcc/fortran/parse.c | 17 ++++++++++++++- gcc/fortran/resolve.c | 3 +++ gcc/fortran/st.c | 1 + gcc/fortran/trans-openmp.c | 25 ++++++++++++++++++++++ gcc/fortran/trans.c | 1 + .../gfortran.dg/gomp/parallel-master-1.f90 | 23 ++++++++++++++++++++ .../gfortran.dg/gomp/parallel-master-2.f90 | 9 ++++++++ 12 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/gomp/parallel-master-1.f90 create mode 100644 gcc/testsuite/gfortran.dg/gomp/parallel-master-2.f90 (limited to 'gcc') diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c index b50265a..874e6d4 100644 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -1856,6 +1856,7 @@ show_omp_node (int level, gfc_code *c) case EXEC_OMP_PARALLEL: name = "PARALLEL"; break; case EXEC_OMP_PARALLEL_DO: name = "PARALLEL DO"; break; case EXEC_OMP_PARALLEL_DO_SIMD: name = "PARALLEL DO SIMD"; break; + case EXEC_OMP_PARALLEL_MASTER: name = "PARALLEL MASTER"; break; case EXEC_OMP_PARALLEL_SECTIONS: name = "PARALLEL SECTIONS"; break; case EXEC_OMP_PARALLEL_WORKSHARE: name = "PARALLEL WORKSHARE"; break; case EXEC_OMP_SCAN: name = "SCAN"; break; @@ -1927,6 +1928,7 @@ show_omp_node (int level, gfc_code *c) case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_SCAN: @@ -3139,6 +3141,7 @@ show_code_node (int level, gfc_code *c) case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_SCAN: diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index 93ac4b4..ffe2db4 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -5542,6 +5542,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn, case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: in_omp_workshare = false; diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 4f5d2f8..bab785b 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -266,7 +266,8 @@ enum gfc_statement ST_OMP_REQUIRES, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL, ST_END_CRITICAL, ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_EVENT_POST, ST_EVENT_WAIT, ST_FAIL_IMAGE, ST_FORM_TEAM, ST_CHANGE_TEAM, - ST_END_TEAM, ST_SYNC_TEAM, ST_NONE + ST_END_TEAM, ST_SYNC_TEAM, ST_OMP_PARALLEL_MASTER, + ST_OMP_END_PARALLEL_MASTER, ST_NONE }; /* Types of interfaces that we can have. Assignment interfaces are @@ -2704,7 +2705,8 @@ enum gfc_exec_op EXEC_OMP_TARGET_ENTER_DATA, EXEC_OMP_TARGET_EXIT_DATA, EXEC_OMP_TARGET_PARALLEL, EXEC_OMP_TARGET_PARALLEL_DO, EXEC_OMP_TARGET_PARALLEL_DO_SIMD, EXEC_OMP_TARGET_SIMD, - EXEC_OMP_TASKLOOP, EXEC_OMP_TASKLOOP_SIMD, EXEC_OMP_SCAN, EXEC_OMP_DEPOBJ + EXEC_OMP_TASKLOOP, EXEC_OMP_TASKLOOP_SIMD, EXEC_OMP_SCAN, EXEC_OMP_DEPOBJ, + EXEC_OMP_PARALLEL_MASTER }; typedef struct gfc_code diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h index b72ec67..09c5723 100644 --- a/gcc/fortran/match.h +++ b/gcc/fortran/match.h @@ -174,6 +174,7 @@ match gfc_match_omp_ordered_depend (void); match gfc_match_omp_parallel (void); match gfc_match_omp_parallel_do (void); match gfc_match_omp_parallel_do_simd (void); +match gfc_match_omp_parallel_master (void); match gfc_match_omp_parallel_sections (void); match gfc_match_omp_parallel_workshare (void); match gfc_match_omp_requires (void); diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index 7eeabff..294b6d0 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -3770,6 +3770,13 @@ gfc_match_omp_parallel_do_simd (void) match +gfc_match_omp_parallel_master (void) +{ + return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES); +} + + +match gfc_match_omp_parallel_sections (void) { return match_omp (EXEC_OMP_PARALLEL_SECTIONS, @@ -4833,6 +4840,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: @@ -6796,6 +6804,8 @@ omp_code_to_statement (gfc_code *code) { case EXEC_OMP_PARALLEL: return ST_OMP_PARALLEL; + case EXEC_OMP_PARALLEL_MASTER: + return ST_OMP_PARALLEL_MASTER; case EXEC_OMP_PARALLEL_SECTIONS: return ST_OMP_PARALLEL_SECTIONS; case EXEC_OMP_SECTIONS: @@ -7312,6 +7322,7 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns) case EXEC_OMP_CANCEL: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_PARALLEL: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_SECTIONS: case EXEC_OMP_SINGLE: diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 9bbe9e8..6efb3fd 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -925,6 +925,8 @@ decode_omp_directive (void) matchs ("end parallel do simd", gfc_match_omp_eos_error, ST_OMP_END_PARALLEL_DO_SIMD); matcho ("end parallel do", gfc_match_omp_eos_error, ST_OMP_END_PARALLEL_DO); + matcho ("end parallel master", gfc_match_omp_eos_error, + ST_OMP_END_PARALLEL_MASTER); matcho ("end parallel sections", gfc_match_omp_eos_error, ST_OMP_END_PARALLEL_SECTIONS); matcho ("end parallel workshare", gfc_match_omp_eos_error, @@ -990,6 +992,8 @@ decode_omp_directive (void) matchs ("parallel do simd", gfc_match_omp_parallel_do_simd, ST_OMP_PARALLEL_DO_SIMD); matcho ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO); + matcho ("parallel master", gfc_match_omp_parallel_master, + ST_OMP_PARALLEL_MASTER); matcho ("parallel sections", gfc_match_omp_parallel_sections, ST_OMP_PARALLEL_SECTIONS); matcho ("parallel workshare", gfc_match_omp_parallel_workshare, @@ -1605,7 +1609,7 @@ next_statement (void) #define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: \ case ST_IF_BLOCK: case ST_BLOCK: case ST_ASSOCIATE: \ case ST_WHERE_BLOCK: case ST_SELECT_CASE: case ST_SELECT_TYPE: \ - case ST_SELECT_RANK: case ST_OMP_PARALLEL: \ + case ST_SELECT_RANK: case ST_OMP_PARALLEL: case ST_OMP_PARALLEL_MASTER: \ case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: \ case ST_OMP_CRITICAL: case ST_OMP_MASTER: case ST_OMP_SINGLE: \ case ST_OMP_DO: case ST_OMP_PARALLEL_DO: case ST_OMP_ATOMIC: \ @@ -2349,6 +2353,9 @@ gfc_ascii_statement (gfc_statement st) case ST_OMP_END_PARALLEL_DO_SIMD: p = "!$OMP END PARALLEL DO SIMD"; break; + case ST_OMP_END_PARALLEL_MASTER: + p = "!$OMP END PARALLEL MASTER"; + break; case ST_OMP_END_PARALLEL_SECTIONS: p = "!$OMP END PARALLEL SECTIONS"; break; @@ -2443,6 +2450,9 @@ gfc_ascii_statement (gfc_statement st) case ST_OMP_PARALLEL_DO_SIMD: p = "!$OMP PARALLEL DO SIMD"; break; + case ST_OMP_PARALLEL_MASTER: + p = "!$OMP PARALLEL MASTER"; + break; case ST_OMP_PARALLEL_SECTIONS: p = "!$OMP PARALLEL SECTIONS"; break; @@ -5255,6 +5265,9 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) case ST_OMP_PARALLEL: omp_end_st = ST_OMP_END_PARALLEL; break; + case ST_OMP_PARALLEL_MASTER: + omp_end_st = ST_OMP_END_PARALLEL_MASTER; + break; case ST_OMP_PARALLEL_SECTIONS: omp_end_st = ST_OMP_END_PARALLEL_SECTIONS; break; @@ -5379,6 +5392,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) break; case ST_OMP_PARALLEL: + case ST_OMP_PARALLEL_MASTER: case ST_OMP_PARALLEL_SECTIONS: parse_omp_structured_block (st, false); break; @@ -5580,6 +5594,7 @@ parse_executable (gfc_statement st) break; case ST_OMP_PARALLEL: + case ST_OMP_PARALLEL_MASTER: case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 83b41a3..c02bbed 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -10802,6 +10802,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns) case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_SECTIONS: @@ -11763,6 +11764,7 @@ gfc_resolve_code (gfc_code *code, gfc_namespace *ns) case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_TARGET_PARALLEL: case EXEC_OMP_TARGET_PARALLEL_DO: @@ -12243,6 +12245,7 @@ start: case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: omp_workshare_save = omp_workshare_flag; diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c index 9e76199..02a81da 100644 --- a/gcc/fortran/st.c +++ b/gcc/fortran/st.c @@ -230,6 +230,7 @@ gfc_free_statement (gfc_code *p) case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_SCAN: diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index aa3a82e..5666cd6 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -5554,6 +5554,28 @@ gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock, } static tree +gfc_trans_omp_parallel_master (gfc_code *code) +{ + stmtblock_t block; + tree stmt, omp_clauses; + + gfc_start_block (&block); + omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, + code->loc); + pushlevel (); + stmt = gfc_trans_omp_master (code); + if (TREE_CODE (stmt) != BIND_EXPR) + stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); + else + poplevel (0, 0); + stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL, + void_type_node, stmt, omp_clauses); + OMP_PARALLEL_COMBINED (stmt) = 1; + gfc_add_expr_to_block (&block, stmt); + return gfc_finish_block (&block); +} + +static tree gfc_trans_omp_parallel_sections (gfc_code *code) { stmtblock_t block; @@ -6092,6 +6114,7 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_CRITICAL: @@ -6273,6 +6296,8 @@ gfc_trans_omp_directive (gfc_code *code) return gfc_trans_omp_parallel_do (code, NULL, NULL); case EXEC_OMP_PARALLEL_DO_SIMD: return gfc_trans_omp_parallel_do_simd (code, NULL, NULL); + case EXEC_OMP_PARALLEL_MASTER: + return gfc_trans_omp_parallel_master (code); case EXEC_OMP_PARALLEL_SECTIONS: return gfc_trans_omp_parallel_sections (code); case EXEC_OMP_PARALLEL_WORKSHARE: diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index 624c713..9f296bd 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -2174,6 +2174,7 @@ trans_code (gfc_code * code, tree cond) case EXEC_OMP_PARALLEL: case EXEC_OMP_PARALLEL_DO: case EXEC_OMP_PARALLEL_DO_SIMD: + case EXEC_OMP_PARALLEL_MASTER: case EXEC_OMP_PARALLEL_SECTIONS: case EXEC_OMP_PARALLEL_WORKSHARE: case EXEC_OMP_SECTIONS: diff --git a/gcc/testsuite/gfortran.dg/gomp/parallel-master-1.f90 b/gcc/testsuite/gfortran.dg/gomp/parallel-master-1.f90 new file mode 100644 index 0000000..2ccc18f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/parallel-master-1.f90 @@ -0,0 +1,23 @@ +! { dg-additional-options "-fdump-tree-original" } + implicit none + integer :: k, p, s, r, nth, t, f + logical(kind=2) l2 + !$omp threadprivate (t) + + external bar + !$omp parallel master default(none) private (k) + call bar (k) + !$omp end parallel master + + !$omp parallel master private (p) firstprivate (f) if (parallel: l2) default(shared) & + !$omp& shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) copyin(t) + ! + !$omp end parallel master +end + +! { dg-final { scan-tree-dump "omp parallel private\\(k\\) default\\(none\\)" "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp master" 1 "original" } } +! { dg-final { scan-tree-dump "D.\[0-9\]+ = l2;" "original" } } +! { dg-final { scan-tree-dump "D.\[0-9\]+ = nth;" "original" } } +! { dg-final { scan-tree-dump "#pragma omp parallel private\\(p\\) firstprivate\\(f\\) shared\\(s\\) copyin\\(t\\) reduction\\(\\+:r\\) if\\(parallel:D.\[0-9\]+\\) num_threads\\(D.\[0-9\]+\\) default\\(shared\\) proc_bind\\(spread\\)" "original" } } + diff --git a/gcc/testsuite/gfortran.dg/gomp/parallel-master-2.f90 b/gcc/testsuite/gfortran.dg/gomp/parallel-master-2.f90 new file mode 100644 index 0000000..2e12de6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/parallel-master-2.f90 @@ -0,0 +1,9 @@ + use iso_c_binding, only: c_intptr_t + implicit none (external, type) + integer, parameter :: omp_event_handle_kind = c_intptr_t + integer (kind=omp_event_handle_kind) :: x + !$omp parallel master default (none) ! { dg-message "enclosing 'parallel'" } + !$omp task detach (x) ! { dg-error "'x' not specified in enclosing 'parallel'" } + !$omp end task + !$omp end parallel master +end -- cgit v1.1 From 87a7d10c2e9ec34a276e6acb5d2282a35b9cfafb Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 15 May 2021 00:16:27 +0000 Subject: Daily bump. --- gcc/ChangeLog | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 6 ++++++ gcc/c-family/ChangeLog | 4 ++++ gcc/cp/ChangeLog | 21 +++++++++++++++++++ gcc/fortran/ChangeLog | 25 ++++++++++++++++++++++ gcc/testsuite/ChangeLog | 42 +++++++++++++++++++++++++++++++++++++ 7 files changed, 154 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3b937d4..dfa8ae2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,58 @@ +2021-05-14 Jason Merrill + + * intl.h: Add comments. + +2021-05-14 Kyrylo Tkachov + + * config/aarch64/aarch64-simd.md + (aarch64_sqdmll2_lane_internal): Split into... + (aarch64_sqdmlsl2_lane_internal): ... This... + (aarch64_sqdmlal2_lane_internal): ... And this. + (aarch64_sqdmll2_laneq_internal): Split into ... + (aarch64_sqdmlsl2_laneq_internal): ... This... + (aarch64_sqdmlal2_laneq_internal): ... And this. + (aarch64_sqdmll2_n_internal): Split into... + (aarch64_sqdmlsl2_n_internal): ... This... + (aarch64_sqdmlal2_n_internal): ... And this. + +2021-05-14 Prathamesh Kulkarni + + PR target/66791 + * config/arm/arm_neon.h (vtst_s8): Replace call to vtst builtin with it's + boolean logic equivalent. + (vtst_s16): Likewise. + (vtst_s32): Likewise. + (vtst_u8): Likewise. + (vtst_u16): Likewise. + (vtst_u32): Likewise. + (vtst_p8): Likewise. + (vtst_p16): Likewise. + (vtstq_s8): Likewise. + (vtstq_s16): Likewise. + (vtstq_s32): Likewise. + (vtstq_u8): Likewise. + (vtstq_u16): Likewise. + (vtstq_u32): Likewise. + (vtstq_p8): Likewise. + (vtstq_p16): Likewise. + * config/arm/arm_neon_builtins.def: Remove entry for vtst. + * config/arm/neon.md (neon_vtst): Remove pattern. + +2021-05-14 Kyrylo Tkachov + + * config/aarch64/aarch64-simd.md (aarch64_sqdmlal2): Merge into... + (aarch64_sqdmll2): ... This. + (aarch64_sqdmlsl2): Delete. + (aarch64_sqdmlal2_lane): Merge this... + (aarch64_sqdmlsl2_lane): ... And this... + (aarch64_sqdmll2_lane): ... Into this. + (aarch64_sqdmlal2_laneq): Merge this... + (aarch64_sqdmlsl2_laneq): ... And this... + (aarch64_sqdmll2_laneq): ... Into this. + (aarch64_sqdmlal2_n): Merge this... + (aarch64_sqdmlsl2_n): ... And this... + (aarch64_sqdmll2_n): ... Into this. + 2021-05-13 Martin Sebor PR middle-end/100574 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 552c3b2..40eb1ca 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210514 +20210515 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2279e46..5146820 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2021-05-14 Martin Liska + + * doc/Makefile: Add gnat-style target. + * doc/share/conf.py: Likewise. + * doc/gnat-style.rst: New file. + 2021-05-12 Bob Duff PR ada/100564 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d33ad4a..7fc64a5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,7 @@ +2021-05-14 Martin Liska + + * c.opt: Add Warning keyword for 2 options. + 2021-05-13 Martin Liska PR middle-end/100504 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5a8a650..48425b9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +2021-05-14 Jason Merrill + + PR c++/95870 + * pt.c (enclosing_instantiation_of): Just compare + DECL_SOURCE_LOCATION. + (regenerate_decl_from_template): Copy DECL_SOURCE_LOCATION. + +2021-05-14 Marek Polacek + Jason Merrill + + PR c++/99032 + * cp-tree.h (any_non_type_attribute_p): Declare. + * decl.c (grokdeclarator): Diagnose when an attribute appertains to + a friend declaration that is not a definition. + * decl2.c (any_non_type_attribute_p): New. + * parser.c (cp_parser_decl_specifier_seq): Diagnose standard attributes + in the middle of decl-specifiers. + (cp_parser_elaborated_type_specifier): Diagnose when an attribute + appertains to a friend declaration that is not a definition. + (cp_parser_member_declaration): Likewise. + 2021-05-12 Marek Polacek * pt.c (tsubst_copy_and_build): Add warn_int_in_bool_context diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 71cc3d8..781dedd 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,28 @@ +2021-05-14 Tobias Burnus + + * dump-parse-tree.c (show_omp_node, show_code_node): Handle + EXEC_OMP_PARALLEL_MASTER. + * frontend-passes.c (gfc_code_walker): Likewise. + * gfortran.h (enum gfc_statement): Add ST_OMP_PARALLEL_MASTER and + ST_OMP_END_PARALLEL_MASTER. + (enum gfc_exec_op): Add EXEC_OMP_PARALLEL_MASTER.. + * match.h (gfc_match_omp_parallel_master): Handle it. + * openmp.c (gfc_match_omp_parallel_master, resolve_omp_clauses, + omp_code_to_statement, gfc_resolve_omp_directive): Likewise. + * parse.c (decode_omp_directive, case_exec_markers, + gfc_ascii_statement, parse_omp_structured_block, + parse_executable): Likewise. + * resolve.c (gfc_resolve_blocks, gfc_resolve_code): Likewise. + * st.c (gfc_free_statement): Likewise. + * trans-openmp.c (gfc_trans_omp_parallel_master, + gfc_trans_omp_workshare, gfc_trans_omp_directive): Likewise. + * trans.c (trans_code): Likewise. + +2021-05-14 Tobias Burnus + + * resolve.c (resolve_symbol): Handle implicit SAVE of main-program + for vars in 'omp threadprivate' and 'omp declare target'. + 2021-05-10 Martin Liska * decl.c (variable_decl): Use startswith diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9dfab7b..5647950 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,45 @@ +2021-05-14 Tobias Burnus + + * gfortran.dg/gomp/parallel-master-1.f90: New test. + * gfortran.dg/gomp/parallel-master-2.f90: New test. + +2021-05-14 Tobias Burnus + + * gfortran.dg/gomp/implicit-save.f90: New test. + +2021-05-14 Jakub Jelinek + + PR c++/95226 + * g++.dg/cpp1y/pr95226.C: New test. + +2021-05-14 Jakub Jelinek + + PR c++/94616 + * g++.dg/cpp0x/pr94616.C: New test. + +2021-05-14 Jakub Jelinek + + PR c++/90019 + * g++.dg/cpp0x/sfinae68.C: New test. + +2021-05-14 Jakub Jelinek + + * g++.dg/cpp1y/pr88872.C: New test. + +2021-05-14 Michael de Lang + + * g++.dg/tsan/pthread_cond_clockwait.C: New test. + +2021-05-14 Marek Polacek + Jason Merrill + + PR c++/99032 + * g++.dg/cpp0x/friend7.C: New test. + * g++.dg/cpp0x/gen-attrs-4.C: Add dg-error. + * g++.dg/cpp0x/gen-attrs-39-1.C: Likewise. + * g++.dg/cpp0x/gen-attrs-74.C: New test. + * g++.dg/ext/attrib63.C: New test. + 2021-05-13 Martin Sebor PR tree-optimization/93100 -- cgit v1.1 From 425ad87dcfacbb326d8f448a0f2b4d6b53dcd98f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 15 May 2021 10:12:11 +0200 Subject: regcprop: Fix another cprop_hardreg bug [PR100342] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Tue, Jan 19, 2021 at 04:10:33PM +0000, Richard Sandiford via Gcc-patches wrote: > Ah, ok, thanks for the extra context. > > So AIUI the problem when recording xmm2<-di isn't just: > > [A] partial_subreg_p (vd->e[sr].mode, GET_MODE (src)) > > but also that: > > [B] partial_subreg_p (vd->e[sr].mode, vd->e[vd->e[sr].oldest_regno].mode) > > For example, all registers in this sequence can be part of the same chain: > > (set (reg:HI R1) (reg:HI R0)) > (set (reg:SI R2) (reg:SI R1)) // [A] > (set (reg:DI R3) (reg:DI R2)) // [A] > (set (reg:SI R4) (reg:SI R[0-3])) > (set (reg:HI R5) (reg:HI R[0-4])) > > But: > > (set (reg:SI R1) (reg:SI R0)) > (set (reg:HI R2) (reg:HI R1)) > (set (reg:SI R3) (reg:SI R2)) // [A] && [B] > > is problematic because it dips below the precision of the oldest regno > and then increases again. > > When this happens, I guess we have two choices: > > (1) what the patch does: treat R3 as the start of a new chain. > (2) pretend that the copy occured in vd->e[sr].mode instead > (i.e. copy vd->e[sr].mode to vd->e[dr].mode) > > I guess (2) would need to be subject to REG_CAN_CHANGE_MODE_P. > Maybe the optimisation provided by (2) compared to (1) isn't common > enough to be worth the complication. > > I think we should test [B] as well as [A] though. The pass is set > up to do some quite elaborate mode changes and I think rejecting > [A] on its own would make some of the other code redundant. > It also feels like it should be a seperate “if” or “else if”, > with its own comment. Unfortunately, we now have a testcase that shows that testing also [B] is a problem (unfortunately now latent on the trunk, only reproduces on 10 and 11 branches). The comment in the patch tries to list just the interesting instructions, we have a 64-bit value, copy low 8 bit of those to another register, copy full 64 bits to another register and then clobber the original register. Before that (set (reg:DI r14) (const_int ...)) we have a chain DI r14, QI si, DI bp , that instruction drops the DI r14 from that chain, so we have QI si, DI bp , si being the oldest_regno. Next DI si is copied into DI dx. Only the low 8 bits of that are defined, the rest is unspecified, but we would add DI dx into that same chain at the end, so QI si, DI bp, DI dx [*]. Next si is overwritten, so the chain is DI bp, DI dx. And then we see (set (reg:DI dx) (reg:DI bp)) and remove it as redundant, because we think bp and dx are already equivalent, when in reality that is true only for the lowpart 8 bits. I believe the [*] marked step above is where the bug is. The committed regcprop.c (copy_value) change (but only committed to trunk/11, not to 10) added else if (partial_subreg_p (vd->e[sr].mode, GET_MODE (src)) && partial_subreg_p (vd->e[sr].mode, vd->e[vd->e[sr].oldest_regno].mode)) return; and while the first partial_subreg_p call returns true, the second one doesn't; before the (set (reg:DI r14) (const_int ...)) insn it would be true and we'd return, but as that reg got clobbered, si became the oldest regno in the chain and so vd->e[vd->e[sr].oldest_regno].mode is QImode and vd->e[sr].mode is QImode too, so the second partial_subreg_p is false. But as the testcase shows, what is the oldest_regno in the chain is something that changes over time, so relying on it for anything is problematic, something could have a different oldest_regno and later on get a different oldest_regno (perhaps with different mode) because the oldest_regno got overwritten and it can change both ways. The following patch effectively implements your (2) above. 2021-05-15 Jakub Jelinek PR rtl-optimization/100342 * regcprop.c (copy_value): When copying a source reg in a wider mode than it has recorded for the value, adjust recorded destination mode too or punt if !REG_CAN_CHANGE_MODE_P. * gcc.target/i386/pr100342.c: New test. --- gcc/regcprop.c | 48 +++++++++------------- gcc/testsuite/gcc.target/i386/pr100342.c | 70 ++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr100342.c (limited to 'gcc') diff --git a/gcc/regcprop.c b/gcc/regcprop.c index 02753a1..7c271e2 100644 --- a/gcc/regcprop.c +++ b/gcc/regcprop.c @@ -358,34 +358,26 @@ copy_value (rtx dest, rtx src, struct value_data *vd) else if (sn > hard_regno_nregs (sr, vd->e[sr].mode)) return; - /* It is not safe to link DEST into the chain if SRC was defined in some - narrower mode M and if M is also narrower than the mode of the first - register in the chain. For example: - (set (reg:DI r1) (reg:DI r0)) - (set (reg:HI r2) (reg:HI r1)) - (set (reg:SI r3) (reg:SI r2)) //Should be a new chain start at r3 - (set (reg:SI r4) (reg:SI r1)) - (set (reg:SI r5) (reg:SI r4)) - - the upper part of r3 is undefined. If we added it to the chain, - it may be used to replace r5, which has defined upper bits. - See PR98694 for details. - - [A] partial_subreg_p (vd->e[sr].mode, GET_MODE (src)) - [B] partial_subreg_p (vd->e[sr].mode, vd->e[vd->e[sr].oldest_regno].mode) - Condition B is added to to catch optimization opportunities of - - (set (reg:HI R1) (reg:HI R0)) - (set (reg:SI R2) (reg:SI R1)) // [A] - (set (reg:DI R3) (reg:DI R2)) // [A] - (set (reg:SI R4) (reg:SI R[0-3])) - (set (reg:HI R5) (reg:HI R[0-4])) - - in which all registers have only 16 defined bits. */ - else if (partial_subreg_p (vd->e[sr].mode, GET_MODE (src)) - && partial_subreg_p (vd->e[sr].mode, - vd->e[vd->e[sr].oldest_regno].mode)) - return; + /* If a narrower value is copied using wider mode, the upper bits + are undefined (could be e.g. a former paradoxical subreg). Signal + in that case we've only copied value using the narrower mode. + Consider: + (set (reg:DI r14) (mem:DI ...)) + (set (reg:QI si) (reg:QI r14)) + (set (reg:DI bp) (reg:DI r14)) + (set (reg:DI r14) (const_int ...)) + (set (reg:DI dx) (reg:DI si)) + (set (reg:DI si) (const_int ...)) + (set (reg:DI dx) (reg:DI bp)) + The last set is not redundant, while the low 8 bits of dx are already + equal to low 8 bits of bp, the other bits are undefined. */ + else if (partial_subreg_p (vd->e[sr].mode, GET_MODE (src))) + { + if (!REG_CAN_CHANGE_MODE_P (sr, GET_MODE (src), vd->e[sr].mode) + || !REG_CAN_CHANGE_MODE_P (dr, vd->e[sr].mode, GET_MODE (dest))) + return; + set_value_regno (dr, vd->e[sr].mode, vd); + } /* Link DR at the end of the value chain used by SR. */ diff --git a/gcc/testsuite/gcc.target/i386/pr100342.c b/gcc/testsuite/gcc.target/i386/pr100342.c new file mode 100644 index 0000000..8e2ec82 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100342.c @@ -0,0 +1,70 @@ +/* PR rtl-optimization/100342 */ +/* { dg-do run { target int128 } } */ +/* { dg-options "-O2 -fno-dse -fno-forward-propagate -Wno-psabi -mno-sse2" } */ + +#define SHL(x, y) ((x) << ((y) & (sizeof(x) * 8 - 1))) +#define SHR(x, y) ((x) >> ((y) & (sizeof(x) * 8 - 1))) +#define ROR(x, y) (SHR(x, y)) | (SHL(x, (sizeof(x) * 8 - (y)))) +#define SHLV(x, y) ((x) << ((y) & (sizeof((x)[0]) * 8 - 1))) +#define SHLSV(x, y) ((x) << ((y) & (sizeof((y)[0]) * 8 - 1))) +typedef unsigned char A; +typedef unsigned char __attribute__((__vector_size__ (8))) B; +typedef unsigned char __attribute__((__vector_size__ (16))) C; +typedef unsigned char __attribute__((__vector_size__ (32))) D; +typedef unsigned char __attribute__((__vector_size__ (64))) E; +typedef unsigned short F; +typedef unsigned short __attribute__((__vector_size__ (16))) G; +typedef unsigned int H; +typedef unsigned int __attribute__((__vector_size__ (32))) I; +typedef unsigned long long J; +typedef unsigned long long __attribute__((__vector_size__ (8))) K; +typedef unsigned long long __attribute__((__vector_size__ (32))) L; +typedef unsigned long long __attribute__((__vector_size__ (64))) M; +typedef unsigned __int128 N; +typedef unsigned __int128 __attribute__((__vector_size__ (16))) O; +typedef unsigned __int128 __attribute__((__vector_size__ (32))) P; +typedef unsigned __int128 __attribute__((__vector_size__ (64))) Q; +B v1; +D v2; +L v3; +K v4; +I v5; +O v6; + +B +foo (A a, C b, E c, F d, G e, H f, J g, M h, N i, P j, Q k) +{ + b &= (A) f; + k += a; + G l = e; + D m = v2 >= (A) (J) v1; + J r = a + g; + L n = v3 <= f; + k -= i / f; + l -= (A) g; + c |= (A) d; + b -= (A) i; + J o = ROR (__builtin_clz (r), a); + K p = v4 | f, q = v4 <= f; + P s = SHLV (SHLSV (__builtin_bswap64 (i), (P) (0 < j)) <= 0, j); + n += a <= r; + M t = (M) (a / SHLV (c, 0)) != __builtin_bswap64 (i); + I u = f - v5; + E v = (E) h + (E) t + (E) k; + D w = (union { D b[2]; }) { }.b[0] + ((union { E b; }) v).b[1] + m + (D) u + (D) n + (D) s; + C x = ((union { D b; }) w).b[1] + b + (C) l + (C) v6; + B y = ((union { C a; B b; }) x).b + ((union { C a; B b[2]; }) x).b[1] + (B) p + (B) q; + J z = i + o; + F z2 = z; + A z3 = z2; + return y + z3; +} + +int +main () +{ + B x = foo (0, (C) { }, (E) { }, 10, (G) { }, 4, 2, (M) { }, 123842323652213865LL, (P) { 1 }, (Q) { }); + if ((J) x != 0x2e2c2e2c2e2c2e30ULL) + __builtin_abort(); + return 0; +} -- cgit v1.1 From af42043e6618e69187b47f37dac870763c01e20f Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Sat, 15 May 2021 10:11:12 +0200 Subject: Revert "tree-sra: Avoid refreshing into const base decls (PR 100453)" This reverts commit ca9bb74a5f856ccdceb4797f18b0a4ac8f49d069. ...because of Ada issues I did not catch with original testing. gcc/ChangeLog: 2021-05-12 Martin Jambor Revert: PR tree-optimization/100453 * tree-sra.c (sra_modify_assign): All const base accesses do not need refreshing, not just those from decl_pool. (sra_modify_assign): Do not refresh into a const base decl. gcc/testsuite/ChangeLog: 2021-05-12 Martin Jambor Revert: PR tree-optimization/100453 * gcc.dg/tree-ssa/pr100453.c: New test. --- gcc/testsuite/gcc.dg/tree-ssa/pr100453.c | 18 ------------------ gcc/tree-sra.c | 4 ++-- 2 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr100453.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr100453.c b/gcc/testsuite/gcc.dg/tree-ssa/pr100453.c deleted file mode 100644 index 0cf0ad2..0000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr100453.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do run } */ -/* { dg-options "-O1" } */ - -struct a { - int b : 4; -} d; -static int c, e; -static const struct a f; -static void g(const struct a h) { - for (; c < 1; c++) - d = h; - e = h.b; - c = h.b; -} -int main() { - g(f); - return 0; -} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 186cd62..8dfc923 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -4244,7 +4244,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) || stmt_ends_bb_p (stmt)) { /* No need to copy into a constant-pool, it comes pre-initialized. */ - if (access_has_children_p (racc) && !TREE_READONLY (racc->base)) + if (access_has_children_p (racc) && !constant_decl_p (racc->base)) generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0, gsi, false, false, loc); if (access_has_children_p (lacc)) @@ -4333,7 +4333,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) } /* Restore the aggregate RHS from its components so the prevailing aggregate copy does the right thing. */ - if (access_has_children_p (racc) && !TREE_READONLY (racc->base)) + if (access_has_children_p (racc)) generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0, gsi, false, false, loc); /* Re-load the components of the aggregate copy destination. -- cgit v1.1 From 57d2342fbb55f73ef29ca186744663b320352c92 Mon Sep 17 00:00:00 2001 From: Hans-Peter Nilsson Date: Sat, 15 May 2021 01:26:17 +0200 Subject: reorg.c (fill_slots_from_thread): Reinstate code typoed out in "Remove CC0". The typo here, is obviously mistaken removal of lines next to a line that was validly removed. Targets affected are those with a delay-slot *and* defining TARGET_FLAGS_REGNUM. In-tree, a git-grep says the only ones matching are CRIS, h8300 and visium. The code removal has the effect of wrong-code, not reverting the effect of r11-2814. I'm "guessing" it was the effect of an incorrect conflict resolution in preparatory work for the r12-440 / bd1cd0d0e0fe / "Remove CC0" commit, when rebasing a related branch, and not testing any of the affected targets. Either way, the effect was a btest-gcc.sh state of "regress-1152" for cris-elf. FWIW, I wrote the removed code (sans the validly removed cc0 line), a part of what was committed at 2020-08-24 as 0e6c51de8ec47 / r11-2814. This commit gets cris-elf test-results back to a sane state (tested at 0ffdbc85d9a6 / r12-761). gcc: * reorg.c (fill_slots_from_thread): Reinstate code typoed out in "Remove CC0". --- gcc/reorg.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'gcc') diff --git a/gcc/reorg.c b/gcc/reorg.c index 4595f9a..7f06a6f 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -2375,6 +2375,16 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition, if (! insn_references_resource_p (trial, &set, true) && ! insn_sets_resource_p (trial, filter_flags ? &fset : &set, true) && ! insn_sets_resource_p (trial, &needed, true) + /* If we're handling sets to the flags register specially, we + only allow an insn into a delay-slot, if it either: + - doesn't set the flags register, + - the "set" of the flags register isn't used (clobbered), + - insns between the delay-slot insn and the trial-insn + as accounted in "set", have not affected the flags register. */ + && (! filter_flags + || ! insn_sets_resource_p (trial, &flags_res, true) + || find_regno_note (trial, REG_UNUSED, targetm.flags_regnum) + || ! TEST_HARD_REG_BIT (set.regs, targetm.flags_regnum)) && ! can_throw_internal (trial)) { rtx_insn *prior_insn; -- cgit v1.1 From 0df864ed1d24bbb0cf7504814e2f48e496ea5669 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Fri, 14 May 2021 14:15:55 -0500 Subject: rs6000: Add -mrop-protect and -mprivileged flags 2021-05-14 Bill Schmidt gcc/ * config/rs6000/rs6000.c (rs6000_option_override_internal): Disable shrink wrap when inserting ROP-protect instructions. * config/rs6000/rs6000.opt (mrop-protect): New option. (mprivileged): Likewise. * doc/invoke.texi: Document mrop-protect and mprivileged. --- gcc/config/rs6000/rs6000.c | 4 ++++ gcc/config/rs6000/rs6000.opt | 8 ++++++++ gcc/doc/invoke.texi | 20 ++++++++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index d1b76f6..53a9f54 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4040,6 +4040,10 @@ rs6000_option_override_internal (bool global_init_p) && ((rs6000_isa_flags_explicit & OPTION_MASK_QUAD_MEMORY_ATOMIC) == 0)) rs6000_isa_flags |= OPTION_MASK_QUAD_MEMORY_ATOMIC; + /* If we are inserting ROP-protect instructions, disable shrink wrap. */ + if (rs6000_rop_protect) + flag_shrink_wrap = 0; + /* If we can shrink-wrap the TOC register save separately, then use -msave-toc-indirect unless explicitly disabled. */ if ((rs6000_isa_flags_explicit & OPTION_MASK_SAVE_TOC_INDIRECT) == 0 diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index 0dbdf75..2685fa7 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -619,3 +619,11 @@ Generate (do not generate) MMA instructions. mrelative-jumptables Target Undocumented Var(rs6000_relative_jumptables) Init(1) Save + +mrop-protect +Target Var(rs6000_rop_protect) Init(0) +Enable instructions that guard against return-oriented programming attacks. + +mprivileged +Target Var(rs6000_privileged) Init(0) +Generate code that will run in privileged state. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 5198815..9cb8421 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1240,7 +1240,8 @@ See RS/6000 and PowerPC Options. -mgnu-attribute -mno-gnu-attribute @gol -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol -mstack-protector-guard-offset=@var{offset} -mprefixed -mno-prefixed @gol --mpcrel -mno-pcrel -mmma -mno-mmma} +-mpcrel -mno-pcrel -mmma -mno-mmma -mrop-protect -mno-rop-protect @gol +-mprivileged -mno-privileged} @emph{RX Options} @gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol @@ -27029,7 +27030,8 @@ following options: -mmulhw -mdlmzb -mmfpgpr -mvsx @gol -mcrypto -mhtm -mpower8-fusion -mpower8-vector @gol -mquad-memory -mquad-memory-atomic -mfloat128 @gol --mfloat128-hardware -mprefixed -mpcrel -mmma} +-mfloat128-hardware -mprefixed -mpcrel -mmma @gol +-mrop-protect} The particular options set for any particular CPU varies between compiler versions, depending on what setting seems to produce optimal @@ -28034,6 +28036,20 @@ store instructions when the option @option{-mcpu=future} is used. Generate (do not generate) the MMA instructions when the option @option{-mcpu=future} is used. +@item -mrop-protect +@itemx -mno-rop-protect +@opindex mrop-protect +@opindex mno-rop-protect +Generate (do not generate) ROP protection instructions when the target +processor supports them. Currently this option disables the shrink-wrap +optimization (@option{-fshrink-wrap}). + +@item -mprivileged +@itemx -mno-privileged +@opindex mprivileged +@opindex mno-privileged +Generate (do not generate) code that will run in privileged state. + @item -mblock-ops-unaligned-vsx @itemx -mno-block-ops-unaligned-vsx @opindex block-ops-unaligned-vsx -- cgit v1.1 From af979a98bce444082cd5fc5d358dcdf3f65fdfce Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Fri, 14 May 2021 14:25:25 -0500 Subject: rs6000: Emit ROP-mitigation instructions in prologue and epilogue 2021-05-14 Bill Schmidt gcc/ * config/rs6000/rs6000-internal.h (rs6000_stack): Add rop_hash_save_offset and rop_hash_size. * config/rs6000/rs6000-logue.c (rs6000_stack_info): Compute rop_hash_size and rop_hash_save_offset. (debug_stack_info): Dump rop_hash_save_offset and rop_hash_size. (rs6000_emit_prologue): Emit hashst[p] in prologue. (rs6000_emit_epilogue): Emit hashchk[p] in epilogue. * config/rs6000/rs6000.md (unspec): Add UNSPEC_HASHST and UNSPEC_HASHCHK. (hashst): New define_insn. (hashchk): Likewise. --- gcc/config/rs6000/rs6000-internal.h | 2 + gcc/config/rs6000/rs6000-logue.c | 74 +++++++++++++++++++++++++++++++++---- gcc/config/rs6000/rs6000.md | 31 ++++++++++++++++ 3 files changed, 100 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h index 428a786..88cf9bd 100644 --- a/gcc/config/rs6000/rs6000-internal.h +++ b/gcc/config/rs6000/rs6000-internal.h @@ -39,6 +39,7 @@ typedef struct rs6000_stack { int gp_save_offset; /* offset to save GP regs from initial SP */ int fp_save_offset; /* offset to save FP regs from initial SP */ int altivec_save_offset; /* offset to save AltiVec regs from initial SP */ + int rop_hash_save_offset; /* offset to save ROP hash from initial SP */ int lr_save_offset; /* offset to save LR from initial SP */ int cr_save_offset; /* offset to save CR from initial SP */ int vrsave_save_offset; /* offset to save VRSAVE from initial SP */ @@ -53,6 +54,7 @@ typedef struct rs6000_stack { int gp_size; /* size of saved GP registers */ int fp_size; /* size of saved FP registers */ int altivec_size; /* size of saved AltiVec registers */ + int rop_hash_size; /* size of ROP hash slot */ int cr_size; /* size to hold CR if not in fixed area */ int vrsave_size; /* size to hold VRSAVE */ int altivec_padding_size; /* size of altivec alignment padding */ diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index b0ac183..13c00e7 100644 --- a/gcc/config/rs6000/rs6000-logue.c +++ b/gcc/config/rs6000/rs6000-logue.c @@ -595,19 +595,21 @@ rs6000_savres_strategy (rs6000_stack_t *info, +---------------------------------------+ | Parameter save area (+padding*) (P) | 32 +---------------------------------------+ - | Alloca space (A) | 32+P + | Optional ROP hash slot (R) | 32+P +---------------------------------------+ - | Local variable space (L) | 32+P+A + | Alloca space (A) | 32+P+R +---------------------------------------+ - | Save area for AltiVec registers (W) | 32+P+A+L + | Local variable space (L) | 32+P+R+A +---------------------------------------+ - | AltiVec alignment padding (Y) | 32+P+A+L+W + | Save area for AltiVec registers (W) | 32+P+R+A+L +---------------------------------------+ - | Save area for GP registers (G) | 32+P+A+L+W+Y + | AltiVec alignment padding (Y) | 32+P+R+A+L+W +---------------------------------------+ - | Save area for FP registers (F) | 32+P+A+L+W+Y+G + | Save area for GP registers (G) | 32+P+R+A+L+W+Y +---------------------------------------+ - old SP->| back chain to caller's caller | 32+P+A+L+W+Y+G+F + | Save area for FP registers (F) | 32+P+R+A+L+W+Y+G + +---------------------------------------+ + old SP->| back chain to caller's caller | 32+P+R+A+L+W+Y+G+F +---------------------------------------+ * If the alloca area is present, the parameter save area is @@ -716,6 +718,19 @@ rs6000_stack_info (void) /* Does this function call anything (apart from sibling calls)? */ info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame); + info->rop_hash_size = 0; + + if (TARGET_POWER10 + && info->calls_p + && DEFAULT_ABI == ABI_ELFv2 + && rs6000_rop_protect) + info->rop_hash_size = 8; + else if (rs6000_rop_protect && DEFAULT_ABI != ABI_ELFv2) + { + /* We can't check this in rs6000_option_override_internal since + DEFAULT_ABI isn't established yet. */ + error ("%qs requires the ELFv2 ABI", "-mrop-protect"); + } /* Determine if we need to save the condition code registers. */ if (save_reg_p (CR2_REGNO) @@ -808,6 +823,11 @@ rs6000_stack_info (void) /* Adjust for AltiVec case. */ info->ehrd_offset = info->altivec_save_offset - ehrd_size; + + /* Adjust for ROP protection. */ + info->rop_hash_save_offset + = info->altivec_save_offset - info->rop_hash_size; + info->ehrd_offset -= info->rop_hash_size; } else info->ehrd_offset = info->gp_save_offset - ehrd_size; @@ -849,6 +869,7 @@ rs6000_stack_info (void) + info->gp_size + info->altivec_size + info->altivec_padding_size + + info->rop_hash_size + ehrd_size + ehcr_size + info->cr_size @@ -987,6 +1008,10 @@ debug_stack_info (rs6000_stack_t *info) fprintf (stderr, "\tvrsave_save_offset = %5d\n", info->vrsave_save_offset); + if (info->rop_hash_size) + fprintf (stderr, "\trop_hash_save_offset = %5d\n", + info->rop_hash_save_offset); + if (info->lr_save_p) fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset); @@ -1026,6 +1051,9 @@ debug_stack_info (rs6000_stack_t *info) fprintf (stderr, "\taltivec_padding_size= %5d\n", info->altivec_padding_size); + if (info->rop_hash_size) + fprintf (stderr, "\trop_hash_size = %5d\n", info->rop_hash_size); + if (info->cr_size) fprintf (stderr, "\tcr_size = %5d\n", info->cr_size); @@ -3252,6 +3280,22 @@ rs6000_emit_prologue (void) } } + /* The ROP hash store must occur before a stack frame is created, + since the hash operates on r1. */ + /* NOTE: The hashst isn't needed if we're going to do a sibcall, + but there's no way to know that here. Harmless except for + performance, of course. */ + if (TARGET_POWER10 && rs6000_rop_protect && info->rop_hash_size != 0) + { + gcc_assert (DEFAULT_ABI == ABI_ELFv2); + rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); + rtx addr = gen_rtx_PLUS (Pmode, stack_ptr, + GEN_INT (info->rop_hash_save_offset)); + rtx mem = gen_rtx_MEM (Pmode, addr); + rtx reg0 = gen_rtx_REG (Pmode, 0); + emit_insn (gen_hashst (mem, reg0)); + } + /* If we need to save CR, put it into r12 or r11. Choose r12 except when r12 will be needed by out-of-line gpr save. */ cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) @@ -4980,6 +5024,22 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa)); } + /* The ROP hash check must occur after the stack pointer is restored + (since the hash involves r1), and is not performed for a sibcall. */ + if (TARGET_POWER10 + && rs6000_rop_protect + && info->rop_hash_size != 0 + && epilogue_type != EPILOGUE_TYPE_SIBCALL) + { + gcc_assert (DEFAULT_ABI == ABI_ELFv2); + rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); + rtx addr = gen_rtx_PLUS (Pmode, stack_ptr, + GEN_INT (info->rop_hash_save_offset)); + rtx mem = gen_rtx_MEM (Pmode, addr); + rtx reg0 = gen_rtx_REG (Pmode, 0); + emit_insn (gen_hashchk (reg0, mem)); + } + if (epilogue_type != EPILOGUE_TYPE_SIBCALL && restoring_FPRs_inline) { if (cfa_restores) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index c8cdc42..0bfeb24 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -154,6 +154,8 @@ UNSPEC_CNTTZDM UNSPEC_PDEPD UNSPEC_PEXTD + UNSPEC_HASHST + UNSPEC_HASHCHK ]) ;; @@ -14948,6 +14950,35 @@ "TARGET_P9_MISC && TARGET_64BIT" "cmpeqb %0,%1,%2" [(set_attr "type" "logical")]) + + +;; ROP mitigation instructions. + +(define_insn "hashst" + [(set (match_operand:DI 0 "simple_offsettable_mem_operand" "=m") + (unspec_volatile:DI [(match_operand:DI 1 "int_reg_operand" "r")] + UNSPEC_HASHST))] + "TARGET_POWER10 && rs6000_rop_protect" +{ + static char templ[32]; + const char *p = rs6000_privileged ? "p" : ""; + sprintf (templ, "hashst%s %%1,%%0", p); + return templ; +} + [(set_attr "type" "store")]) + +(define_insn "hashchk" + [(unspec_volatile [(match_operand:DI 0 "int_reg_operand" "r") + (match_operand:DI 1 "simple_offsettable_mem_operand" "m")] + UNSPEC_HASHCHK)] + "TARGET_POWER10 && rs6000_rop_protect" +{ + static char templ[32]; + const char *p = rs6000_privileged ? "p" : ""; + sprintf (templ, "hashchk%s %%0,%%1", p); + return templ; +} + [(set_attr "type" "load")]) (include "sync.md") -- cgit v1.1 From 3ec3a9feb83d98715c97c0df4ae751a4eb582956 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Thu, 13 May 2021 13:10:10 -0500 Subject: rs6000: Conditionally define __ROP_PROTECT__ 2021-05-13 Bill Schmidt gcc/ * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define __ROP_PROTECT__ if -mrop-protect is selected. --- gcc/config/rs6000/rs6000-c.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 0f8a629..afcb5bb 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -602,6 +602,9 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags, /* Whether pc-relative code is being generated. */ if ((flags & OPTION_MASK_PCREL) != 0) rs6000_define_or_undefine_macro (define_p, "__PCREL__"); + /* Tell the user -mrop-protect is in play. */ + if (rs6000_rop_protect) + rs6000_define_or_undefine_macro (define_p, "__ROP_PROTECT__"); } void -- cgit v1.1 From 5bd66c6826e5f3a38ba393702923feb88959f845 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Thu, 13 May 2021 13:33:35 -0500 Subject: rs6000: Add ROP tests 2021-05-13 Bill Schmidt gcc/testsuite/ * gcc.target/powerpc/rop-1.c: New. * gcc.target/powerpc/rop-2.c: New. * gcc.target/powerpc/rop-3.c: New. * gcc.target/powerpc/rop-4.c: New. * gcc.target/powerpc/rop-5.c: New. --- gcc/testsuite/gcc.target/powerpc/rop-1.c | 17 +++++++++++++++++ gcc/testsuite/gcc.target/powerpc/rop-2.c | 17 +++++++++++++++++ gcc/testsuite/gcc.target/powerpc/rop-3.c | 18 ++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/rop-4.c | 15 +++++++++++++++ gcc/testsuite/gcc.target/powerpc/rop-5.c | 13 +++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/rop-1.c create mode 100644 gcc/testsuite/gcc.target/powerpc/rop-2.c create mode 100644 gcc/testsuite/gcc.target/powerpc/rop-3.c create mode 100644 gcc/testsuite/gcc.target/powerpc/rop-4.c create mode 100644 gcc/testsuite/gcc.target/powerpc/rop-5.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/powerpc/rop-1.c b/gcc/testsuite/gcc.target/powerpc/rop-1.c new file mode 100644 index 0000000..8cedcb6 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/rop-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */ +/* { dg-require-effective-target powerpc_elfv2 } */ + +/* Verify that ROP-protect instructions are inserted when a + call is present. */ + +extern void foo (void); + +int bar () +{ + foo (); + return 5; +} + +/* { dg-final { scan-assembler-times {\mhashst\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mhashchk\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/rop-2.c b/gcc/testsuite/gcc.target/powerpc/rop-2.c new file mode 100644 index 0000000..c556952 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/rop-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect -mprivileged" } */ +/* { dg-require-effective-target powerpc_elfv2 } */ + +/* Verify that privileged ROP-protect instructions are inserted when a + call is present. */ + +extern void foo (void); + +int bar () +{ + foo (); + return 5; +} + +/* { dg-final { scan-assembler-times {\mhashstp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mhashchkp\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/rop-3.c b/gcc/testsuite/gcc.target/powerpc/rop-3.c new file mode 100644 index 0000000..8d03792 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/rop-3.c @@ -0,0 +1,18 @@ +/* { dg-do run { target { power10_hw } } } */ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */ + +/* Verify that ROP-protect instructions execute correctly when a + call is present. */ + +void __attribute__((noipa)) foo () +{ + asm (""); +} + +int main () +{ + foo (); + return 0; +} + diff --git a/gcc/testsuite/gcc.target/powerpc/rop-4.c b/gcc/testsuite/gcc.target/powerpc/rop-4.c new file mode 100644 index 0000000..dcf47c6 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/rop-4.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */ +/* { dg-require-effective-target powerpc_elfv2 } */ + +/* Verify that no ROP-protect instructions are inserted when no + call is present. */ + + +int bar () +{ + return 5; +} + +/* { dg-final { scan-assembler-not {\mhashst\M} } } */ +/* { dg-final { scan-assembler-not {\mhashchk\M} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/rop-5.c b/gcc/testsuite/gcc.target/powerpc/rop-5.c new file mode 100644 index 0000000..cf04ea9 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/rop-5.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect" } */ + +/* Verify that __ROP_PROTECT__ is predefined for -mrop-protect. */ + +int foo () +{ +#ifndef __ROP_PROTECT__ + __ROP_PROTECT__ macro is not defined when it should be +#endif + return 0; +} + -- cgit v1.1 From 1ba3f0ef546ec83fe28fef7f34e0ee9e52c6477f Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 16 May 2021 00:16:37 +0000 Subject: Daily bump. --- gcc/ChangeLog | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 21 +++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dfa8ae2..6a49afe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,52 @@ +2021-05-15 Bill Schmidt + + * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define + __ROP_PROTECT__ if -mrop-protect is selected. + +2021-05-15 Bill Schmidt + + * config/rs6000/rs6000-internal.h (rs6000_stack): Add + rop_hash_save_offset and rop_hash_size. + * config/rs6000/rs6000-logue.c (rs6000_stack_info): Compute + rop_hash_size and rop_hash_save_offset. + (debug_stack_info): Dump rop_hash_save_offset and rop_hash_size. + (rs6000_emit_prologue): Emit hashst[p] in prologue. + (rs6000_emit_epilogue): Emit hashchk[p] in epilogue. + * config/rs6000/rs6000.md (unspec): Add UNSPEC_HASHST and + UNSPEC_HASHCHK. + (hashst): New define_insn. + (hashchk): Likewise. + +2021-05-15 Bill Schmidt + + * config/rs6000/rs6000.c (rs6000_option_override_internal): + Disable shrink wrap when inserting ROP-protect instructions. + * config/rs6000/rs6000.opt (mrop-protect): New option. + (mprivileged): Likewise. + * doc/invoke.texi: Document mrop-protect and mprivileged. + +2021-05-15 Hans-Peter Nilsson + + * reorg.c (fill_slots_from_thread): Reinstate code typoed out in + "Remove CC0". + +2021-05-15 Martin Jambor + + Revert: + 2021-05-13 Martin Jambor + + PR tree-optimization/100453 + * tree-sra.c (sra_modify_assign): All const base accesses do not + need refreshing, not just those from decl_pool. + (sra_modify_assign): Do not refresh into a const base decl. + +2021-05-15 Jakub Jelinek + + PR rtl-optimization/100342 + * regcprop.c (copy_value): When copying a source reg in a wider + mode than it has recorded for the value, adjust recorded destination + mode too or punt if !REG_CAN_CHANGE_MODE_P. + 2021-05-14 Jason Merrill * intl.h: Add comments. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 40eb1ca..a271d95 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210515 +20210516 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5647950..26b04e7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,24 @@ +2021-05-15 Bill Schmidt + + * gcc.target/powerpc/rop-1.c: New. + * gcc.target/powerpc/rop-2.c: New. + * gcc.target/powerpc/rop-3.c: New. + * gcc.target/powerpc/rop-4.c: New. + * gcc.target/powerpc/rop-5.c: New. + +2021-05-15 Martin Jambor + + Revert: + 2021-05-15 Martin Jambor + + PR tree-optimization/100453 + * gcc.dg/tree-ssa/pr100453.c: New test. + +2021-05-15 Jakub Jelinek + + PR rtl-optimization/100342 + * gcc.target/i386/pr100342.c: New test. + 2021-05-14 Tobias Burnus * gfortran.dg/gomp/parallel-master-1.f90: New test. -- cgit v1.1 From f1146b50e8af87dc9da25cf6d8633e91dac07e1a Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Sun, 16 May 2021 13:46:06 +0000 Subject: testsuite/arm: Improve unsigned-float.c The test requires an FPU, so use -march=armv7-a+fp -mfpu=auto instead of -march=armv7-a. We also remove dg-require-effective-target arm_fp_ok, but keep dg-add-options arm_fp: this enables the test to pass on arm-eabi configured with default cpu/fpu/mode. dg-require-effective-target arm_fp_ok fails on such a configuration for lack of FPU, since dg-options are not taken into account by dg-require-effective-target. Add -march=armv7-a+fp -mfpu=auto is sufficient for arm_fp options to be acceptable. This enables the test to pass on all the arm-eabi configurations I'm testing, as well as arm-linux-gnueabi when forcing -march=armv5t. 2021-05-16 Christophe Lyon gcc/testsuite/ * gcc.target/arm/unsigned-float.c: Remove arm_fp_ok, adjust dg-options. --- gcc/testsuite/gcc.target/arm/unsigned-float.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/arm/unsigned-float.c b/gcc/testsuite/gcc.target/arm/unsigned-float.c index ad589d9..ea3abc7 100644 --- a/gcc/testsuite/gcc.target/arm/unsigned-float.c +++ b/gcc/testsuite/gcc.target/arm/unsigned-float.c @@ -1,8 +1,8 @@ /* { dg-do compile } */ -/* { dg-require-effective-target arm_fp_ok } */ -/* { dg-skip-if "need fp instructions" { *-*-* } { "-mfloat-abi=soft" } { "" } } */ /* { dg-skip-if "-mpure-code supports M-profile only" { *-*-* } { "-mpure-code" } } */ -/* { dg-options "-march=armv7-a -O1" } */ +/* { dg-options "-march=armv7-a+fp -mfpu=auto -O1" } */ +/* Do not require arm_ok effective target to avoid skipping on arm-eabi with + default configure options. */ /* { dg-add-options arm_fp } */ -- cgit v1.1 From 4a322345cab10879162a2ddf659fb0f873ba0182 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Sun, 16 May 2021 13:48:21 +0000 Subject: arm: remove error in CPP_SPEC when -mlittle-endian and -mbig-endian are used together arm.h has had this error message since 1997, but it is no longer needed since option parsing has been improved: -mXXX-endian is handled via arm.opt and updates the BIG_END mask. So, the last instance of -mXXX-endian on the command line wins. Tested on many arm* configurations, with no impact on the testsuite results. 2021-05-16 Christophe Lyon gcc/ * config/arm/arm.h (CPP_SPEC): Remove error message about -mlittle-endian/-mbig-endian conflict. --- gcc/config/arm/arm.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index e430e4d..8e5bd57 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -89,9 +89,7 @@ extern tree arm_bf16_ptr_type_node; #undef CPP_SPEC -#define CPP_SPEC "%(subtarget_cpp_spec) \ -%{mbig-endian:%{mlittle-endian: \ - %e-mbig-endian and -mlittle-endian may not be used together}}" +#define CPP_SPEC "%(subtarget_cpp_spec)" #ifndef CC1_SPEC #define CC1_SPEC "" -- cgit v1.1 From 2fa3e5740b87085f82970887ddacfc877cdedbff Mon Sep 17 00:00:00 2001 From: David Edelsohn Date: Fri, 14 May 2021 12:45:59 -0400 Subject: testsuite: Require fsanitize support on the target. * g++.dg/warn/uninit-pr93100.C: Require fsantize support. --- gcc/testsuite/g++.dg/warn/uninit-pr93100.C | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C index c9cd3ef..56dc894 100644 --- a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C +++ b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C @@ -1,5 +1,6 @@ /* PR tree-optimization/98508 - Sanitizer disable -Wall and -Wextra { dg-do compile } + { dg-require-effective-target no_fsanitize_address } { dg-options "-O0 -Wall -fsanitize=address" } */ struct S -- cgit v1.1 From e49ff61d41979d024714ca1b44d6c969bbb59d06 Mon Sep 17 00:00:00 2001 From: David Edelsohn Date: Sat, 15 May 2021 15:24:56 -0400 Subject: testsuite: Silence psabi warning * g++.dg/ext/attrib63.C: Add -Wno-psabi option. --- gcc/testsuite/g++.dg/ext/attrib63.C | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/ext/attrib63.C b/gcc/testsuite/g++.dg/ext/attrib63.C index e515a2b..93bde1e 100644 --- a/gcc/testsuite/g++.dg/ext/attrib63.C +++ b/gcc/testsuite/g++.dg/ext/attrib63.C @@ -1,4 +1,5 @@ // { dg-do compile } +// { dg-additional-options "-Wno-psabi" } #define vector __attribute__((vector_size(16))) class A { -- cgit v1.1 From 1dfb5d8ab52c3c76c877077d8d6dc4eaae3c6153 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 17 May 2021 00:16:31 +0000 Subject: Daily bump. --- gcc/ChangeLog | 5 +++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 13 +++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6a49afe..eeb293a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2021-05-16 Christophe Lyon + + * config/arm/arm.h (CPP_SPEC): Remove error message about + -mlittle-endian/-mbig-endian conflict. + 2021-05-15 Bill Schmidt * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index a271d95..915a0b2 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210516 +20210517 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 26b04e7..936f37a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2021-05-16 David Edelsohn + + * g++.dg/ext/attrib63.C: Add -Wno-psabi option. + +2021-05-16 David Edelsohn + + * g++.dg/warn/uninit-pr93100.C: Require fsantize support. + +2021-05-16 Christophe Lyon + + * gcc.target/arm/unsigned-float.c: Remove arm_fp_ok, adjust + dg-options. + 2021-05-15 Bill Schmidt * gcc.target/powerpc/rop-1.c: New. -- cgit v1.1 From b050cf6a4d9c305daff4a96e5a2489ece69dc287 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 17 May 2021 09:25:43 +0000 Subject: testsuite: Require openmp effective-target for PR100515 The related test uses -fopenmp, which is not supported by newlib-based targets such as arm-eabi or aarch64-elf. Requiring the openmp effective-target makes the test unsupported rather than failed. 2021-05-17 Christophe Lyon PR debug/100515 gcc/testsuite * gcc.dg/debug/dwarf2/pr100515.c: Require openmp effective-target. --- gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c index 7c72fcd..17f6463 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr100515.c @@ -1,5 +1,6 @@ /* PR debug/100515 */ /* { dg-do compile } */ +/* { dg-require-effective-target fopenmp } */ /* { dg-options "-g -O2 -fopenmp" } */ void -- cgit v1.1 From 3cbcb5d0cfcd1713867ded483cb81148e2ccf0fc Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 13 May 2021 13:41:17 +0200 Subject: LTO: merge -flto=foo both from IL and linker cmdline gcc/ChangeLog: * lto-wrapper.c (merge_flto_options): Factor out a new function. (merge_and_complain): Use it. (run_gcc): Merge also linker command line -flto=foo argument with IL files. --- gcc/lto-wrapper.c | 118 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 53 deletions(-) (limited to 'gcc') diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index a71d614..1c26439 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -189,6 +189,37 @@ find_option (vec &options, cl_decoded_option *option) return find_option (options, option->opt_index); } +/* Merge -flto FOPTION into vector of DECODED_OPTIONS. */ + +static void +merge_flto_options (vec &decoded_options, + cl_decoded_option *foption) +{ + int existing_opt = find_option (decoded_options, foption); + if (existing_opt == -1) + decoded_options.safe_push (*foption); + else + { + if (strcmp (foption->arg, decoded_options[existing_opt].arg) != 0) + { + /* -flto=auto is preferred. */ + if (strcmp (decoded_options[existing_opt].arg, "auto") == 0) + ; + else if (strcmp (foption->arg, "auto") == 0 + || strcmp (foption->arg, "jobserver") == 0) + decoded_options[existing_opt].arg = foption->arg; + else if (strcmp (decoded_options[existing_opt].arg, + "jobserver") != 0) + { + int n = atoi (foption->arg); + int original_n = atoi (decoded_options[existing_opt].arg); + if (n > original_n) + decoded_options[existing_opt].arg = foption->arg; + } + } + } +} + /* Try to merge and complain about options FDECODED_OPTIONS when applied ontop of DECODED_OPTIONS. */ @@ -427,28 +458,7 @@ merge_and_complain (vec decoded_options, break; case OPT_flto_: - if (existing_opt == -1) - decoded_options.safe_push (*foption); - else - { - if (strcmp (foption->arg, decoded_options[existing_opt].arg) != 0) - { - /* -flto=auto is preferred. */ - if (strcmp (decoded_options[existing_opt].arg, "auto") == 0) - ; - else if (strcmp (foption->arg, "auto") == 0 - || strcmp (foption->arg, "jobserver") == 0) - decoded_options[existing_opt].arg = foption->arg; - else if (strcmp (decoded_options[existing_opt].arg, - "jobserver") != 0) - { - int n = atoi (foption->arg); - int original_n = atoi (decoded_options[existing_opt].arg); - if (n > original_n) - decoded_options[existing_opt].arg = foption->arg; - } - } - } + merge_flto_options (decoded_options, foption); break; } } @@ -1515,37 +1525,6 @@ run_gcc (unsigned argc, char *argv[]) append_compiler_options (&argv_obstack, fdecoded_options); append_linker_options (&argv_obstack, decoded_options); - /* Process LTO-related options on merged options. */ - for (j = 1; j < fdecoded_options.length (); ++j) - { - cl_decoded_option *option = &fdecoded_options[j]; - switch (option->opt_index) - { - case OPT_flto_: - if (strcmp (option->arg, "jobserver") == 0) - { - parallel = 1; - jobserver = 1; - } - else if (strcmp (option->arg, "auto") == 0) - { - parallel = 1; - auto_parallel = 1; - } - else - { - parallel = atoi (option->arg); - if (parallel <= 1) - parallel = 0; - } - /* Fallthru. */ - - case OPT_flto: - lto_mode = LTO_MODE_WHOPR; - break; - } - } - /* Scan linker driver arguments for things that are of relevance to us. */ for (j = 1; j < decoded_options.length (); ++j) { @@ -1574,6 +1553,8 @@ run_gcc (unsigned argc, char *argv[]) break; case OPT_flto_: + /* Merge linker -flto= option with what we have in IL files. */ + merge_flto_options (fdecoded_options, option); if (strcmp (option->arg, "jobserver") == 0) jobserver_requested = true; break; @@ -1596,6 +1577,37 @@ run_gcc (unsigned argc, char *argv[]) } } + /* Process LTO-related options on merged options. */ + for (j = 1; j < fdecoded_options.length (); ++j) + { + cl_decoded_option *option = &fdecoded_options[j]; + switch (option->opt_index) + { + case OPT_flto_: + if (strcmp (option->arg, "jobserver") == 0) + { + parallel = 1; + jobserver = 1; + } + else if (strcmp (option->arg, "auto") == 0) + { + parallel = 1; + auto_parallel = 1; + } + else + { + parallel = atoi (option->arg); + if (parallel <= 1) + parallel = 0; + } + /* Fallthru. */ + + case OPT_flto: + lto_mode = LTO_MODE_WHOPR; + break; + } + } + /* Output lto-wrapper invocation command. */ if (verbose) { -- cgit v1.1 From a8e19fa4198ea2504c89d01741d11766e0e9e91b Mon Sep 17 00:00:00 2001 From: Joern Rennecke Date: Mon, 17 May 2021 10:57:23 +0100 Subject: Avoid outputting corrupt string constructor when host/target chars mismatch. * c-common.c (braced_list_to_string): Return CTOR unchanged if host and target character sizes don't match. --- gcc/c-family/c-common.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'gcc') diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 7bd799d..b7daa2e 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -9059,6 +9059,12 @@ braced_list_to_string (tree type, tree ctor, bool member) if (!member && !tree_fits_uhwi_p (typesize)) return ctor; + /* If the target char size differes from the host char size, we'd risk + loosing data and getting object sizes wrong by converting to + host chars. */ + if (TYPE_PRECISION (char_type_node) != CHAR_BIT) + return ctor; + /* If the array has an explicit bound, use it to constrain the size of the string. If it doesn't, be sure to create a string that's as long as implied by the index of the last zero specified via -- cgit v1.1 From 582776eb1b62c32f5234566a01ea92247b7d6bcc Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Mon, 17 May 2021 13:20:27 +0200 Subject: OpenMP/Fortran: Reject nonintrinsic assignments in OMP WORKSHARE [PR100633] PR fortran/100633 gcc/fortran/ChangeLog: * resolve.c (gfc_resolve_code): Reject nonintrinsic assignments in OMP WORKSHARE. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/workshare-59.f90: New test. --- gcc/fortran/resolve.c | 6 ++++++ gcc/testsuite/gfortran.dg/gomp/workshare-59.f90 | 26 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 gcc/testsuite/gfortran.dg/gomp/workshare-59.f90 (limited to 'gcc') diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index c02bbed..747516f 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -11940,6 +11940,12 @@ start: if (resolve_ordinary_assign (code, ns)) { + if (omp_workshare_flag) + { + gfc_error ("Expected intrinsic assignment in OMP WORKSHARE " + "at %L", &code->loc); + break; + } if (code->op == EXEC_COMPCALL) goto compcall; else diff --git a/gcc/testsuite/gfortran.dg/gomp/workshare-59.f90 b/gcc/testsuite/gfortran.dg/gomp/workshare-59.f90 new file mode 100644 index 0000000..65d04c2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/workshare-59.f90 @@ -0,0 +1,26 @@ +! PR fortran/100633 + +module defined_assign + interface assignment(=) + module procedure work_assign + end interface + + contains + subroutine work_assign(a,b) + integer, intent(out) :: a + logical, intent(in) :: b(:) + end subroutine work_assign +end module defined_assign + +program omp_workshare + use defined_assign + + integer :: a + logical :: l(10) + l = .TRUE. + + !$omp workshare + a = l ! { dg-error "Expected intrinsic assignment in OMP WORKSHARE" } + !$omp end workshare + +end program omp_workshare -- cgit v1.1 From 325187841aa66f0d03403d41fe9e696d094588b9 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 17 May 2021 11:53:14 +0000 Subject: testsuite/arm: Fix and rename arm_qbit_ok into arm_sat_ok effective-target The acle/saturation.c test uses __[su]sat() and __saturation_occurred() intrinsics but __[su]sat() are defined in acle.h if __ARM_FEATURE_SAT true, while __saturation_occurred() depends on __ARM_FEATURE_QBIT. QBIT is a v5te feature, while SAT is available since v6, so the test really needs __ARM_FEATURE_SAT, to have both available. This patch renames arm_qbit_ok into arm_sat_ok and checks __ARM_FEATURE_SAT. It updates acle/saturation.c accordingly. This enables the test to pass on arm-eabi with default cpu/fpu/mode, where arm_qbit previously used -march=armv5te instead of armv6 now. 2021-05-17 Christophe Lyon gcc/ * doc/sourcebuild.texi (arm_qbit_ok): Rename into... (arm_sat_ok): ...this. gcc/testsuite/ * gcc.target/arm/acle/saturation.c: Use arm_sat_ok effective target. * lib/target-supports.exp (check_effective_target_arm_qbit_ok_nocache): Rename into... (check_effective_target_arm_sat_ok_nocache): ... this. Check __ARM_FEATURE_SAT and use armv6. --- gcc/doc/sourcebuild.texi | 6 ++-- gcc/testsuite/gcc.target/arm/acle/saturation.c | 4 +-- gcc/testsuite/lib/target-supports.exp | 42 +++++++++++++------------- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'gcc') diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 3a1d653..ceb6b99 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2125,9 +2125,9 @@ ARM Target supports options suitable for accessing the SIMD32 intrinsics from @code{arm_acle.h}. Some multilibs may be incompatible with these options. -@item arm_qbit_ok -@anchor{arm_qbit_ok} -ARM Target supports options suitable for accessing the Q-bit manipulation +@item arm_sat_ok +@anchor{arm_sat_ok} +ARM Target supports options suitable for accessing the saturation intrinsics from @code{arm_acle.h}. Some multilibs may be incompatible with these options. diff --git a/gcc/testsuite/gcc.target/arm/acle/saturation.c b/gcc/testsuite/gcc.target/arm/acle/saturation.c index 0b3fe51..a9f99e5 100644 --- a/gcc/testsuite/gcc.target/arm/acle/saturation.c +++ b/gcc/testsuite/gcc.target/arm/acle/saturation.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-require-effective-target arm_qbit_ok } */ -/* { dg-add-options arm_qbit } */ +/* { dg-require-effective-target arm_sat_ok } */ +/* { dg-add-options arm_sat } */ #include diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 5700c23..8192da5 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -4180,24 +4180,24 @@ proc add_options_for_arm_simd32 { flags } { return "$flags $et_arm_simd32_flags" } -# Return 1 if this is an ARM target supporting the saturation intrinsics -# from arm_acle.h. Some multilibs may be incompatible with these options. -# Also set et_arm_qbit_flags to the best options to add. -# arm_acle.h includes stdint.h which can cause trouble with incompatible -# -mfloat-abi= options. - -proc check_effective_target_arm_qbit_ok_nocache { } { - global et_arm_qbit_flags - set et_arm_qbit_flags "" - foreach flags {"" "-march=armv5te" "-march=armv5te -mfloat-abi=softfp" "-march=armv5te -mfloat-abi=hard"} { - if { [check_no_compiler_messages_nocache et_arm_qbit_flags object { +# Return 1 if this is an ARM target supporting the __ssat and __usat +# saturation intrinsics from arm_acle.h. Some multilibs may be +# incompatible with these options. Also set et_arm_sat_flags to the +# best options to add. arm_acle.h includes stdint.h which can cause +# trouble with incompatible -mfloat-abi= options. + +proc check_effective_target_arm_sat_ok_nocache { } { + global et_arm_sat_flags + set et_arm_sat_flags "" + foreach flags {"" "-march=armv6" "-march=armv6 -mfloat-abi=softfp" "-march=armv6 -mfloat-abi=hard -mfpu=vfp"} { + if { [check_no_compiler_messages_nocache et_arm_sat_flags object { #include int dummy; - #ifndef __ARM_FEATURE_QBIT - #error not QBIT + #ifndef __ARM_FEATURE_SAT + #error not SAT #endif } "$flags"] } { - set et_arm_qbit_flags $flags + set et_arm_sat_flags $flags return 1 } } @@ -4205,17 +4205,17 @@ proc check_effective_target_arm_qbit_ok_nocache { } { return 0 } -proc check_effective_target_arm_qbit_ok { } { - return [check_cached_effective_target et_arm_qbit_flags \ - check_effective_target_arm_qbit_ok_nocache] +proc check_effective_target_arm_sat_ok { } { + return [check_cached_effective_target et_arm_sat_flags \ + check_effective_target_arm_sat_ok_nocache] } -proc add_options_for_arm_qbit { flags } { - if { ! [check_effective_target_arm_qbit_ok] } { +proc add_options_for_arm_sat { flags } { + if { ! [check_effective_target_arm_sat_ok] } { return "$flags" } - global et_arm_qbit_flags - return "$flags $et_arm_qbit_flags" + global et_arm_sat_flags + return "$flags $et_arm_sat_flags" } # Return 1 if this is an ARM target supporting the DSP intrinsics from -- cgit v1.1 From e87d568e9e3e331e22850127308abedd0642e5e8 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 17 May 2021 11:57:30 +0000 Subject: testsuite/arm: Improve mve-vshr.c Vector right shifts by immediate use vshr, while right shifts by vectors instead use vneg and vshl. This patch adds the corresponding scan-assembler-times that were missing. 2021-05-17 Christophe Lyon gcc/testsuite/ * gcc.target/arm/simd/mve-vshr.c: Add more scan-assembler-times. --- gcc/testsuite/gcc.target/arm/simd/mve-vshr.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vshr.c b/gcc/testsuite/gcc.target/arm/simd/mve-vshr.c index d4e658c..d4258e9 100644 --- a/gcc/testsuite/gcc.target/arm/simd/mve-vshr.c +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vshr.c @@ -55,5 +55,12 @@ FUNC_IMM(u, uint, 8, 16, >>, vshrimm) /* MVE has only 128-bit vectors, so we can vectorize only half of the functions above. */ +/* Vector right shifts use vneg and left shifts. */ +/* { dg-final { scan-assembler-times {vshl.s[0-9]+\tq[0-9]+, q[0-9]+} 3 } } */ +/* { dg-final { scan-assembler-times {vshl.u[0-9]+\tq[0-9]+, q[0-9]+} 3 } } */ +/* { dg-final { scan-assembler-times {vneg.s[0-9]+ q[0-9]+, q[0-9]+} 6 } } */ + + +/* Shift by immediate. */ /* { dg-final { scan-assembler-times {vshr.s[0-9]+\tq[0-9]+, q[0-9]+} 3 } } */ /* { dg-final { scan-assembler-times {vshr.u[0-9]+\tq[0-9]+, q[0-9]+} 3 } } */ -- cgit v1.1 From afa4401edd8a6a882848a6613d5441b0d0a10587 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 17 May 2021 11:59:01 +0000 Subject: testsuite/arm: Factorize and increase coverage in mve-sub_1.c Use a template macro to factorize the existing test functions. This patch also adds a version to check subtraction with __fp16 type. 2021-05-17 Christophe Lyon gcc/testsuite/ * gcc.target/arm/simd/mve-vsub_1.c: Factorize and add __fp16 test. --- gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c | 60 +++++++++----------------- 1 file changed, 21 insertions(+), 39 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c b/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c index 842e5c6..5a6c345 100644 --- a/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vsub_1.c @@ -5,60 +5,42 @@ #include -void test_vsub_i32 (int32_t * dest, int32_t * a, int32_t * b) { - int i; - for (i=0; i<4; i++) { - dest[i] = a[i] - b[i]; - } +#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \ + void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, \ + TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \ + int i; \ + for (i=0; i Date: Mon, 17 May 2021 12:00:07 +0000 Subject: testsuite/arm: Add mve-vadd-1.c test Support for vadd has been present for a while, but it was lacking a test. 2021-05-17 Christophe Lyon gcc/testsuite/ * gcc.target/arm/simd/mve-vadd-1.c: New. --- gcc/testsuite/gcc.target/arm/simd/mve-vadd-1.c | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-vadd-1.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vadd-1.c b/gcc/testsuite/gcc.target/arm/simd/mve-vadd-1.c new file mode 100644 index 0000000..15a9daa --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vadd-1.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3" } */ + +#include + +#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \ + void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, \ + TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \ + int i; \ + for (i=0; i Date: Mon, 17 May 2021 12:02:40 +0000 Subject: testsuite/arm: Add mve-vadd-scalar-1.c test This patch adds a test for the scalar mode of vadd, precisely noting that we do not yet use the T2 variants of vadd, which take a scalar as final argument. 2021-05-17 Christophe Lyon gcc/testsuite/ * gcc.target/arm/simd/mve-vadd-scalar-1.c: New. --- .../gcc.target/arm/simd/mve-vadd-scalar-1.c | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-vadd-scalar-1.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vadd-scalar-1.c b/gcc/testsuite/gcc.target/arm/simd/mve-vadd-scalar-1.c new file mode 100644 index 0000000..bbf70e1 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vadd-scalar-1.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3" } */ + +#include + +#define FUNC_IMM(SIGN, TYPE, BITS, NB, OP, NAME) \ + void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, \ + TYPE##BITS##_t *a) { \ + int i; \ + for (i=0; i Date: Thu, 13 May 2021 13:08:16 +0800 Subject: Fix ICE [PR target/100549] When arg0 is same as arg1 in __builtin_ia32_pcmpgtw, gimple_build (&stmts, GT_EXPR, cmp_type, arg0, arg1) will simplify the comparison to vector constant 0, no stmts is generated, which causes ICE in gsi_insert_before (gsi, stmts, GSI_SAME_STMT). So use gsi_insert_seq_before instead which will handle NULL seq. gcc/ChangeLog: PR target/100549 * config/i386/i386.c (ix86_gimple_fold_builtin): Use gsi_insert_seq_before instead. gcc/testsuite/ChangeLog: PR target/100549 * gcc.target/i386/pr100549.c: New test. --- gcc/config/i386/i386.c | 4 +- gcc/testsuite/gcc.target/i386/pr100549.c | 108 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr100549.c (limited to 'gcc') diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 6a1f574..befe69e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -18000,8 +18000,8 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi) tree cmp_type = truth_type_for (type); gimple_seq stmts = NULL; tree cmp = gimple_build (&stmts, tcode, cmp_type, arg0, arg1); - gsi_insert_before (gsi, stmts, GSI_SAME_STMT); - gimple *g = gimple_build_assign (gimple_call_lhs (stmt), + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + gimple* g = gimple_build_assign (gimple_call_lhs (stmt), VEC_COND_EXPR, cmp, minus_one_vec, zero_vec); gimple_set_location (g, loc); diff --git a/gcc/testsuite/gcc.target/i386/pr100549.c b/gcc/testsuite/gcc.target/i386/pr100549.c new file mode 100644 index 0000000..83bba3c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100549.c @@ -0,0 +1,108 @@ +/* PR target/100549 */ +/* { dg-do compile } */ +/* { dg-options "-O -mavx2" } */ + +typedef char v16qi __attribute__ ((vector_size (16))); +typedef char v32qi __attribute__ ((vector_size (32))); +typedef short v8hi __attribute__ ((vector_size (16))); +typedef short v16hi __attribute__ ((vector_size (32))); +typedef int v4si __attribute__ ((vector_size (16))); +typedef int v8si __attribute__ ((vector_size (32))); +typedef long long v2di __attribute__ ((vector_size (16))); +typedef long long v4di __attribute__ ((vector_size (32))); + +v16qi +f1 (v16qi a) +{ + return __builtin_ia32_pcmpeqb128 (a, a); +} + +v8hi +f2 (v8hi a) +{ + return __builtin_ia32_pcmpeqw128 (a, a); +} + +v4si +f3 (v4si a) +{ + return __builtin_ia32_pcmpeqd128 (a, a); +} + +v2di +f4 (v2di a) +{ + return __builtin_ia32_pcmpeqq (a, a); +} + +v16qi +f5 (v16qi a) +{ + return __builtin_ia32_pcmpgtb128 (a, a); +} + +v8hi +f6 (v8hi a) +{ + return __builtin_ia32_pcmpgtw128 (a, a); +} + +v4si +f7 (v4si a) +{ + return __builtin_ia32_pcmpgtd128 (a, a); +} + +v2di +f8 (v2di a) +{ + return __builtin_ia32_pcmpgtq (a, a); +} + +v32qi +f9 (v32qi a) +{ + return __builtin_ia32_pcmpeqb256 (a, a); +} + +v16hi +f10 (v16hi a) +{ + return __builtin_ia32_pcmpeqw256 (a, a); +} + +v8si +f11 (v8si a) +{ + return __builtin_ia32_pcmpeqd256 (a, a); +} + +v4di +f12 (v4di a) +{ + return __builtin_ia32_pcmpeqq256 (a, a); +} + +v32qi +f13 (v32qi a) +{ + return __builtin_ia32_pcmpgtb256 (a, a); +} + +v16hi +f14 (v16hi a) +{ + return __builtin_ia32_pcmpgtw256 (a, a); +} + +v8si +f15 (v8si a) +{ + return __builtin_ia32_pcmpgtd256 (a, a); +} + +v4di +f16 (v4di a) +{ + return __builtin_ia32_pcmpgtq256 (a, a); +} -- cgit v1.1 From a6eacbf1055520e968d1a25f6d30d6ff4b66272d Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 17 May 2021 12:29:42 +0000 Subject: arm: Auto-vectorization for MVE: vcmp Since MVE has a different set of vector comparison operators from Neon, we have to update the expansion to take into account the new ones, for instance 'NE' for which MVE does not require to use 'EQ' with the inverted condition. Conversely, Neon supports comparisons with #0, MVE does not. For: typedef long int vs32 __attribute__((vector_size(16))); vs32 cmp_eq_vs32_reg (vs32 a, vs32 b) { return a == b; } we now generate: cmp_eq_vs32_reg: vldr.64 d4, .L123 @ 8 [c=8 l=4] *mve_movv4si/8 vldr.64 d5, .L123+8 vldr.64 d6, .L123+16 @ 9 [c=8 l=4] *mve_movv4si/8 vldr.64 d7, .L123+24 vcmp.i32 eq, q0, q1 @ 7 [c=16 l=4] mve_vcmpeqq_v4si vpsel q0, q3, q2 @ 15 [c=8 l=4] mve_vpselq_sv4si bx lr @ 26 [c=8 l=4] *thumb2_return .L124: .align 3 .L123: .word 0 .word 0 .word 0 .word 0 .word 1 .word 1 .word 1 .word 1 For some reason emit_move_insn (zero, CONST0_RTX (cmp_mode)) produces a pair of vldr instead of vmov.i32, qX, #0 2021-05-17 Christophe Lyon gcc/ * config/arm/arm-protos.h (arm_expand_vector_compare): Update prototype. * config/arm/arm.c (arm_expand_vector_compare): Add support for MVE. (arm_expand_vcond): Likewise. * config/arm/iterators.md (supf): Remove VCMPNEQ_S, VCMPEQQ_S, VCMPEQQ_N_S, VCMPNEQ_N_S. (VCMPNEQ, VCMPEQQ, VCMPEQQ_N, VCMPNEQ_N): Remove. * config/arm/mve.md (@mve_vcmpq_): Add '@' prefix. (@mve_vcmpq_f): Likewise. (@mve_vcmpq_n_f): Likewise. (@mve_vpselq_): Likewise. (@mve_vpselq_f"): Likewise. * config/arm/neon.md (vec_cmp): Likewise. (vcond): Likewise. (vcond): Likewise. (vcondu): Likewise. (vcond_mask_): Likewise. * config/arm/unspecs.md (VCMPNEQ_U, VCMPNEQ_S, VCMPEQQ_S) (VCMPEQQ_N_S, VCMPNEQ_N_S, VCMPEQQ_U, CMPEQQ_N_U, VCMPNEQ_N_U) (VCMPGEQ_N_S, VCMPGEQ_S, VCMPGTQ_N_S, VCMPGTQ_S, VCMPLEQ_N_S) (VCMPLEQ_S, VCMPLTQ_N_S, VCMPLTQ_S, VCMPCSQ_N_U, VCMPCSQ_U) (VCMPHIQ_N_U, VCMPHIQ_U): Remove. * config/arm/vec-common.md (vec_cmp): Likewise. (vcond): Likewise. (vcond): Likewise. (vcondu): Likewise. (vcond_mask_): Likewise. Added unsafe math condition. gcc/testsuite * gcc.target/arm/simd/mve-compare-1.c: New test with GCC vectors. * gcc.target/arm/simd/mve-compare-2.c: New test with GCC vectors. * gcc.target/arm/simd/mve-compare-scalar-1.c: New test with GCC vectors. * gcc.target/arm/simd/mve-vcmp-f32.c: New test for auto-vectorization. * gcc.target/arm/simd/mve-vcmp.c: New test for auto-vectorization. --- gcc/config/arm/arm-protos.h | 2 +- gcc/config/arm/arm.c | 211 ++++++++++++++++----- gcc/config/arm/iterators.md | 9 +- gcc/config/arm/mve.md | 10 +- gcc/config/arm/neon.md | 87 --------- gcc/config/arm/unspecs.md | 20 -- gcc/config/arm/vec-common.md | 108 +++++++++++ gcc/testsuite/gcc.target/arm/simd/mve-compare-1.c | 80 ++++++++ gcc/testsuite/gcc.target/arm/simd/mve-compare-2.c | 38 ++++ .../gcc.target/arm/simd/mve-compare-scalar-1.c | 69 +++++++ gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f32.c | 30 +++ gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c | 50 +++++ 12 files changed, 548 insertions(+), 166 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-compare-1.c create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-compare-2.c create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-compare-scalar-1.c create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f32.c create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c (limited to 'gcc') diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 2521541..ffccaa7 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -373,7 +373,7 @@ extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx, extern bool arm_fusion_enabled_p (tune_params::fuse_ops); extern bool arm_valid_symbolic_address_p (rtx); extern bool arm_validize_comparison (rtx *, rtx *, rtx *); -extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool); +extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool, bool); #endif /* RTX_CODE */ extern bool arm_gen_setmem (rtx *); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d0c0c50..eee3671 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -30959,66 +30959,113 @@ arm_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem, and return true if TARGET contains the inverse. If !CAN_INVERT, always store the result in TARGET, never its inverse. + If VCOND_MVE, do not emit the vpsel instruction here, let arm_expand_vcond do + it with the right destination type to avoid emiting two vpsel, one here and + one in arm_expand_vcond. + Note that the handling of floating-point comparisons is not IEEE compliant. */ bool arm_expand_vector_compare (rtx target, rtx_code code, rtx op0, rtx op1, - bool can_invert) + bool can_invert, bool vcond_mve) { machine_mode cmp_result_mode = GET_MODE (target); machine_mode cmp_mode = GET_MODE (op0); bool inverted; - switch (code) - { - /* For these we need to compute the inverse of the requested - comparison. */ - case UNORDERED: - case UNLT: - case UNLE: - case UNGT: - case UNGE: - case UNEQ: - case NE: - code = reverse_condition_maybe_unordered (code); - if (!can_invert) - { - /* Recursively emit the inverted comparison into a temporary - and then store its inverse in TARGET. This avoids reusing - TARGET (which for integer NE could be one of the inputs). */ - rtx tmp = gen_reg_rtx (cmp_result_mode); - if (arm_expand_vector_compare (tmp, code, op0, op1, true)) - gcc_unreachable (); - emit_insn (gen_rtx_SET (target, gen_rtx_NOT (cmp_result_mode, tmp))); - return false; - } - inverted = true; - break; - default: + /* MVE supports more comparisons than Neon. */ + if (TARGET_HAVE_MVE) inverted = false; - break; - } + else + switch (code) + { + /* For these we need to compute the inverse of the requested + comparison. */ + case UNORDERED: + case UNLT: + case UNLE: + case UNGT: + case UNGE: + case UNEQ: + case NE: + code = reverse_condition_maybe_unordered (code); + if (!can_invert) + { + /* Recursively emit the inverted comparison into a temporary + and then store its inverse in TARGET. This avoids reusing + TARGET (which for integer NE could be one of the inputs). */ + rtx tmp = gen_reg_rtx (cmp_result_mode); + if (arm_expand_vector_compare (tmp, code, op0, op1, true, vcond_mve)) + gcc_unreachable (); + emit_insn (gen_rtx_SET (target, gen_rtx_NOT (cmp_result_mode, tmp))); + return false; + } + inverted = true; + break; + + default: + inverted = false; + break; + } switch (code) { - /* These are natively supported for zero comparisons, but otherwise - require the operands to be swapped. */ + /* These are natively supported by Neon for zero comparisons, but otherwise + require the operands to be swapped. For MVE, we can only compare + registers. */ case LE: case LT: - if (op1 != CONST0_RTX (cmp_mode)) - { - code = swap_condition (code); - std::swap (op0, op1); - } + if (!TARGET_HAVE_MVE) + if (op1 != CONST0_RTX (cmp_mode)) + { + code = swap_condition (code); + std::swap (op0, op1); + } /* Fall through. */ - /* These are natively supported for both register and zero operands. */ + /* These are natively supported by Neon for both register and zero + operands. MVE supports registers only. */ case EQ: case GE: case GT: - emit_insn (gen_neon_vc (code, cmp_mode, target, op0, op1)); + case NE: + if (TARGET_HAVE_MVE) + { + rtx vpr_p0; + if (vcond_mve) + vpr_p0 = target; + else + vpr_p0 = gen_reg_rtx (HImode); + + switch (GET_MODE_CLASS (cmp_mode)) + { + case MODE_VECTOR_INT: + emit_insn (gen_mve_vcmpq (code, cmp_mode, vpr_p0, op0, force_reg (cmp_mode, op1))); + break; + case MODE_VECTOR_FLOAT: + if (TARGET_HAVE_MVE_FLOAT) + emit_insn (gen_mve_vcmpq_f (code, cmp_mode, vpr_p0, op0, force_reg (cmp_mode, op1))); + else + gcc_unreachable (); + break; + default: + gcc_unreachable (); + } + + /* If we are not expanding a vcond, build the result here. */ + if (!vcond_mve) + { + rtx zero = gen_reg_rtx (cmp_result_mode); + rtx one = gen_reg_rtx (cmp_result_mode); + emit_move_insn (zero, CONST0_RTX (cmp_result_mode)); + emit_move_insn (one, CONST1_RTX (cmp_result_mode)); + emit_insn (gen_mve_vpselq (VPSELQ_S, cmp_result_mode, target, one, zero, vpr_p0)); + } + } + else + emit_insn (gen_neon_vc (code, cmp_mode, target, op0, op1)); return inverted; /* These are natively supported for register operands only. @@ -31026,16 +31073,54 @@ arm_expand_vector_compare (rtx target, rtx_code code, rtx op0, rtx op1, or canonicalized by target-independent code. */ case GEU: case GTU: - emit_insn (gen_neon_vc (code, cmp_mode, target, - op0, force_reg (cmp_mode, op1))); + if (TARGET_HAVE_MVE) + { + rtx vpr_p0; + if (vcond_mve) + vpr_p0 = target; + else + vpr_p0 = gen_reg_rtx (HImode); + + emit_insn (gen_mve_vcmpq (code, cmp_mode, vpr_p0, op0, force_reg (cmp_mode, op1))); + if (!vcond_mve) + { + rtx zero = gen_reg_rtx (cmp_result_mode); + rtx one = gen_reg_rtx (cmp_result_mode); + emit_move_insn (zero, CONST0_RTX (cmp_result_mode)); + emit_move_insn (one, CONST1_RTX (cmp_result_mode)); + emit_insn (gen_mve_vpselq (VPSELQ_S, cmp_result_mode, target, one, zero, vpr_p0)); + } + } + else + emit_insn (gen_neon_vc (code, cmp_mode, target, + op0, force_reg (cmp_mode, op1))); return inverted; /* These require the operands to be swapped and likewise do not support comparisons with zero. */ case LEU: case LTU: - emit_insn (gen_neon_vc (swap_condition (code), cmp_mode, - target, force_reg (cmp_mode, op1), op0)); + if (TARGET_HAVE_MVE) + { + rtx vpr_p0; + if (vcond_mve) + vpr_p0 = target; + else + vpr_p0 = gen_reg_rtx (HImode); + + emit_insn (gen_mve_vcmpq (swap_condition (code), cmp_mode, vpr_p0, force_reg (cmp_mode, op1), op0)); + if (!vcond_mve) + { + rtx zero = gen_reg_rtx (cmp_result_mode); + rtx one = gen_reg_rtx (cmp_result_mode); + emit_move_insn (zero, CONST0_RTX (cmp_result_mode)); + emit_move_insn (one, CONST1_RTX (cmp_result_mode)); + emit_insn (gen_mve_vpselq (VPSELQ_S, cmp_result_mode, target, one, zero, vpr_p0)); + } + } + else + emit_insn (gen_neon_vc (swap_condition (code), cmp_mode, + target, force_reg (cmp_mode, op1), op0)); return inverted; /* These need a combination of two comparisons. */ @@ -31047,8 +31132,8 @@ arm_expand_vector_compare (rtx target, rtx_code code, rtx op0, rtx op1, rtx gt_res = gen_reg_rtx (cmp_result_mode); rtx alt_res = gen_reg_rtx (cmp_result_mode); rtx_code alt_code = (code == LTGT ? LT : LE); - if (arm_expand_vector_compare (gt_res, GT, op0, op1, true) - || arm_expand_vector_compare (alt_res, alt_code, op0, op1, true)) + if (arm_expand_vector_compare (gt_res, GT, op0, op1, true, vcond_mve) + || arm_expand_vector_compare (alt_res, alt_code, op0, op1, true, vcond_mve)) gcc_unreachable (); emit_insn (gen_rtx_SET (target, gen_rtx_IOR (cmp_result_mode, gt_res, alt_res))); @@ -31066,13 +31151,47 @@ arm_expand_vector_compare (rtx target, rtx_code code, rtx op0, rtx op1, void arm_expand_vcond (rtx *operands, machine_mode cmp_result_mode) { - rtx mask = gen_reg_rtx (cmp_result_mode); + /* When expanding for MVE, we do not want to emit a (useless) vpsel in + arm_expand_vector_compare, and another one here. */ + bool vcond_mve=false; + rtx mask; + + if (TARGET_HAVE_MVE) + { + vcond_mve=true; + mask = gen_reg_rtx (HImode); + } + else + mask = gen_reg_rtx (cmp_result_mode); + bool inverted = arm_expand_vector_compare (mask, GET_CODE (operands[3]), - operands[4], operands[5], true); + operands[4], operands[5], true, vcond_mve); if (inverted) std::swap (operands[1], operands[2]); + if (TARGET_NEON) emit_insn (gen_neon_vbsl (GET_MODE (operands[0]), operands[0], mask, operands[1], operands[2])); + else + { + machine_mode cmp_mode = GET_MODE (operands[4]); + rtx vpr_p0 = mask; + rtx zero = gen_reg_rtx (cmp_mode); + rtx one = gen_reg_rtx (cmp_mode); + emit_move_insn (zero, CONST0_RTX (cmp_mode)); + emit_move_insn (one, CONST1_RTX (cmp_mode)); + switch (GET_MODE_CLASS (cmp_mode)) + { + case MODE_VECTOR_INT: + emit_insn (gen_mve_vpselq (VPSELQ_S, cmp_result_mode, operands[0], one, zero, vpr_p0)); + break; + case MODE_VECTOR_FLOAT: + if (TARGET_HAVE_MVE_FLOAT) + emit_insn (gen_mve_vpselq_f (cmp_mode, operands[0], one, zero, vpr_p0)); + break; + default: + gcc_unreachable (); + } + } } #define MAX_VECT_LEN 16 diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 95df8bd..a128465 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -1288,12 +1288,11 @@ (VCREATEQ_U "u") (VCREATEQ_S "s") (VSHRQ_N_S "s") (VSHRQ_N_U "u") (VCVTQ_N_FROM_F_S "s") (VSHLQ_U "u") (VCVTQ_N_FROM_F_U "u") (VADDLVQ_P_S "s") (VSHLQ_S "s") - (VADDLVQ_P_U "u") (VCMPNEQ_S "s") + (VADDLVQ_P_U "u") (VABDQ_M_S "s") (VABDQ_M_U "u") (VABDQ_S "s") (VABDQ_U "u") (VADDQ_N_S "s") (VADDQ_N_U "u") (VADDVQ_P_S "s") (VADDVQ_P_U "u") (VBRSRQ_N_S "s") - (VBRSRQ_N_U "u") (VCMPEQQ_S "s") - (VCMPEQQ_N_S "s") (VCMPNEQ_N_S "s") + (VBRSRQ_N_U "u") (VHADDQ_N_S "s") (VHADDQ_N_U "u") (VHADDQ_S "s") (VHADDQ_U "u") (VHSUBQ_N_S "s") (VHSUBQ_N_U "u") (VHSUBQ_S "s") (VMAXQ_S "s") (VMAXQ_U "u") (VHSUBQ_U "u") @@ -1549,16 +1548,12 @@ (define_int_iterator VSHRQ_N [VSHRQ_N_S VSHRQ_N_U]) (define_int_iterator VCVTQ_N_FROM_F [VCVTQ_N_FROM_F_S VCVTQ_N_FROM_F_U]) (define_int_iterator VADDLVQ_P [VADDLVQ_P_S VADDLVQ_P_U]) -(define_int_iterator VCMPNEQ [VCMPNEQ_S]) (define_int_iterator VSHLQ [VSHLQ_S VSHLQ_U]) (define_int_iterator VABDQ [VABDQ_S VABDQ_U]) (define_int_iterator VADDQ_N [VADDQ_N_S VADDQ_N_U]) (define_int_iterator VADDVAQ [VADDVAQ_S VADDVAQ_U]) (define_int_iterator VADDVQ_P [VADDVQ_P_U VADDVQ_P_S]) (define_int_iterator VBRSRQ_N [VBRSRQ_N_U VBRSRQ_N_S]) -(define_int_iterator VCMPEQQ [VCMPEQQ_S]) -(define_int_iterator VCMPEQQ_N [VCMPEQQ_N_S]) -(define_int_iterator VCMPNEQ_N [VCMPNEQ_N_S]) (define_int_iterator VHADDQ [VHADDQ_S VHADDQ_U]) (define_int_iterator VHADDQ_N [VHADDQ_N_U VHADDQ_N_S]) (define_int_iterator VHSUBQ [VHSUBQ_S VHSUBQ_U]) diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index 45df211..133ebe9 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -813,7 +813,7 @@ ;; ;; [vcmpneq_, vcmpcsq_, vcmpeqq_, vcmpgeq_, vcmpgtq_, vcmphiq_, vcmpleq_, vcmpltq_]) ;; -(define_insn "mve_vcmpq_" +(define_insn "@mve_vcmpq_" [ (set (match_operand:HI 0 "vpr_register_operand" "=Up") (MVE_COMPARISONS:HI (match_operand:MVE_2 1 "s_register_operand" "w") @@ -1903,7 +1903,7 @@ ;; ;; [vcmpeqq_f, vcmpgeq_f, vcmpgtq_f, vcmpleq_f, vcmpltq_f, vcmpneq_f]) ;; -(define_insn "mve_vcmpq_f" +(define_insn "@mve_vcmpq_f" [ (set (match_operand:HI 0 "vpr_register_operand" "=Up") (MVE_FP_COMPARISONS:HI (match_operand:MVE_0 1 "s_register_operand" "w") @@ -1917,7 +1917,7 @@ ;; ;; [vcmpeqq_n_f, vcmpgeq_n_f, vcmpgtq_n_f, vcmpleq_n_f, vcmpltq_n_f, vcmpneq_n_f]) ;; -(define_insn "mve_vcmpq_n_f" +(define_insn "@mve_vcmpq_n_f" [ (set (match_operand:HI 0 "vpr_register_operand" "=Up") (MVE_FP_COMPARISONS:HI (match_operand:MVE_0 1 "s_register_operand" "w") @@ -3282,7 +3282,7 @@ ;; ;; [vpselq_u, vpselq_s]) ;; -(define_insn "mve_vpselq_" +(define_insn "@mve_vpselq_" [ (set (match_operand:MVE_1 0 "s_register_operand" "=w") (unspec:MVE_1 [(match_operand:MVE_1 1 "s_register_operand" "w") @@ -4377,7 +4377,7 @@ ;; ;; [vpselq_f]) ;; -(define_insn "mve_vpselq_f" +(define_insn "@mve_vpselq_f" [ (set (match_operand:MVE_0 0 "s_register_operand" "=w") (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w") diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 641d26f..cc82d06 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -1416,93 +1416,6 @@ [(set_attr "type" "neon_qsub")] ) -(define_expand "vec_cmp" - [(set (match_operand: 0 "s_register_operand") - (match_operator: 1 "comparison_operator" - [(match_operand:VDQW 2 "s_register_operand") - (match_operand:VDQW 3 "reg_or_zero_operand")]))] - "TARGET_NEON && (! || flag_unsafe_math_optimizations)" -{ - arm_expand_vector_compare (operands[0], GET_CODE (operands[1]), - operands[2], operands[3], false); - DONE; -}) - -(define_expand "vec_cmpu" - [(set (match_operand:VDQIW 0 "s_register_operand") - (match_operator:VDQIW 1 "comparison_operator" - [(match_operand:VDQIW 2 "s_register_operand") - (match_operand:VDQIW 3 "reg_or_zero_operand")]))] - "TARGET_NEON" -{ - arm_expand_vector_compare (operands[0], GET_CODE (operands[1]), - operands[2], operands[3], false); - DONE; -}) - -;; Conditional instructions. These are comparisons with conditional moves for -;; vectors. They perform the assignment: -;; -;; Vop0 = (Vop4 Vop5) ? Vop1 : Vop2; -;; -;; where op3 is <, <=, ==, !=, >= or >. Operations are performed -;; element-wise. - -(define_expand "vcond" - [(set (match_operand:VDQW 0 "s_register_operand") - (if_then_else:VDQW - (match_operator 3 "comparison_operator" - [(match_operand:VDQW 4 "s_register_operand") - (match_operand:VDQW 5 "reg_or_zero_operand")]) - (match_operand:VDQW 1 "s_register_operand") - (match_operand:VDQW 2 "s_register_operand")))] - "TARGET_NEON && (! || flag_unsafe_math_optimizations)" -{ - arm_expand_vcond (operands, mode); - DONE; -}) - -(define_expand "vcond" - [(set (match_operand: 0 "s_register_operand") - (if_then_else: - (match_operator 3 "comparison_operator" - [(match_operand:V32 4 "s_register_operand") - (match_operand:V32 5 "reg_or_zero_operand")]) - (match_operand: 1 "s_register_operand") - (match_operand: 2 "s_register_operand")))] - "TARGET_NEON && (! || flag_unsafe_math_optimizations)" -{ - arm_expand_vcond (operands, mode); - DONE; -}) - -(define_expand "vcondu" - [(set (match_operand:VDQW 0 "s_register_operand") - (if_then_else:VDQW - (match_operator 3 "arm_comparison_operator" - [(match_operand: 4 "s_register_operand") - (match_operand: 5 "reg_or_zero_operand")]) - (match_operand:VDQW 1 "s_register_operand") - (match_operand:VDQW 2 "s_register_operand")))] - "TARGET_NEON" -{ - arm_expand_vcond (operands, mode); - DONE; -}) - -(define_expand "vcond_mask_" - [(set (match_operand:VDQW 0 "s_register_operand") - (if_then_else:VDQW - (match_operand: 3 "s_register_operand") - (match_operand:VDQW 1 "s_register_operand") - (match_operand:VDQW 2 "s_register_operand")))] - "TARGET_NEON" -{ - emit_insn (gen_neon_vbsl (operands[0], operands[3], operands[1], - operands[2])); - DONE; -}) - ;; Patterns for builtins. ; good for plain vadd, vaddq. diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index 07ca53b..0778db1 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -596,8 +596,6 @@ VCVTQ_N_FROM_F_U VADDLVQ_P_S VADDLVQ_P_U - VCMPNEQ_U - VCMPNEQ_S VSHLQ_S VSHLQ_U VABDQ_S @@ -605,9 +603,6 @@ VADDVAQ_S VADDVQ_P_S VBRSRQ_N_S - VCMPEQQ_S - VCMPEQQ_N_S - VCMPNEQ_N_S VHADDQ_S VHADDQ_N_S VHSUBQ_S @@ -645,9 +640,6 @@ VADDVAQ_U VADDVQ_P_U VBRSRQ_N_U - VCMPEQQ_U - VCMPEQQ_N_U - VCMPNEQ_N_U VHADDQ_U VHADDQ_N_U VHSUBQ_U @@ -680,14 +672,6 @@ VSHLQ_R_U VSUBQ_U VSUBQ_N_U - VCMPGEQ_N_S - VCMPGEQ_S - VCMPGTQ_N_S - VCMPGTQ_S - VCMPLEQ_N_S - VCMPLEQ_S - VCMPLTQ_N_S - VCMPLTQ_S VHCADDQ_ROT270_S VHCADDQ_ROT90_S VMAXAQ_S @@ -702,10 +686,6 @@ VQRDMULHQ_N_S VQRDMULHQ_S VQSHLUQ_N_S - VCMPCSQ_N_U - VCMPCSQ_U - VCMPHIQ_N_U - VCMPHIQ_U VABDQ_M_S VABDQ_M_U VABDQ_F diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md index 0b2b3b1..448731f 100644 --- a/gcc/config/arm/vec-common.md +++ b/gcc/config/arm/vec-common.md @@ -362,3 +362,111 @@ DONE; } }) + +(define_expand "vec_cmp" + [(set (match_operand: 0 "s_register_operand") + (match_operator: 1 "comparison_operator" + [(match_operand:VDQW 2 "s_register_operand") + (match_operand:VDQW 3 "reg_or_zero_operand")]))] + "ARM_HAVE__ARITH + && !TARGET_REALLY_IWMMXT + && (! || flag_unsafe_math_optimizations)" +{ + arm_expand_vector_compare (operands[0], GET_CODE (operands[1]), + operands[2], operands[3], false, false); + DONE; +}) + +(define_expand "vec_cmpu" + [(set (match_operand:VDQIW 0 "s_register_operand") + (match_operator:VDQIW 1 "comparison_operator" + [(match_operand:VDQIW 2 "s_register_operand") + (match_operand:VDQIW 3 "reg_or_zero_operand")]))] + "ARM_HAVE__ARITH + && !TARGET_REALLY_IWMMXT" +{ + arm_expand_vector_compare (operands[0], GET_CODE (operands[1]), + operands[2], operands[3], false, false); + DONE; +}) + +;; Conditional instructions. These are comparisons with conditional moves for +;; vectors. They perform the assignment: +;; +;; Vop0 = (Vop4 Vop5) ? Vop1 : Vop2; +;; +;; where op3 is <, <=, ==, !=, >= or >. Operations are performed +;; element-wise. + +(define_expand "vcond" + [(set (match_operand:VDQW 0 "s_register_operand") + (if_then_else:VDQW + (match_operator 3 "comparison_operator" + [(match_operand:VDQW 4 "s_register_operand") + (match_operand:VDQW 5 "reg_or_zero_operand")]) + (match_operand:VDQW 1 "s_register_operand") + (match_operand:VDQW 2 "s_register_operand")))] + "ARM_HAVE__ARITH + && !TARGET_REALLY_IWMMXT + && (! || flag_unsafe_math_optimizations)" +{ + arm_expand_vcond (operands, mode); + DONE; +}) + +(define_expand "vcond" + [(set (match_operand: 0 "s_register_operand") + (if_then_else: + (match_operator 3 "comparison_operator" + [(match_operand:V32 4 "s_register_operand") + (match_operand:V32 5 "reg_or_zero_operand")]) + (match_operand: 1 "s_register_operand") + (match_operand: 2 "s_register_operand")))] + "ARM_HAVE__ARITH + && !TARGET_REALLY_IWMMXT + && (! || flag_unsafe_math_optimizations)" +{ + arm_expand_vcond (operands, mode); + DONE; +}) + +(define_expand "vcondu" + [(set (match_operand:VDQW 0 "s_register_operand") + (if_then_else:VDQW + (match_operator 3 "arm_comparison_operator" + [(match_operand: 4 "s_register_operand") + (match_operand: 5 "reg_or_zero_operand")]) + (match_operand:VDQW 1 "s_register_operand") + (match_operand:VDQW 2 "s_register_operand")))] + "ARM_HAVE__ARITH + && !TARGET_REALLY_IWMMXT" +{ + arm_expand_vcond (operands, mode); + DONE; +}) + +(define_expand "vcond_mask_" + [(set (match_operand:VDQW 0 "s_register_operand") + (if_then_else:VDQW + (match_operand: 3 "s_register_operand") + (match_operand:VDQW 1 "s_register_operand") + (match_operand:VDQW 2 "s_register_operand")))] + "ARM_HAVE__ARITH + && !TARGET_REALLY_IWMMXT + && (! || flag_unsafe_math_optimizations)" +{ + if (TARGET_NEON) + { + emit_insn (gen_neon_vbsl (mode, operands[0], operands[3], + operands[1], operands[2])); + } + else if (TARGET_HAVE_MVE) + { + emit_insn (gen_mve_vpselq (VPSELQ_S, mode, operands[0], + operands[1], operands[2], operands[3])); + } + else + gcc_unreachable (); + + DONE; +}) diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-compare-1.c b/gcc/testsuite/gcc.target/arm/simd/mve-compare-1.c new file mode 100644 index 0000000..029c931 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-compare-1.c @@ -0,0 +1,80 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ +/* { dg-add-options arm_v8_1m_mve } */ +/* { dg-additional-options "-O3" } */ + +/* Integer tests. */ + +#define COMPARE_REG(NAME, OP, TYPE) \ + TYPE \ + cmp_##NAME##_##TYPE##_reg (TYPE a, TYPE b) \ + { \ + return a OP b; \ + } + +#define COMPARE_REG_AND_ZERO(NAME, OP, TYPE) \ + COMPARE_REG (NAME, OP, TYPE) \ + \ + TYPE \ + cmp_##NAME##_##TYPE##_zero (TYPE a) \ + { \ + return a OP (TYPE) {}; \ + } + +#define COMPARE_TYPE(TYPE, COMPARE_ORDERED) \ + COMPARE_REG_AND_ZERO (eq, ==, TYPE) \ + COMPARE_REG_AND_ZERO (ne, !=, TYPE) \ + COMPARE_ORDERED (lt, <, TYPE) \ + COMPARE_ORDERED (le, <=, TYPE) \ + COMPARE_ORDERED (gt, >, TYPE) \ + COMPARE_ORDERED (ge, >=, TYPE) + +#define TEST_TYPE(NAME, ELEM, COMPARE_ORDERED, SIZE) \ + typedef ELEM NAME##SIZE __attribute__((vector_size(SIZE))); \ + COMPARE_TYPE (NAME##SIZE, COMPARE_ORDERED) + +/* 64-bits vectors, not vectorized. */ +TEST_TYPE (vs8, __INT8_TYPE__, COMPARE_REG_AND_ZERO, 8) +TEST_TYPE (vu8, __UINT8_TYPE__, COMPARE_REG, 8) +TEST_TYPE (vs16, __INT16_TYPE__, COMPARE_REG_AND_ZERO, 8) +TEST_TYPE (vu16, __UINT16_TYPE__, COMPARE_REG, 8) +TEST_TYPE (vs32, __INT32_TYPE__, COMPARE_REG_AND_ZERO, 8) +TEST_TYPE (vu32, __UINT32_TYPE__, COMPARE_REG, 8) + +/* 128-bits vectors. */ +TEST_TYPE (vs8, __INT8_TYPE__, COMPARE_REG_AND_ZERO, 16) +TEST_TYPE (vu8, __UINT8_TYPE__, COMPARE_REG, 16) +TEST_TYPE (vs16, __INT16_TYPE__, COMPARE_REG_AND_ZERO, 16) +TEST_TYPE (vu16, __UINT16_TYPE__, COMPARE_REG, 16) +TEST_TYPE (vs32, __INT32_TYPE__, COMPARE_REG_AND_ZERO, 16) +TEST_TYPE (vu32, __UINT32_TYPE__, COMPARE_REG, 16) + +/* { 8 bits } x { eq, ne, lt, le, gt, ge, hi, cs }. +/* { dg-final { scan-assembler-times {\tvcmp.i8 eq, q[0-9]+, q[0-9]+\n} 4 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.i8 ne, q[0-9]+, q[0-9]+\n} 4 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 lt, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 le, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 gt, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 ge, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u8 hi, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u8 cs, q[0-9]+, q[0-9]+\n} 2 } } */ + +/* { 16 bits } x { eq, ne, lt, le, gt, ge, hi, cs }. +/* { dg-final { scan-assembler-times {\tvcmp.i16 eq, q[0-9]+, q[0-9]+\n} 4 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.i16 ne, q[0-9]+, q[0-9]+\n} 4 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 lt, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 le, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 gt, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 ge, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u16 hi, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u16 cs, q[0-9]+, q[0-9]+\n} 2 } } */ + +/* { 32 bits } x { eq, ne, lt, le, gt, ge, hi, cs }. +/* { dg-final { scan-assembler-times {\tvcmp.i32 eq, q[0-9]+, q[0-9]+\n} 4 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.i32 ne, q[0-9]+, q[0-9]+\n} 4 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 lt, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 le, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 gt, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 ge, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u32 hi, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u32 cs, q[0-9]+, q[0-9]+\n} 2 } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-compare-2.c b/gcc/testsuite/gcc.target/arm/simd/mve-compare-2.c new file mode 100644 index 0000000..8515195 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-compare-2.c @@ -0,0 +1,38 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3 -funsafe-math-optimizations" } */ + +/* float 32 tests. */ + +#ifndef ELEM_TYPE +#define ELEM_TYPE float +#endif +#ifndef INT_ELEM_TYPE +#define INT_ELEM_TYPE __INT32_TYPE__ +#endif + +#define COMPARE(NAME, OP) \ + int_vec \ + cmp_##NAME##_reg (vec a, vec b) \ + { \ + return a OP b; \ + } + +typedef INT_ELEM_TYPE int_vec __attribute__((vector_size(16))); +typedef ELEM_TYPE vec __attribute__((vector_size(16))); + +COMPARE (eq, ==) +COMPARE (ne, !=) +COMPARE (lt, <) +COMPARE (le, <=) +COMPARE (gt, >) +COMPARE (ge, >=) + +/* eq, ne, lt, le, gt, ge. +/* { dg-final { scan-assembler-times {\tvcmp.f32\teq, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tne, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tlt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tle, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tgt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tge, q[0-9]+, q[0-9]+\n} 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-compare-scalar-1.c b/gcc/testsuite/gcc.target/arm/simd/mve-compare-scalar-1.c new file mode 100644 index 0000000..7774972 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-compare-scalar-1.c @@ -0,0 +1,69 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ +/* { dg-add-options arm_v8_1m_mve } */ +/* { dg-additional-options "-O3" } */ + +#define COMPARE_REG(NAME, OP, TYPE, SCALAR) \ + TYPE \ + cmp_##NAME##_##TYPE##_scalar (TYPE a, SCALAR b) \ + { \ + return a OP b; \ + } + +#define COMPARE_TYPE(SCALAR, TYPE) \ + COMPARE_REG (eq, ==, TYPE, SCALAR) \ + COMPARE_REG (ne, !=, TYPE, SCALAR) \ + COMPARE_REG (lt, <, TYPE, SCALAR) \ + COMPARE_REG (le, <=, TYPE, SCALAR) \ + COMPARE_REG (gt, >, TYPE, SCALAR) \ + COMPARE_REG (ge, >=, TYPE, SCALAR) + +#define TEST_TYPE(NAME, ELEM, SIZE) \ + typedef ELEM NAME##SIZE __attribute__((vector_size(SIZE))); \ + COMPARE_TYPE (ELEM, NAME##SIZE) + +/* 64-bits vectors, not vectorized. */ +TEST_TYPE (vs8, __INT8_TYPE__, 8) +TEST_TYPE (vu8, __UINT8_TYPE__, 8) +TEST_TYPE (vs16, __INT16_TYPE__, 8) +TEST_TYPE (vu16, __UINT16_TYPE__, 8) +TEST_TYPE (vs32, __INT32_TYPE__, 8) +TEST_TYPE (vu32, __UINT32_TYPE__, 8) + +/* 128-bits vectors. */ +TEST_TYPE (vs8, __INT8_TYPE__, 16) +TEST_TYPE (vu8, __UINT8_TYPE__, 16) +TEST_TYPE (vs16, __INT16_TYPE__, 16) +TEST_TYPE (vu16, __UINT16_TYPE__, 16) +TEST_TYPE (vs32, __INT32_TYPE__, 16) +TEST_TYPE (vu32, __UINT32_TYPE__, 16) + +/* { 8 bits } x { eq, ne, lt, le, gt, ge, hi, cs }. +/* { dg-final { scan-assembler-times {\tvcmp.i8 eq, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.i8 ne, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 lt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 le, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 gt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s8 ge, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u8 hi, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u8 cs, q[0-9]+, q[0-9]+\n} 2 } } */ + +/* { 16 bits } x { eq, ne, lt, le, gt, ge, hi, cs }. +/* { dg-final { scan-assembler-times {\tvcmp.i16 eq, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.i16 ne, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 lt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 le, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 gt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s16 ge, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u16 hi, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u16 cs, q[0-9]+, q[0-9]+\n} 2 } } */ + +/* { 32 bits } x { eq, ne, lt, le, gt, ge, hi, cs }. +/* { dg-final { scan-assembler-times {\tvcmp.i32 eq, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.i32 ne, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 lt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 le, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 gt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s32 ge, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u32 hi, q[0-9]+, q[0-9]+\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u32 cs, q[0-9]+, q[0-9]+\n} 2 } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f32.c b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f32.c new file mode 100644 index 0000000..4ed449e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f32.c @@ -0,0 +1,30 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3 -funsafe-math-optimizations" } */ + +#include + +#define NB 4 + +#define FUNC(OP, NAME) \ + void test_ ## NAME ##_f (float * __restrict__ dest, float *a, float *b) { \ + int i; \ + for (i=0; i, vcmpgt) +FUNC(>=, vcmpge) + +/* { dg-final { scan-assembler-times {\tvcmp.f32\teq, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tne, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tlt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tle, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tgt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f32\tge, q[0-9]+, q[0-9]+\n} 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c new file mode 100644 index 0000000..8da15e7 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c @@ -0,0 +1,50 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ +/* { dg-add-options arm_v8_1m_mve } */ +/* { dg-additional-options "-O3" } */ + +#include + +#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME) \ + void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \ + int i; \ + for (i=0; i, vcmpgt) +ALL_FUNCS(>=, vcmpge) + +/* MVE has only 128-bit vectors, so we can vectorize only half of the + functions above. */ +/* { dg-final { scan-assembler-times {\tvcmp.i[0-9]+ eq, q[0-9]+, q[0-9]+\n} 6 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.i[0-9]+ ne, q[0-9]+, q[0-9]+\n} 6 } } */ + +/* lt, le, gt, ge apply to signed types, cs and hi to unsigned types. */ +/* lt and le with unsigned types are replaced with the opposite condition, hence + the double number of matches for cs and hi. */ +/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+ lt, q[0-9]+, q[0-9]+\n} 3 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+ le, q[0-9]+, q[0-9]+\n} 3 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+ gt, q[0-9]+, q[0-9]+\n} 3 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+ ge, q[0-9]+, q[0-9]+\n} 3 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u[0-9]+ cs, q[0-9]+, q[0-9]+\n} 6 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.u[0-9]+ hi, q[0-9]+, q[0-9]+\n} 6 } } */ -- cgit v1.1 From 7606865198b241b4c944f66761d6506b02ead951 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 17 May 2021 12:31:58 +0000 Subject: arm: Auto-vectorization for MVE: add __fp16 support to VCMP This patch adds __fp16 support to the previous patch that added vcmp support with MVE. For this we update existing expanders to use VDQWH iterator, and add a new expander vcond. In the process we need to create suitable iterators, and update v_cmp_result as needed. 2021-05-17 Christophe Lyon gcc/ * config/arm/iterators.md (V16): New iterator. (VH_cvtto): New iterator. (v_cmp_result): Added V4HF and V8HF support. * config/arm/vec-common.md (vec_cmp): Use VDQWH. (vcond): Likewise. (vcond_mask_): Likewise. (vcond): New expander. gcc/testsuite/ * gcc.target/arm/simd/mve-compare-3.c: New test with GCC vectors. * gcc.target/arm/simd/mve-vcmp-f16.c: New test for auto-vectorization. * gcc.target/arm/armv8_2-fp16-arith-1.c: Adjust since we now vectorize float16_t vectors. --- gcc/config/arm/iterators.md | 6 ++++ gcc/config/arm/vec-common.md | 40 +++++++++++++++------- .../gcc.target/arm/armv8_2-fp16-arith-1.c | 16 +++++++-- gcc/testsuite/gcc.target/arm/simd/mve-compare-3.c | 38 ++++++++++++++++++++ gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f16.c | 30 ++++++++++++++++ 5 files changed, 116 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-compare-3.c create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f16.c (limited to 'gcc') diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index a128465..3042baf 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -231,6 +231,9 @@ ;; Vector modes for 16-bit floating-point support. (define_mode_iterator VH [V8HF V4HF]) +;; Modes with 16-bit elements only. +(define_mode_iterator V16 [V4HI V4HF V8HI V8HF]) + ;; 16-bit floating-point vector modes suitable for moving (includes BFmode). (define_mode_iterator VHFBF [V8HF V4HF V4BF V8BF]) @@ -571,6 +574,8 @@ ;; (Opposite) mode to convert to/from for vector-half mode conversions. (define_mode_attr VH_CVTTO [(V4HI "V4HF") (V4HF "V4HI") (V8HI "V8HF") (V8HF "V8HI")]) +(define_mode_attr VH_cvtto [(V4HI "v4hf") (V4HF "v4hi") + (V8HI "v8hf") (V8HF "v8hi")]) ;; Define element mode for each vector mode. (define_mode_attr V_elem [(V8QI "QI") (V16QI "QI") @@ -720,6 +725,7 @@ (define_mode_attr v_cmp_result [(V8QI "v8qi") (V16QI "v16qi") (V4HI "v4hi") (V8HI "v8hi") (V2SI "v2si") (V4SI "v4si") + (V4HF "v4hi") (V8HF "v8hi") (DI "di") (V2DI "v2di") (V2SF "v2si") (V4SF "v4si")]) diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md index 448731f..265fa40 100644 --- a/gcc/config/arm/vec-common.md +++ b/gcc/config/arm/vec-common.md @@ -366,8 +366,8 @@ (define_expand "vec_cmp" [(set (match_operand: 0 "s_register_operand") (match_operator: 1 "comparison_operator" - [(match_operand:VDQW 2 "s_register_operand") - (match_operand:VDQW 3 "reg_or_zero_operand")]))] + [(match_operand:VDQWH 2 "s_register_operand") + (match_operand:VDQWH 3 "reg_or_zero_operand")]))] "ARM_HAVE__ARITH && !TARGET_REALLY_IWMMXT && (! || flag_unsafe_math_optimizations)" @@ -399,13 +399,13 @@ ;; element-wise. (define_expand "vcond" - [(set (match_operand:VDQW 0 "s_register_operand") - (if_then_else:VDQW + [(set (match_operand:VDQWH 0 "s_register_operand") + (if_then_else:VDQWH (match_operator 3 "comparison_operator" - [(match_operand:VDQW 4 "s_register_operand") - (match_operand:VDQW 5 "reg_or_zero_operand")]) - (match_operand:VDQW 1 "s_register_operand") - (match_operand:VDQW 2 "s_register_operand")))] + [(match_operand:VDQWH 4 "s_register_operand") + (match_operand:VDQWH 5 "reg_or_zero_operand")]) + (match_operand:VDQWH 1 "s_register_operand") + (match_operand:VDQWH 2 "s_register_operand")))] "ARM_HAVE__ARITH && !TARGET_REALLY_IWMMXT && (! || flag_unsafe_math_optimizations)" @@ -430,6 +430,22 @@ DONE; }) +(define_expand "vcond" + [(set (match_operand: 0 "s_register_operand") + (if_then_else: + (match_operator 3 "comparison_operator" + [(match_operand:V16 4 "s_register_operand") + (match_operand:V16 5 "reg_or_zero_operand")]) + (match_operand: 1 "s_register_operand") + (match_operand: 2 "s_register_operand")))] + "ARM_HAVE__ARITH + && !TARGET_REALLY_IWMMXT + && (! || flag_unsafe_math_optimizations)" +{ + arm_expand_vcond (operands, mode); + DONE; +}) + (define_expand "vcondu" [(set (match_operand:VDQW 0 "s_register_operand") (if_then_else:VDQW @@ -446,11 +462,11 @@ }) (define_expand "vcond_mask_" - [(set (match_operand:VDQW 0 "s_register_operand") - (if_then_else:VDQW + [(set (match_operand:VDQWH 0 "s_register_operand") + (if_then_else:VDQWH (match_operand: 3 "s_register_operand") - (match_operand:VDQW 1 "s_register_operand") - (match_operand:VDQW 2 "s_register_operand")))] + (match_operand:VDQWH 1 "s_register_operand") + (match_operand:VDQWH 2 "s_register_operand")))] "ARM_HAVE__ARITH && !TARGET_REALLY_IWMMXT && (! || flag_unsafe_math_optimizations)" diff --git a/gcc/testsuite/gcc.target/arm/armv8_2-fp16-arith-1.c b/gcc/testsuite/gcc.target/arm/armv8_2-fp16-arith-1.c index 921d26e..52b8737 100644 --- a/gcc/testsuite/gcc.target/arm/armv8_2-fp16-arith-1.c +++ b/gcc/testsuite/gcc.target/arm/armv8_2-fp16-arith-1.c @@ -104,8 +104,20 @@ TEST_CMP (greaterthanqual, >=, int16x8_t, float16x8_t) /* { dg-final { scan-assembler-times {vmul\.f16\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } } */ /* { dg-final { scan-assembler-times {vdiv\.f16\ts[0-9]+, s[0-9]+, s[0-9]+} 13 } } */ -/* { dg-final { scan-assembler-times {vcmp\.f32\ts[0-9]+, s[0-9]+} 26 } } */ -/* { dg-final { scan-assembler-times {vcmpe\.f32\ts[0-9]+, s[0-9]+} 52 } } */ + +/* For float16_t. */ +/* { dg-final { scan-assembler-times {vcmp\.f32\ts[0-9]+, s[0-9]+} 2 } } */ +/* { dg-final { scan-assembler-times {vcmpe\.f32\ts[0-9]+, s[0-9]+} 4 } } */ + +/* For float16x4_t. */ +/* { dg-final { scan-assembler-times {vceq\.f16\td[0-9]+, d[0-9]+} 2 } } */ +/* { dg-final { scan-assembler-times {vcge\.f16\td[0-9]+, d[0-9]+} 2 } } */ +/* { dg-final { scan-assembler-times {vcgt\.f16\td[0-9]+, d[0-9]+} 2 } } */ + +/* For float16x8_t. */ +/* { dg-final { scan-assembler-times {vceq\.f16\tq[0-9]+, q[0-9]+} 2 } } */ +/* { dg-final { scan-assembler-times {vcge\.f16\tq[0-9]+, q[0-9]+} 2 } } */ +/* { dg-final { scan-assembler-times {vcgt\.f16\tq[0-9]+, q[0-9]+} 2 } } */ /* { dg-final { scan-assembler-not {vadd\.f32} } } */ /* { dg-final { scan-assembler-not {vsub\.f32} } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-compare-3.c b/gcc/testsuite/gcc.target/arm/simd/mve-compare-3.c new file mode 100644 index 0000000..76f81e8 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-compare-3.c @@ -0,0 +1,38 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3 -funsafe-math-optimizations" } */ + +/* float 16 tests. */ + +#ifndef ELEM_TYPE +#define ELEM_TYPE __fp16 +#endif +#ifndef INT_ELEM_TYPE +#define INT_ELEM_TYPE __INT16_TYPE__ +#endif + +#define COMPARE(NAME, OP) \ + int_vec \ + cmp_##NAME##_reg (vec a, vec b) \ + { \ + return a OP b; \ + } + +typedef INT_ELEM_TYPE int_vec __attribute__((vector_size(16))); +typedef ELEM_TYPE vec __attribute__((vector_size(16))); + +COMPARE (eq, ==) +COMPARE (ne, !=) +COMPARE (lt, <) +COMPARE (le, <=) +COMPARE (gt, >) +COMPARE (ge, >=) + +/* eq, ne, lt, le, gt, ge. +/* { dg-final { scan-assembler-times {\tvcmp.f16\teq, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tne, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tlt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tle, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tgt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tge, q[0-9]+, q[0-9]+\n} 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f16.c b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f16.c new file mode 100644 index 0000000..dbae2d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp-f16.c @@ -0,0 +1,30 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */ +/* { dg-add-options arm_v8_1m_mve_fp } */ +/* { dg-additional-options "-O3 -funsafe-math-optimizations" } */ + +#include + +#define NB 8 + +#define FUNC(OP, NAME) \ + void test_ ## NAME ##_f (__fp16 * __restrict__ dest, __fp16 *a, __fp16 *b) { \ + int i; \ + for (i=0; i, vcmpgt) +FUNC(>=, vcmpge) + +/* { dg-final { scan-assembler-times {\tvcmp.f16\teq, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tne, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tlt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tle, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tgt, q[0-9]+, q[0-9]+\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tvcmp.f16\tge, q[0-9]+, q[0-9]+\n} 1 } } */ -- cgit v1.1 From bdd8e3dd60c4f6080df74fe02b6579451fda6a21 Mon Sep 17 00:00:00 2001 From: Joern Rennecke Date: Mon, 17 May 2021 13:44:49 +0100 Subject: Improve message for wrong number of alternatives. gcc/ * genoutput.c (validate_insn_alternatives) Make "wrong number of alternatives" message more specific, and remove assumption on where the problem is. --- gcc/genoutput.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/genoutput.c b/gcc/genoutput.c index 8e911cc..6d4ab81 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -757,6 +757,7 @@ validate_insn_alternatives (class data *d) int which_alternative = 0; int alternative_count_unsure = 0; bool seen_write = false; + bool alt_mismatch = false; for (p = d->operand[start].constraint; (c = *p); p += len) { @@ -813,8 +814,19 @@ validate_insn_alternatives (class data *d) if (n == 0) n = d->operand[start].n_alternatives; else if (n != d->operand[start].n_alternatives) - error_at (d->loc, "wrong number of alternatives in operand %d", - start); + { + if (!alt_mismatch) + { + alt_mismatch = true; + error_at (d->loc, + "alternative number mismatch: " + "operand %d has %d, operand %d has %d", + 0, n, start, d->operand[start].n_alternatives); + } + else + error_at (d->loc, "operand %d has %d alternatives", + start, d->operand[start].n_alternatives); + } } } -- cgit v1.1 From e0a5daf81f2c79a0275eccd7c1a25349990a7a4d Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 17 May 2021 13:56:14 +0200 Subject: middle-end/100582 - fix array_at_struct_end_p for vector indexing Vector indexing leaves us with ARRAY_REFs of VIEW_CONVERT_EXPRs, sth which array_at_struct_end_p considers a array-at-struct-end even when there's an underlying decl visible. The following fixes the latter. 2021-05-17 Richard Biener PR middle-end/100582 * tree.c (array_at_struct_end_p): Get to the base of the reference before looking for the underlying decl. * gcc.target/i386/pr100582.c: New testcase. --- gcc/testsuite/gcc.target/i386/pr100582.c | 16 ++++++++++++++++ gcc/tree.c | 8 +++----- 2 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr100582.c (limited to 'gcc') diff --git a/gcc/testsuite/gcc.target/i386/pr100582.c b/gcc/testsuite/gcc.target/i386/pr100582.c new file mode 100644 index 0000000..9520fe7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100582.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mavx2" } */ + +typedef unsigned char v32qi __attribute__((vector_size(32))); + +v32qi +f2 (v32qi x, v32qi a, v32qi b) +{ + v32qi e; + for (int i = 0; i != 32; i++) + e[i] = x[i] ? a[i] : b[i]; + + return e; +} + +/* { dg-final { scan-assembler-times "pblendvb" 1 } } */ diff --git a/gcc/tree.c b/gcc/tree.c index 01eda55..8afba59 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12550,13 +12550,11 @@ array_at_struct_end_p (tree ref) || ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) return true; - if (TREE_CODE (ref) == MEM_REF - && TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR) - ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0); - /* If the reference is based on a declared entity, the size of the array is constrained by its given domain. (Do not trust commons PR/69368). */ - if (DECL_P (ref) + ref = get_base_address (ref); + if (ref + && DECL_P (ref) && !(flag_unconstrained_commons && VAR_P (ref) && DECL_COMMON (ref)) && DECL_SIZE_UNIT (ref) -- cgit v1.1