[llvm] ecd46ed - [UpdateTestChecks] Re-add --filter and --filter-out options

David Greene via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 31 13:12:02 PST 2022


Author: David Greene
Date: 2022-01-31T13:11:40-08:00
New Revision: ecd46edd613433154b3d0eeb25af27234f6f98eb

URL: https://github.com/llvm/llvm-project/commit/ecd46edd613433154b3d0eeb25af27234f6f98eb
DIFF: https://github.com/llvm/llvm-project/commit/ecd46edd613433154b3d0eeb25af27234f6f98eb.diff

LOG: [UpdateTestChecks] Re-add --filter and --filter-out options

Re-add filtering options with fixes for failed tests.  We were not passing the
is_filtered argument in all check generator calls in update_cc_test_checks.py

Enhance the various update_*_test_checks.py tools to allow filtering the tool
output with regular expressions.  The --filter option will emit only tool output
lines matching the given regular expression while the --filter-out option will
emit only tools output lines not matching the given regular expression.  Filters
are applied in order of appearance on the command line (or in UTC_ARGS) and the
first matching filter terminates the search.

This allows test authors to create more focused tests by removing irrelevant
tool output and checking only the pieces of output necessary to test the desired
functionality.

Differential Revision: https://reviews.llvm.org/D117694

Added: 
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter-out.expected
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter.expected
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.multifilter.expected
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.nofilter.expected
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-filter.test

Modified: 
    llvm/utils/UpdateTestChecks/asm.py
    llvm/utils/UpdateTestChecks/common.py
    llvm/utils/update_cc_test_checks.py
    llvm/utils/update_llc_test_checks.py
    llvm/utils/update_test_checks.py

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll
new file mode 100644
index 0000000000000..37a7f22587e5c
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll
@@ -0,0 +1,38 @@
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 | FileCheck %s
+
+define i32 @f(<8 x float> %A, i8* %B, <4 x double> %C, <4 x i64> %E, <8 x i32> %F, <16 x i16> %G, <32 x i8> %H, i32* %loadptr) nounwind {
+  %v0 = load i32, i32* %loadptr, align 1
+  %cast = bitcast i8* %B to <8 x float>*
+  %A2 = fadd <8 x float> %A, <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0>
+  store <8 x float> %A2, <8 x float>* %cast, align 32, !nontemporal !0
+  %v1 = load i32, i32* %loadptr, align 1
+  %cast1 = bitcast i8* %B to <4 x i64>*
+  %E2 = add <4 x i64> %E, <i64 1, i64 2, i64 3, i64 4>
+  store <4 x i64> %E2, <4 x i64>* %cast1, align 32, !nontemporal !0
+  %v2 = load i32, i32* %loadptr, align 1
+  %cast2 = bitcast i8* %B to <4 x double>*
+  %C2 = fadd <4 x double> %C, <double 1.0, double 2.0, double 3.0, double 4.0>
+  store <4 x double> %C2, <4 x double>* %cast2, align 32, !nontemporal !0
+  %v3 = load i32, i32* %loadptr, align 1
+  %cast3 = bitcast i8* %B to <8 x i32>*
+  %F2 = add <8 x i32> %F, <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
+  store <8 x i32> %F2, <8 x i32>* %cast3, align 32, !nontemporal !0
+  %v4 = load i32, i32* %loadptr, align 1
+  %cast4 = bitcast i8* %B to <16 x i16>*
+  %G2 = add <16 x i16> %G, <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
+  store <16 x i16> %G2, <16 x i16>* %cast4, align 32, !nontemporal !0
+  %v5 = load i32, i32* %loadptr, align 1
+  %cast5 = bitcast i8* %B to <32 x i8>*
+  %H2 = add <32 x i8> %H, <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8>
+  store <32 x i8> %H2, <32 x i8>* %cast5, align 32, !nontemporal !0
+  %v6 = load i32, i32* %loadptr, align 1
+  %sum1 = add i32 %v0, %v1
+  %sum2 = add i32 %sum1, %v2
+  %sum3 = add i32 %sum2, %v3
+  %sum4 = add i32 %sum3, %v4
+  %sum5 = add i32 %sum4, %v5
+  %sum6 = add i32 %sum5, %v6
+  ret i32 %sum5
+}
+
+!0 = !{i32 1}

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter-out.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter-out.expected
new file mode 100644
index 0000000000000..49577b7ba8bea
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter-out.expected
@@ -0,0 +1,54 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --filter-out "movnt"
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 | FileCheck %s
+
+define i32 @f(<8 x float> %A, i8* %B, <4 x double> %C, <4 x i64> %E, <8 x i32> %F, <16 x i16> %G, <32 x i8> %H, i32* %loadptr) nounwind {
+; CHECK-LABEL: f:
+; CHECK:    movl (%rsi), %eax
+; CHECK:    vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
+; CHECK:    vpaddq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vaddpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm3, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vpaddw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vpaddb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vzeroupper
+; CHECK:    retq
+  %v0 = load i32, i32* %loadptr, align 1
+  %cast = bitcast i8* %B to <8 x float>*
+  %A2 = fadd <8 x float> %A, <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0>
+  store <8 x float> %A2, <8 x float>* %cast, align 32, !nontemporal !0
+  %v1 = load i32, i32* %loadptr, align 1
+  %cast1 = bitcast i8* %B to <4 x i64>*
+  %E2 = add <4 x i64> %E, <i64 1, i64 2, i64 3, i64 4>
+  store <4 x i64> %E2, <4 x i64>* %cast1, align 32, !nontemporal !0
+  %v2 = load i32, i32* %loadptr, align 1
+  %cast2 = bitcast i8* %B to <4 x double>*
+  %C2 = fadd <4 x double> %C, <double 1.0, double 2.0, double 3.0, double 4.0>
+  store <4 x double> %C2, <4 x double>* %cast2, align 32, !nontemporal !0
+  %v3 = load i32, i32* %loadptr, align 1
+  %cast3 = bitcast i8* %B to <8 x i32>*
+  %F2 = add <8 x i32> %F, <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
+  store <8 x i32> %F2, <8 x i32>* %cast3, align 32, !nontemporal !0
+  %v4 = load i32, i32* %loadptr, align 1
+  %cast4 = bitcast i8* %B to <16 x i16>*
+  %G2 = add <16 x i16> %G, <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
+  store <16 x i16> %G2, <16 x i16>* %cast4, align 32, !nontemporal !0
+  %v5 = load i32, i32* %loadptr, align 1
+  %cast5 = bitcast i8* %B to <32 x i8>*
+  %H2 = add <32 x i8> %H, <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8>
+  store <32 x i8> %H2, <32 x i8>* %cast5, align 32, !nontemporal !0
+  %v6 = load i32, i32* %loadptr, align 1
+  %sum1 = add i32 %v0, %v1
+  %sum2 = add i32 %sum1, %v2
+  %sum3 = add i32 %sum2, %v3
+  %sum4 = add i32 %sum3, %v4
+  %sum5 = add i32 %sum4, %v5
+  %sum6 = add i32 %sum5, %v6
+  ret i32 %sum5
+}
+
+!0 = !{i32 1}

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter.expected
new file mode 100644
index 0000000000000..3ab1ea0231b00
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.filter.expected
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --filter "movnt"
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 | FileCheck %s
+
+define i32 @f(<8 x float> %A, i8* %B, <4 x double> %C, <4 x i64> %E, <8 x i32> %F, <16 x i16> %G, <32 x i8> %H, i32* %loadptr) nounwind {
+; CHECK-LABEL: f:
+; CHECK:    vmovntdq %ymm0, (%rdi)
+; CHECK:    vmovntpd %ymm0, (%rdi)
+; CHECK:    vmovntdq %ymm0, (%rdi)
+; CHECK:    vmovntdq %ymm0, (%rdi)
+; CHECK:    vmovntdq %ymm0, (%rdi)
+  %v0 = load i32, i32* %loadptr, align 1
+  %cast = bitcast i8* %B to <8 x float>*
+  %A2 = fadd <8 x float> %A, <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0>
+  store <8 x float> %A2, <8 x float>* %cast, align 32, !nontemporal !0
+  %v1 = load i32, i32* %loadptr, align 1
+  %cast1 = bitcast i8* %B to <4 x i64>*
+  %E2 = add <4 x i64> %E, <i64 1, i64 2, i64 3, i64 4>
+  store <4 x i64> %E2, <4 x i64>* %cast1, align 32, !nontemporal !0
+  %v2 = load i32, i32* %loadptr, align 1
+  %cast2 = bitcast i8* %B to <4 x double>*
+  %C2 = fadd <4 x double> %C, <double 1.0, double 2.0, double 3.0, double 4.0>
+  store <4 x double> %C2, <4 x double>* %cast2, align 32, !nontemporal !0
+  %v3 = load i32, i32* %loadptr, align 1
+  %cast3 = bitcast i8* %B to <8 x i32>*
+  %F2 = add <8 x i32> %F, <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
+  store <8 x i32> %F2, <8 x i32>* %cast3, align 32, !nontemporal !0
+  %v4 = load i32, i32* %loadptr, align 1
+  %cast4 = bitcast i8* %B to <16 x i16>*
+  %G2 = add <16 x i16> %G, <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
+  store <16 x i16> %G2, <16 x i16>* %cast4, align 32, !nontemporal !0
+  %v5 = load i32, i32* %loadptr, align 1
+  %cast5 = bitcast i8* %B to <32 x i8>*
+  %H2 = add <32 x i8> %H, <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8>
+  store <32 x i8> %H2, <32 x i8>* %cast5, align 32, !nontemporal !0
+  %v6 = load i32, i32* %loadptr, align 1
+  %sum1 = add i32 %v0, %v1
+  %sum2 = add i32 %sum1, %v2
+  %sum3 = add i32 %sum2, %v3
+  %sum4 = add i32 %sum3, %v4
+  %sum5 = add i32 %sum4, %v5
+  %sum6 = add i32 %sum5, %v6
+  ret i32 %sum5
+}
+
+!0 = !{i32 1}

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.multifilter.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.multifilter.expected
new file mode 100644
index 0000000000000..46a9b5459321b
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.multifilter.expected
@@ -0,0 +1,57 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --filter "LCPI[0-9]+_[0-9]+" --filter "movnt" --filter "(%esp|%rsi)"
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 | FileCheck %s
+
+define i32 @f(<8 x float> %A, i8* %B, <4 x double> %C, <4 x i64> %E, <8 x i32> %F, <16 x i16> %G, <32 x i8> %H, i32* %loadptr) nounwind {
+; CHECK-LABEL: f:
+; CHECK:    vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
+; CHECK:    vmovntps %ymm0, (%rdi)
+; CHECK:    vpaddq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vmovntdq %ymm0, (%rdi)
+; CHECK:    vaddpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vmovntpd %ymm0, (%rdi)
+; CHECK:    vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm3, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vmovntdq %ymm0, (%rdi)
+; CHECK:    vpaddw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vmovntdq %ymm0, (%rdi)
+; CHECK:    vpaddb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm0
+; CHECK:    addl (%rsi), %eax
+; CHECK:    vmovntdq %ymm0, (%rdi)
+  %v0 = load i32, i32* %loadptr, align 1
+  %cast = bitcast i8* %B to <8 x float>*
+  %A2 = fadd <8 x float> %A, <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0>
+  store <8 x float> %A2, <8 x float>* %cast, align 32, !nontemporal !0
+  %v1 = load i32, i32* %loadptr, align 1
+  %cast1 = bitcast i8* %B to <4 x i64>*
+  %E2 = add <4 x i64> %E, <i64 1, i64 2, i64 3, i64 4>
+  store <4 x i64> %E2, <4 x i64>* %cast1, align 32, !nontemporal !0
+  %v2 = load i32, i32* %loadptr, align 1
+  %cast2 = bitcast i8* %B to <4 x double>*
+  %C2 = fadd <4 x double> %C, <double 1.0, double 2.0, double 3.0, double 4.0>
+  store <4 x double> %C2, <4 x double>* %cast2, align 32, !nontemporal !0
+  %v3 = load i32, i32* %loadptr, align 1
+  %cast3 = bitcast i8* %B to <8 x i32>*
+  %F2 = add <8 x i32> %F, <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
+  store <8 x i32> %F2, <8 x i32>* %cast3, align 32, !nontemporal !0
+  %v4 = load i32, i32* %loadptr, align 1
+  %cast4 = bitcast i8* %B to <16 x i16>*
+  %G2 = add <16 x i16> %G, <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
+  store <16 x i16> %G2, <16 x i16>* %cast4, align 32, !nontemporal !0
+  %v5 = load i32, i32* %loadptr, align 1
+  %cast5 = bitcast i8* %B to <32 x i8>*
+  %H2 = add <32 x i8> %H, <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8>
+  store <32 x i8> %H2, <32 x i8>* %cast5, align 32, !nontemporal !0
+  %v6 = load i32, i32* %loadptr, align 1
+  %sum1 = add i32 %v0, %v1
+  %sum2 = add i32 %sum1, %v2
+  %sum3 = add i32 %sum2, %v3
+  %sum4 = add i32 %sum3, %v4
+  %sum5 = add i32 %sum4, %v5
+  %sum6 = add i32 %sum5, %v6
+  ret i32 %sum5
+}
+
+!0 = !{i32 1}

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.nofilter.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.nofilter.expected
new file mode 100644
index 0000000000000..26f6b1b945b51
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-non-temporal.ll.nofilter.expected
@@ -0,0 +1,61 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 | FileCheck %s
+
+define i32 @f(<8 x float> %A, i8* %B, <4 x double> %C, <4 x i64> %E, <8 x i32> %F, <16 x i16> %G, <32 x i8> %H, i32* %loadptr) nounwind {
+; CHECK-LABEL: f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl (%rsi), %eax
+; CHECK-NEXT:    vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
+; CHECK-NEXT:    vmovntps %ymm0, (%rdi)
+; CHECK-NEXT:    vpaddq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm0
+; CHECK-NEXT:    addl (%rsi), %eax
+; CHECK-NEXT:    vmovntdq %ymm0, (%rdi)
+; CHECK-NEXT:    vaddpd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0
+; CHECK-NEXT:    addl (%rsi), %eax
+; CHECK-NEXT:    vmovntpd %ymm0, (%rdi)
+; CHECK-NEXT:    vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm3, %ymm0
+; CHECK-NEXT:    addl (%rsi), %eax
+; CHECK-NEXT:    vmovntdq %ymm0, (%rdi)
+; CHECK-NEXT:    vpaddw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm0
+; CHECK-NEXT:    addl (%rsi), %eax
+; CHECK-NEXT:    vmovntdq %ymm0, (%rdi)
+; CHECK-NEXT:    vpaddb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm0
+; CHECK-NEXT:    addl (%rsi), %eax
+; CHECK-NEXT:    vmovntdq %ymm0, (%rdi)
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
+  %v0 = load i32, i32* %loadptr, align 1
+  %cast = bitcast i8* %B to <8 x float>*
+  %A2 = fadd <8 x float> %A, <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0>
+  store <8 x float> %A2, <8 x float>* %cast, align 32, !nontemporal !0
+  %v1 = load i32, i32* %loadptr, align 1
+  %cast1 = bitcast i8* %B to <4 x i64>*
+  %E2 = add <4 x i64> %E, <i64 1, i64 2, i64 3, i64 4>
+  store <4 x i64> %E2, <4 x i64>* %cast1, align 32, !nontemporal !0
+  %v2 = load i32, i32* %loadptr, align 1
+  %cast2 = bitcast i8* %B to <4 x double>*
+  %C2 = fadd <4 x double> %C, <double 1.0, double 2.0, double 3.0, double 4.0>
+  store <4 x double> %C2, <4 x double>* %cast2, align 32, !nontemporal !0
+  %v3 = load i32, i32* %loadptr, align 1
+  %cast3 = bitcast i8* %B to <8 x i32>*
+  %F2 = add <8 x i32> %F, <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
+  store <8 x i32> %F2, <8 x i32>* %cast3, align 32, !nontemporal !0
+  %v4 = load i32, i32* %loadptr, align 1
+  %cast4 = bitcast i8* %B to <16 x i16>*
+  %G2 = add <16 x i16> %G, <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
+  store <16 x i16> %G2, <16 x i16>* %cast4, align 32, !nontemporal !0
+  %v5 = load i32, i32* %loadptr, align 1
+  %cast5 = bitcast i8* %B to <32 x i8>*
+  %H2 = add <32 x i8> %H, <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8>
+  store <32 x i8> %H2, <32 x i8>* %cast5, align 32, !nontemporal !0
+  %v6 = load i32, i32* %loadptr, align 1
+  %sum1 = add i32 %v0, %v1
+  %sum2 = add i32 %sum1, %v2
+  %sum3 = add i32 %sum2, %v3
+  %sum4 = add i32 %sum3, %v4
+  %sum5 = add i32 %sum4, %v5
+  %sum6 = add i32 %sum5, %v6
+  ret i32 %sum5
+}
+
+!0 = !{i32 1}

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-filter.test b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-filter.test
new file mode 100644
index 0000000000000..dd7e353a2dfb2
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-filter.test
@@ -0,0 +1,33 @@
+# REQUIRES: x86-registered-target
+
+## Check that --filter works properly.
+# RUN: cp -f %S/Inputs/x86-non-temporal.ll %t.ll && %update_llc_test_checks --filter="movnt" %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.filter.expected
+
+## Check that running the script again does not change the result:
+# RUN: %update_llc_test_checks --filter="movnt" %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.filter.expected
+
+## Check that --filter-out works properly.
+# RUN: cp -f %S/Inputs/x86-non-temporal.ll %t.ll && %update_llc_test_checks --filter-out="movnt" %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.filter-out.expected
+
+## Check that running the script again does not change the result:
+# RUN: %update_llc_test_checks --filter-out="movnt" %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.filter-out.expected
+
+## Check that multiple filters work properly.
+# RUN: cp -f %S/Inputs/x86-non-temporal.ll %t.ll && %update_llc_test_checks --filter="LCPI[0-9]+_[0-9]+" --filter="movnt" --filter="(%esp|%rsi)" %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.multifilter.expected
+
+## Check that running the script again does not change the result:
+# RUN: %update_llc_test_checks --filter="LCPI[0-9]+_[0-9]+" --filter="movnt" --filter="(%esp|%rsi)" %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.multifilter.expected
+
+## Check that no filtering is done.
+# RUN: cp -f %S/Inputs/x86-non-temporal.ll %t.ll && %update_llc_test_checks %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.nofilter.expected
+
+## Check that running the script again does not change the result:
+# RUN: %update_llc_test_checks %t.ll
+# RUN: 
diff  -u %t.ll %S/Inputs/x86-non-temporal.ll.nofilter.expected

diff  --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py
index c24849bd99d41..95d17baa210e8 100644
--- a/llvm/utils/UpdateTestChecks/asm.py
+++ b/llvm/utils/UpdateTestChecks/asm.py
@@ -456,8 +456,11 @@ def get_run_handler(triple):
 
 ##### Generator of assembly CHECK lines
 
-def add_asm_checks(output_lines, comment_marker, prefix_list, func_dict, func_name):
+def add_asm_checks(output_lines, comment_marker, prefix_list, func_dict,
+                   func_name, is_filtered):
   # Label format is based on ASM string.
   check_label_format = '{} %s-LABEL: %s%s:'.format(comment_marker)
   global_vars_seen_dict = {}
-  common.add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, True, False, global_vars_seen_dict)
+  common.add_checks(output_lines, comment_marker, prefix_list, func_dict,
+                    func_name, check_label_format, True, False,
+                    global_vars_seen_dict, is_filtered = is_filtered)

diff  --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index 269b429d1852c..dbcff53e838cf 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -1,5 +1,6 @@
 from __future__ import print_function
 
+import argparse
 import copy
 import glob
 import os
@@ -13,7 +14,99 @@
 _verbose = False
 _prefix_filecheck_ir_name = ''
 
+class Regex(object):
+  """Wrap a compiled regular expression object to allow deep copy of a regexp.
+  This is required for the deep copy done in do_scrub.
+
+  """
+  def __init__(self, regex):
+    self.regex = regex
+
+  def __deepcopy__(self, memo):
+    result = copy.copy(self)
+    result.regex = self.regex
+    return result
+
+  def search(self, line):
+    return self.regex.search(line)
+
+  def sub(self, repl, line):
+    return self.regex.sub(repl, line)
+
+  def pattern(self):
+    return self.regex.pattern
+
+  def flags(self):
+    return self.regex.flags
+
+class Filter(Regex):
+  """Augment a Regex object with a flag indicating whether a match should be
+    added (!is_filter_out) or removed (is_filter_out) from the generated checks.
+
+  """
+  def __init__(self, regex, is_filter_out):
+    super(Filter, self).__init__(regex)
+    self.is_filter_out = is_filter_out
+
+  def __deepcopy__(self, memo):
+    result = copy.deepcopy(super(Filter, self), memo)
+    result.is_filter_out = copy.deepcopy(self.is_filter_out, memo)
+    return result
+
 def parse_commandline_args(parser):
+  class RegexAction(argparse.Action):
+    """Add a regular expression option value to a list of regular expressions.
+    This compiles the expression, wraps it in a Regex and adds it to the option
+    value list."""
+    def __init__(self, option_strings, dest, nargs=None, **kwargs):
+      if nargs is not None:
+        raise ValueError('nargs not allowed')
+      super(RegexAction, self).__init__(option_strings, dest, **kwargs)
+
+    def do_call(self, namespace, values, flags):
+      value_list = getattr(namespace, self.dest)
+      if value_list is None:
+        value_list = []
+
+      try:
+        value_list.append(Regex(re.compile(values, flags)))
+      except re.error as error:
+        raise ValueError('{}: Invalid regular expression \'{}\' ({})'.format(
+          option_string, error.pattern, error.msg))
+
+      setattr(namespace, self.dest, value_list)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+      self.do_call(namespace, values, 0)
+
+  class FilterAction(RegexAction):
+    """Add a filter to a list of filter option values."""
+    def __init__(self, option_strings, dest, nargs=None, **kwargs):
+      super(FilterAction, self).__init__(option_strings, dest, nargs, **kwargs)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+      super(FilterAction, self).__call__(parser, namespace, values, option_string)
+
+      value_list = getattr(namespace, self.dest)
+
+      is_filter_out = ( option_string == '--filter-out' )
+
+      value_list[-1] = Filter(value_list[-1].regex, is_filter_out)
+
+      setattr(namespace, self.dest, value_list)
+
+  filter_group = parser.add_argument_group(
+    'filtering',
+    """Filters are applied to each output line according to the order given. The
+    first matching filter terminates filter processing for that current line.""")
+
+  filter_group.add_argument('--filter', action=FilterAction, dest='filters',
+                            metavar='REGEX',
+                            help='Only include lines matching REGEX (may be specified multiple times)')
+  filter_group.add_argument('--filter-out', action=FilterAction, dest='filters',
+                            metavar='REGEX',
+                            help='Exclude lines matching REGEX')
+
   parser.add_argument('--include-generated-funcs', action='store_true',
                       help='Output checks for functions not in source')
   parser.add_argument('-v', '--verbose', action='store_true',
@@ -258,6 +351,21 @@ def find_run_lines(test, lines):
     debug('  RUN: {}'.format(l))
   return run_lines
 
+def apply_filters(line, filters):
+  has_filter = False
+  for f in filters:
+    if not f.is_filter_out:
+      has_filter = True
+    if f.search(line):
+      return False if f.is_filter_out else True
+  # If we only used filter-out, keep the line, otherwise discard it since no
+  # filter matched.
+  return False if has_filter else True
+
+def do_filter(body, filters):
+  return body if not filters else '\n'.join(filter(
+    lambda line: apply_filters(line, filters), body.splitlines()))
+
 def scrub_body(body):
   # Scrub runs of whitespace out of the assembly, but leave the leading
   # whitespace in place.
@@ -320,6 +428,11 @@ def __init__(self, run_list, flags, scrubber_args, path):
     self._verbose = flags.verbose
     self._record_args = flags.function_signature
     self._check_attributes = flags.check_attributes
+    # Strip double-quotes if input was read by UTC_ARGS
+    self._filters = list(map(lambda f: Filter(re.compile(f.pattern().strip('"'),
+                                                         f.flags()),
+                                              f.is_filter_out),
+                             flags.filters)) if flags.filters else []
     self._scrubber_args = scrubber_args
     self._path = path
     # Strip double-quotes if input was read by UTC_ARGS
@@ -344,6 +457,9 @@ def func_order(self):
   def global_var_dict(self):
     return self._global_var_dict
 
+  def is_filtered(self):
+    return bool(self._filters)
+
   def process_run_line(self, function_re, scrubber, raw_tool_output, prefixes, is_asm):
     build_global_values_dictionary(self._global_var_dict, raw_tool_output, prefixes)
     for m in function_re.finditer(raw_tool_output):
@@ -360,9 +476,10 @@ def process_run_line(self, function_re, scrubber, raw_tool_output, prefixes, is_
           args_and_sig = '('
       else:
           args_and_sig = ''
-      scrubbed_body = do_scrub(body, scrubber, self._scrubber_args,
+      filtered_body = do_filter(body, self._filters)
+      scrubbed_body = do_scrub(filtered_body, scrubber, self._scrubber_args,
                                extra=False)
-      scrubbed_extra = do_scrub(body, scrubber, self._scrubber_args,
+      scrubbed_extra = do_scrub(filtered_body, scrubber, self._scrubber_args,
                                 extra=True)
       if 'analysis' in m.groupdict():
         analysis = m.group('analysis')
@@ -649,7 +766,7 @@ def transform_line_vars(match):
   return lines
 
 
-def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, is_asm, is_analyze, global_vars_seen_dict):
+def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, is_asm, is_analyze, global_vars_seen_dict, is_filtered):
   # prefix_exclusions are prefixes we cannot use to print the function because it doesn't exist in run lines that use these prefixes as well.
   prefix_exclusions = set()
   printed_prefixes = []
@@ -707,15 +824,26 @@ def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name,
       else:
         output_lines.append(check_label_format % (checkprefix, func_name, args_and_sig))
       func_body = str(func_dict[checkprefix][func_name]).splitlines()
+      if not func_body:
+        # We have filtered everything.
+        continue
 
       # For ASM output, just emit the check lines.
       if is_asm:
-        output_lines.append('%s %s:       %s' % (comment_marker, checkprefix, func_body[0]))
+        body_start = 1
+        if is_filtered:
+          # For filtered output we don't add "-NEXT" so don't add extra spaces
+          # before the first line.
+          body_start = 0
+        else:
+          output_lines.append('%s %s:       %s' % (comment_marker, checkprefix, func_body[0]))
         for func_line in func_body[1:]:
           if func_line.strip() == '':
             output_lines.append('%s %s-EMPTY:' % (comment_marker, checkprefix))
           else:
-            output_lines.append('%s %s-NEXT:  %s' % (comment_marker, checkprefix, func_line))
+            check_suffix = '-NEXT' if not is_filtered else ''
+            output_lines.append('%s %s%s:  %s' % (comment_marker, checkprefix,
+                                                  check_suffix, func_line))
         break
 
       # For IR output, change all defs to FileCheck variables, so we're immune
@@ -747,8 +875,9 @@ def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name,
           output_lines.append('{} {}:       {}'.format(
               comment_marker, checkprefix, func_line))
         else:
-          output_lines.append('{} {}-NEXT:  {}'.format(
-              comment_marker, checkprefix, func_line))
+          check_suffix = '-NEXT' if not is_filtered else ''
+          output_lines.append('{} {}{}:  {}'.format(
+              comment_marker, checkprefix, check_suffix, func_line))
         is_blank_line = False
 
       # Add space between 
diff erent check prefixes and also before the first
@@ -762,18 +891,21 @@ def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name,
       break
 
 def add_ir_checks(output_lines, comment_marker, prefix_list, func_dict,
-                  func_name, preserve_names, function_sig, global_vars_seen_dict):
+                  func_name, preserve_names, function_sig,
+                  global_vars_seen_dict, is_filtered):
   # Label format is based on IR string.
   function_def_regex = 'define {{[^@]+}}' if function_sig else ''
   check_label_format = '{} %s-LABEL: {}@%s%s'.format(comment_marker, function_def_regex)
   add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name,
-             check_label_format, False, preserve_names, global_vars_seen_dict)
+             check_label_format, False, preserve_names, global_vars_seen_dict,
+             is_filtered)
 
 def add_analyze_checks(output_lines, comment_marker, prefix_list, func_dict, func_name):
   check_label_format = '{} %s-LABEL: \'%s%s\''.format(comment_marker)
   global_vars_seen_dict = {}
   add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name,
-             check_label_format, False, True, global_vars_seen_dict)
+             check_label_format, False, True, global_vars_seen_dict,
+             is_filtered = False)
 
 def build_global_values_dictionary(glob_val_dict, raw_tool_output, prefixes):
   for nameless_value in nameless_values:
@@ -901,11 +1033,21 @@ def get_autogennote_suffix(parser, args):
         continue
     if parser.get_default(action.dest) == value:
       continue  # Don't add default values
-    autogenerated_note_args += action.option_strings[0] + ' '
-    if action.const is None:  # action takes a parameter
-      if action.nargs == '+':
-        value = ' '.join(map(lambda v: '"' + v.strip('"') + '"', value))
-      autogenerated_note_args += '%s ' % value
+    if action.dest == 'filters':
+      # Create a separate option for each filter element.  The value is a list
+      # of Filter objects.
+      for elem in value:
+        opt_name = 'filter-out' if elem.is_filter_out else 'filter'
+        opt_value = elem.pattern()
+        new_arg = '--%s "%s" ' % (opt_name, opt_value.strip('"'))
+        if new_arg not in autogenerated_note_args:
+          autogenerated_note_args += new_arg
+    else:
+      autogenerated_note_args += action.option_strings[0] + ' '
+      if action.const is None:  # action takes a parameter
+        if action.nargs == '+':
+          value = ' '.join(map(lambda v: '"' + v.strip('"') + '"', value))
+        autogenerated_note_args += '%s ' % value
   if autogenerated_note_args:
     autogenerated_note_args = ' %s %s' % (UTC_ARGS_KEY, autogenerated_note_args[:-1])
   return autogenerated_note_args

diff  --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py
index 15318e19fd66d..d9c53c38796ae 100755
--- a/llvm/utils/update_cc_test_checks.py
+++ b/llvm/utils/update_cc_test_checks.py
@@ -344,11 +344,13 @@ def check_generator(my_output_lines, prefixes, func):
                                prefixes,
                                func_dict, func, False,
                                ti.args.function_signature,
-                               global_vars_seen_dict)
+                               global_vars_seen_dict,
+                               is_filtered=builder.is_filtered())
         else:
           asm.add_asm_checks(my_output_lines, '//',
                              prefixes,
-                             func_dict, func)
+                             func_dict, func,
+                             is_filtered=builder.is_filtered())
 
       if ti.args.check_globals:
         common.add_global_checks(builder.global_var_dict(), '//', run_list,
@@ -398,7 +400,8 @@ def check_generator(my_output_lines, prefixes, func):
                 output_lines.append('//')
               added.add(mangled)
               common.add_ir_checks(output_lines, '//', filecheck_run_list, func_dict, mangled,
-                                   False, args.function_signature, global_vars_seen_dict)
+                                   False, args.function_signature, global_vars_seen_dict,
+                                   is_filtered=builder.is_filtered())
               if line.rstrip('\n') == '//':
                 include_line = False
 

diff  --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py
index a9e86eaa069b3..cf68d2384862c 100755
--- a/llvm/utils/update_llc_test_checks.py
+++ b/llvm/utils/update_llc_test_checks.py
@@ -111,6 +111,7 @@ def main():
         run_list=run_list,
         flags=type('', (object,), {
             'verbose': ti.args.verbose,
+            'filters': ti.args.filters,
             'function_signature': False,
             'check_attributes': False,
             'replace_value_regex': []}),
@@ -161,7 +162,8 @@ def main():
                                lambda my_output_lines, prefixes, func:
                                asm.add_asm_checks(my_output_lines,
                                                   check_indent + ';',
-                                                  prefixes, func_dict, func))
+                                                  prefixes, func_dict, func,
+                                                  is_filtered=builder.is_filtered()))
     else:
       for input_info in ti.iterlines(output_lines):
         input_line = input_info.line
@@ -176,7 +178,9 @@ def main():
               continue
 
           # Print out the various check lines here.
-          asm.add_asm_checks(output_lines, check_indent + ';', run_list, func_dict, func_name)
+          asm.add_asm_checks(output_lines, check_indent + ';', run_list,
+                             func_dict, func_name,
+                             is_filtered=builder.is_filtered())
           is_in_function_start = False
 
         if is_in_function:

diff  --git a/llvm/utils/update_test_checks.py b/llvm/utils/update_test_checks.py
index d7fce8d931633..dee3a5133f56f 100755
--- a/llvm/utils/update_test_checks.py
+++ b/llvm/utils/update_test_checks.py
@@ -160,7 +160,8 @@ def main():
                                                     prefixes,
                                                     func_dict, func, False,
                                                     args.function_signature,
-                                                    global_vars_seen_dict))
+                                                    global_vars_seen_dict,
+                                                    is_filtered=builder.is_filtered()))
     else:
       # "Normal" mode.
       for input_line_info in ti.iterlines(output_lines):
@@ -178,7 +179,8 @@ def main():
           # Print out the various check lines here.
           common.add_ir_checks(output_lines, ';', prefix_list, func_dict,
                                func_name, args.preserve_names, args.function_signature,
-                               global_vars_seen_dict)
+                               global_vars_seen_dict,
+                               is_filtered=builder.is_filtered())
           is_in_function_start = False
 
         m = common.IR_FUNCTION_RE.match(input_line)


        


More information about the llvm-commits mailing list