From: Richard Sandiford Date: Mon, 29 Jul 2019 08:46:46 +0000 (+0000) Subject: Add dg test for matching function bodies X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4d706ff86ea86868615558e92407674a4f4b4af9;p=gcc.git Add dg test for matching function bodies There isn't a 1:1 mapping from SVE intrinsics to SVE instructions, but the intrinsics are still close enough to the instructions for there to be a specific preferred sequence (or sometimes choice of preferred sequences) for a given combination of operands. Sometimes these sequences will be one instruction, sometimes they'll be several. I therefore wanted a convenient way of matching the exact assembly implementation of a given function. It's possible to do that using single scan-assembler lines, but: (a) they become hard to read for multiline matches (b) the PASS/FAIL lines tend to be overly long (c) it's useful to have a single place that skips over uninteresting lines, such as entry block labels and .cfi_* directives, without being overly broad This patch therefore adds a new check-function-bodies dg-final test that looks for specially-formatted comments. As a demo, the patch converts the SVE vec_init tests to use the new harness instead of scan-assembler. The regexps in parse_function_bodies are fairly general, but might still need to be extended in future for targets like Darwin or AIX. 2019-07-29 Richard Sandiford gcc/ * doc/sourcebuild.texi (check-function-bodies): Document. gcc/testsuite/ * lib/scanasm.exp (parse_function_bodies, check_function_body) (check-function-bodies): New procedures. * gcc.target/aarch64/sve/init_1.c: Use check-function-bodies instead of scan-assembler. * gcc.target/aarch64/sve/init_2.c: Likewise. * gcc.target/aarch64/sve/init_3.c: Likewise. * gcc.target/aarch64/sve/init_4.c: Likewise. * gcc.target/aarch64/sve/init_5.c: Likewise. * gcc.target/aarch64/sve/init_6.c: Likewise. * gcc.target/aarch64/sve/init_7.c: Likewise. * gcc.target/aarch64/sve/init_8.c: Likewise. * gcc.target/aarch64/sve/init_9.c: Likewise. * gcc.target/aarch64/sve/init_10.c: Likewise. * gcc.target/aarch64/sve/init_11.c: Likewise. * gcc.target/aarch64/sve/init_12.c: Likewise. From-SVN: r273869 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 706939c850d..650201a640c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2019-07-29 Richard Sandiford + + * doc/sourcebuild.texi (check-function-bodies): Document. + 2019-07-29 Richard Sandiford * simplify-rtx.c (simplify_const_unary_operation): Fold a diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 6a665154833..73186c58537 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2669,6 +2669,91 @@ assembly output. @item scan-not-hidden @var{symbol} [@{ target/xfail @var{selector} @}] Passes if @var{symbol} is not defined as a hidden symbol in the test's assembly output. + +@item check-function-bodies @var{prefix} @var{terminator} [@var{option}] +Looks through the source file for comments that give the expected assembly +output for selected functions. Each line of expected output starts with the +prefix string @var{prefix} and the expected output for a function as a whole +is followed by a line that starts with the string @var{terminator}. +Specifying an empty terminator is equivalent to specifying @samp{"*/"}. + +If @var{option} is specified, the test only applies to command lines +that contain @var{option}. This can be useful if a source file is compiled +both with and without optimization, since it is rarely useful to check the +assembly output for unoptimized code. + +The first line of the expected output for a function @var{fn} has the form: + +@smallexample +@var{prefix} @var{fn}: [@{ target/xfail @var{selector} @}] +@end smallexample + +Subsequent lines of the expected output also start with @var{prefix}. +In both cases, whitespace after @var{prefix} is not significant. + +The test discards assembly directives such as @code{.cfi_startproc} +and local label definitions such as @code{.LFB0} from the compiler's +assembly output. It then matches the result against the expected +output for a function as a single regular expression. This means that +later lines can use backslashes to refer back to @samp{(@dots{})} +captures on earlier lines. For example: + +@smallexample +/* @{ dg-final @{ check-function-bodies "**" "" "-DCHECK_ASM" @} @} */ +@dots{} +/* +** add_w0_s8_m: +** mov (z[0-9]+\.b), w0 +** add z0\.b, p0/m, z0\.b, \1 +** ret +*/ +svint8_t add_w0_s8_m (@dots{}) @{ @dots{} @} +@dots{} +/* +** add_b0_s8_m: +** mov (z[0-9]+\.b), b0 +** add z1\.b, p0/m, z1\.b, \1 +** ret +*/ +svint8_t add_b0_s8_m (@dots{}) @{ @dots{} @} +@end smallexample + +checks whether the implementations of @code{add_w0_s8_m} and +@code{add_b0_s8_m} match the regular expressions given. The test only +runs when @samp{-DCHECK_ASM} is passed on the command line. + +It is possible to create non-capturing multi-line regular expression +groups of the form @samp{(@var{a}|@var{b}|@dots{})} by putting the +@samp{(}, @samp{|} and @samp{)} on separate lines (each still using +@var{prefix}). For example: + +@smallexample +/* +** cmple_f16_tied: +** ( +** fcmge p0\.h, p0/z, z1\.h, z0\.h +** | +** fcmle p0\.h, p0/z, z0\.h, z1\.h +** ) +** ret +*/ +svbool_t cmple_f16_tied (@dots{}) @{ @dots{} @} +@end smallexample + +checks whether @code{cmple_f16_tied} is implemented by the +@code{fcmge} instruction followed by @code{ret} or by the +@code{fcmle} instruction followed by @code{ret}. The test is +still a single regular rexpression. + +A line containing just: + +@smallexample +@var{prefix} ... +@end smallexample + +stands for zero or more unmatched lines; the whitespace after +@var{prefix} is again not significant. + @end table @subsubsection Scan optimization dump files diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4230691c11a..f896434fc0b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,21 @@ +2019-07-29 Richard Sandiford + + * lib/scanasm.exp (parse_function_bodies, check_function_body) + (check-function-bodies): New procedures. + * gcc.target/aarch64/sve/init_1.c: Use check-function-bodies + instead of scan-assembler. + * gcc.target/aarch64/sve/init_2.c: Likewise. + * gcc.target/aarch64/sve/init_3.c: Likewise. + * gcc.target/aarch64/sve/init_4.c: Likewise. + * gcc.target/aarch64/sve/init_5.c: Likewise. + * gcc.target/aarch64/sve/init_6.c: Likewise. + * gcc.target/aarch64/sve/init_7.c: Likewise. + * gcc.target/aarch64/sve/init_8.c: Likewise. + * gcc.target/aarch64/sve/init_9.c: Likewise. + * gcc.target/aarch64/sve/init_10.c: Likewise. + * gcc.target/aarch64/sve/init_11.c: Likewise. + * gcc.target/aarch64/sve/init_12.c: Likewise. + 2019-07-28 Rainer Orth * g++.dg/lto/pr89330_0.C (dg-lto-options): Add -fPIC. diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_1.c b/gcc/testsuite/gcc.target/aarch64/sve/init_1.c index 14abc22e2cb..8e6004337b3 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_1.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 1.1: Trailing constants with stepped sequence. */ @@ -7,20 +8,15 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** index (z[0-9]+\.s), #1, #1 +** insr \1, w1 +** insr \1, w0 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b) { return (vnx4si) { a, b, 1, 2, 3, 4, 5, 6 }; } - -/* -foo: -.LFB0: - .cfi_startproc - index z0.s, #1, #1 - insr z0.s, w1 - insr z0.s, w0 - ret -*/ - -/* { dg-final { scan-assembler {\tindex\t(z[0-9]+\.s), #1, #1\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_10.c b/gcc/testsuite/gcc.target/aarch64/sve/init_10.c index c83debe4dac..bee039415d0 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_10.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_10.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 5.4: Interleaved repeating elements and non-repeating elements. */ @@ -7,22 +8,17 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** mov (z[0-9]+\.s), w3 +** mov (z[0-9]+\.s), w2 +** insr \2, w1 +** insr \2, w0 +** zip1 \2, \2, \1 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b, int c, int f) { return (vnx4si) { a, f, b, f, c, f, c, f }; } - -/* -foo: -.LFB0: - .cfi_startproc - mov z1.s, w3 - mov z0.s, w2 - insr z0.s, w1 - insr z0.s, w0 - zip1 z0.s, z0.s, z1.s - ret -*/ - -/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w3\n\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\2, w1\n\tinsr\t\2, w0\n\tzip1\t\2, \2, \1} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_11.c b/gcc/testsuite/gcc.target/aarch64/sve/init_11.c index 90627b44efc..8a9496f34e4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_11.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_11.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 5.5: Interleaved repeating elements and trailing same elements. */ @@ -7,21 +8,16 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** mov (z[0-9]+\.s), w1 +** insr \1, w0 +** mov (z[0-9]+\.s), w2 +** zip1 \1, \1, \2 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b, int f) { return (vnx4si) { a, f, b, f, b, f, b, f }; } - -/* -foo: -.LFB0: - .cfi_startproc - mov z0.s, w1 - insr z0.s, w0 - mov z1.s, w2 - zip1 z0.s, z0.s, z1.s - ret -*/ - -/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w1\n\tinsr\t\1, w0\n\tmov\t(z[0-9]+\.s), w2\n\tzip1\t\1, \1, \2} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_12.c b/gcc/testsuite/gcc.target/aarch64/sve/init_12.c index dc20e86c02c..cbf418e4e63 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_12.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_12.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 5.5: Interleaved repeating elements and trailing same elements. */ @@ -7,23 +8,18 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** mov (z[0-9]+\.s), w2 +** mov (z[0-9]+\.s), w0 +** insr \2, w1 +** insr \2, w1 +** insr \2, w1 +** zip1 \2, \2, \1 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b, int f) { return (vnx4si) { b, f, b, f, b, f, a, f }; } - -/* -foo: -.LFB0: - .cfi_startproc - mov z1.s, w2 - mov z0.s, w0 - insr z0.s, w1 - insr z0.s, w1 - insr z0.s, w1 - zip1 z0.s, z0.s, z1.s - ret -*/ - -/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tmov\t(z[0-9]+\.s), w0\n\tinsr\t\2, w1\n\tinsr\t\2, w1\n\tinsr\t\2, w1\n\tzip1\t\2, \2, \1} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_2.c b/gcc/testsuite/gcc.target/aarch64/sve/init_2.c index 5b4ba105af2..83bd999d21e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_2.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 1.2: Trailing constants with repeating sequence. */ @@ -7,23 +8,16 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** ... +** ld1w (z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\] +** insr \1, w1 +** insr \1, w0 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b) { return (vnx4si) { a, b, 2, 3, 2, 3, 2, 3 }; } - -/* -foo: -.LFB0: - .cfi_startproc - ptrue p0.s, vl8 - adrp x2, .LANCHOR0 - add x2, x2, :lo12:.LANCHOR0 - ld1w z0.s, p0/z, [x2] - insr z0.s, w1 - insr z0.s, w0 - ret -*/ - -/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_3.c b/gcc/testsuite/gcc.target/aarch64/sve/init_3.c index 28d218cd768..4a418b633f5 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_3.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_3.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 2.1: Leading constants with stepped sequence. */ @@ -7,21 +8,17 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** index (z[0-9]+\.s), #6, #-1 +** insr \1, w0 +** insr \1, w1 +** rev \1, \1 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b) { return (vnx4si) { 1, 2, 3, 4, 5, 6, a, b }; } -/* -foo: -.LFB0: - .cfi_startproc - index z0.s, #6, #-1 - insr z0.s, w0 - insr z0.s, w1 - rev z0.s, z0.s - ret -*/ - -/* { dg-final { scan-assembler {\tindex\t(z[0-9]+\.s), #6, #-1\n\tinsr\t\1, w0\n\tinsr\t\1, w1\n\trev\t\1, \1} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_4.c b/gcc/testsuite/gcc.target/aarch64/sve/init_4.c index 94484b1a4e6..fa914488adc 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_4.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_4.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 2.2: Leading constants with stepped sequence. */ @@ -7,24 +8,17 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** ... +** ld1w (z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\] +** insr \1, w1 +** insr \1, w0 +** rev \1, \1 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b) { return (vnx4si) { 3, 2, 3, 2, 3, 2, b, a }; } - -/* -foo: -.LFB0: - .cfi_startproc - ptrue p0.s, vl8 - adrp x2, .LANCHOR0 - add x2, x2, :lo12:.LANCHOR0 - ld1w z0.s, p0/z, [x2] - insr z0.s, w1 - insr z0.s, w0 - rev z0.s, z0.s - ret -*/ - -/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tinsr\t\1, w1\n\tinsr\t\1, w0\n\trev\t\1, \1} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_5.c b/gcc/testsuite/gcc.target/aarch64/sve/init_5.c index a43dd7a4ac7..794e265c3b8 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_5.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_5.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 3: Trailing same element. */ @@ -7,20 +8,15 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** mov (z[0-9]+\.s), w2 +** insr \1, w1 +** insr \1, w0 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b, int c) { return (vnx4si) { a, b, c, c, c, c, c, c }; } - -/* -foo: -.LFB0: - .cfi_startproc - mov z0.s, w2 - insr z0.s, w1 - insr z0.s, w0 - ret -*/ - -/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_6.c b/gcc/testsuite/gcc.target/aarch64/sve/init_6.c index b8e30fb72eb..8443fc0000e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_6.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_6.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 3: Trailing same element. */ @@ -7,21 +8,16 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** mov (z[0-9]+\.s), w2 +** insr \1, w1 +** insr \1, w0 +** rev \1, \1 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b, int c) { return (vnx4si) { c, c, c, c, c, c, b, a }; } - -/* -foo: -.LFB0: - .cfi_startproc - mov z0.s, w2 - insr z0.s, w1 - insr z0.s, w0 - rev z0.s, z0.s - ret -*/ - -/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0\n\trev\t\1, \1} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_7.c b/gcc/testsuite/gcc.target/aarch64/sve/init_7.c index dd27978faf7..63dbbbe61f6 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_7.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_7.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 5.1: All elements. */ @@ -7,25 +8,20 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** mov (z[0-9]+\.s), w7 +** insr \1, w6 +** insr \1, w5 +** insr \1, w4 +** insr \1, w3 +** insr \1, w2 +** insr \1, w1 +** insr \1, w0 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b, int c, int d, int e, int f, int g, int h) { return (vnx4si) { a, b, c, d, e, f, g, h }; } - -/* -foo: -.LFB0: - .cfi_startproc - mov z0.s, w7 - insr z0.s, w6 - insr z0.s, w5 - insr z0.s, w4 - insr z0.s, w3 - insr z0.s, w2 - insr z0.s, w1 - insr z0.s, w0 - ret -*/ - -/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w7\n\tinsr\t\1, w6\n\tinsr\t\1, w5\n\tinsr\t\1, w4\n\tinsr\t\1, w3\n\tinsr\t\1, w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_8.c b/gcc/testsuite/gcc.target/aarch64/sve/init_8.c index 73f7aba3df3..9c2456785d5 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_8.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_8.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 5.2: Interleaved elements and constants. */ @@ -7,26 +8,19 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** ... +** ld1w (z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\] +** mov (z[0-9]+\.s), w3 +** insr \2, w2 +** insr \2, w1 +** insr \2, w0 +** zip1 \2, \2, \1 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b, int c, int d) { return (vnx4si) { a, 1, b, 2, c, 3, d, 4 }; } - -/* -foo: -.LFB0: - .cfi_startproc - ptrue p0.s, vl8 - adrp x4, .LANCHOR0 - add x4, x4, :lo12:.LANCHOR0 - ld1w z1.s, p0/z, [x4] - mov z0.s, w3 - insr z0.s, w2 - insr z0.s, w1 - insr z0.s, w0 - zip1 z0.s, z0.s, z1.s - ret -*/ - -/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tmov\t(z[0-9]+\.s), w3\n\tinsr\t\2, w2\n\tinsr\t\2, w1\n\tinsr\t\2, w0\n\tzip1\t\2, \2, \1} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_9.c b/gcc/testsuite/gcc.target/aarch64/sve/init_9.c index 2cc564a5a83..d22ab71e696 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/init_9.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/init_9.c @@ -1,5 +1,6 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" } } */ /* Case 5.3: Repeated elements. */ @@ -7,20 +8,15 @@ typedef int32_t vnx4si __attribute__((vector_size (32))); +/* +** foo: +** mov (z[0-9]+\.s), w0 +** mov (z[0-9]+\.s), w1 +** zip1 \1, \1, \2 +** ... +*/ __attribute__((noipa)) vnx4si foo(int a, int b) { return (vnx4si) { a, b, a, b, a, b, a, b }; } - -/* -foo: -.LFB0: - .cfi_startproc - mov z0.s, w0 - mov z1.s, w1 - zip1 z0.s, z0.s, z1.s - ret -*/ - -/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w0\n\tmov\t(z[0-9]+\.s), w1\n\tzip1\t\1, \1, \2} } } */ diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index 231a4d66bad..0f1b246b8dc 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -554,3 +554,169 @@ proc scan-lto-assembler { args } { verbose "output_file: $output_file" dg-scan "scan-lto-assembler" 1 $testcase $output_file $args } + +# Read assembly file FILENAME and store a mapping from function names +# to function bodies in array RESULT. FILENAME has already been uploaded +# locally where necessary and is known to exist. + +proc parse_function_bodies { filename result } { + upvar $result up_result + + # Regexp for the start of a function definition (name in \1). + set label {^([a-zA-Z_]\S+):$} + + # Regexp for the end of a function definition. + set terminator {^\s*\.size} + + # Regexp for lines that aren't interesting. + set fluff {^\s*(?:\.|//)} + + set fd [open $filename r] + set in_function 0 + while { [gets $fd line] >= 0 } { + if { [regexp $label $line dummy function_name] } { + set in_function 1 + set function_body "" + } elseif { $in_function } { + if { [regexp $terminator $line] } { + set up_result($function_name) $function_body + set in_function 0 + } elseif { ![regexp $fluff $line] } { + append function_body $line "\n" + } + } + } + close $fd +} + +# FUNCTIONS is an array that maps function names to function bodies. +# Return true if it contains a definition of function NAME and if +# that definition matches BODY_REGEXP. + +proc check_function_body { functions name body_regexp } { + upvar $functions up_functions + + if { ![info exists up_functions($name)] } { + return 0 + } + return [regexp "^$body_regexp\$" $up_functions($name)] +} + +# Check the implementations of functions against expected output. Used as: +# +# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION] } } +# +# See sourcebuild.texi for details. + +proc check-function-bodies { args } { + if { [llength $args] < 2 } { + error "too few arguments to check-function-bodies" + } + if { [llength $args] > 3 } { + error "too many arguments to check-function-bodies" + } + + if { [llength $args] == 3 } { + set required_flag [lindex $args 2] + + upvar 2 dg-extra-tool-flags extra_tool_flags + set flags $extra_tool_flags + + global torture_current_flags + if { [info exists torture_current_flags] } { + append flags " " $torture_current_flags + } + if { ![regexp " $required_flag " $flags] } { + return + } + } + + set testcase [testname-for-summary] + # The name might include a list of options; extract the file name. + set filename [lindex $testcase 0] + + global srcdir + set input_filename "$srcdir/$filename" + set output_filename "[file rootname [file tail $filename]].s" + + set prefix [lindex $args 0] + set prefix_len [string length $prefix] + set terminator [lindex $args 1] + if { [string equal $terminator ""] } { + set terminator "*/" + } + set terminator_len [string length $terminator] + + set have_bodies 0 + if { [is_remote host] } { + remote_upload host "$filename" + } + if { [file exists $output_filename] } { + parse_function_bodies $output_filename functions + set have_bodies 1 + } else { + verbose -log "$testcase: output file does not exist" + } + + set count 0 + set function_regexp "" + set label {^(\S+):$} + + set lineno 1 + set fd [open $input_filename r] + set in_function 0 + while { [gets $fd line] >= 0 } { + if { [string equal -length $prefix_len $line $prefix] } { + set line [string trim [string range $line $prefix_len end]] + if { !$in_function } { + if { [regexp "^(.*\\S)\\s+{(.*)}\$" $line dummy \ + line selector] } { + set selector [dg-process-target $selector] + } else { + set selector "P" + } + if { ![regexp $label $line dummy function_name] } { + close $fd + error "check-function-bodies: line $lineno does not have a function label" + } + set in_function 1 + set function_regexp "" + } elseif { [string equal $line "("] } { + append function_regexp "(?:" + } elseif { [string equal $line "|"] } { + append function_regexp "|" + } elseif { [string equal $line ")"] } { + append function_regexp ")" + } elseif { [string equal $line "..."] } { + append function_regexp ".*" + } else { + append function_regexp "\t" $line "\n" + } + } elseif { [string equal -length $terminator_len $line $terminator] } { + if { ![string equal $selector "N"] } { + if { [string equal $selector "F"] } { + setup_xfail "*-*-*" + } + set testname "$testcase check-function-bodies $function_name" + if { !$have_bodies } { + unresolved $testname + } elseif { [check_function_body functions $function_name \ + $function_regexp] } { + pass $testname + } else { + fail $testname + } + } + set in_function 0 + incr count + } + incr lineno + } + close $fd + if { $in_function } { + error "check-function-bodies: missing \"$terminator\"" + } + if { $count == 0 } { + error "check-function-bodies: no matches found" + } +}