From 0a1019144f8a74e1b5f5b949c55a8872a8915317 Mon Sep 17 00:00:00 2001 From: Camsyn Date: Thu, 30 Oct 2025 21:24:04 +0800 Subject: [PATCH 1/8] [UTC] CHECK-EMPTY instead of skiping blank lines --- llvm/utils/UpdateTestChecks/common.py | 36 +++++++-------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 119303c319246..48f82b563f596 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -2292,42 +2292,24 @@ def add_checks( ignore_all_comments=not check_inst_comments, ) - # This could be selectively enabled with an optional invocation argument. - # Disabled for now: better to check everything. Be safe rather than sorry. - - # Handle the first line of the function body as a special case because - # it's often just noise (a useless asm comment or entry label). - # if func_body[0].startswith("#") or func_body[0].startswith("entry:"): - # is_blank_line = True - # else: - # output_lines.append('%s %s: %s' % (comment_marker, checkprefix, func_body[0])) - # is_blank_line = False - - is_blank_line = False for func_line in func_body: if func_line.strip() == "": - is_blank_line = True + # Instead of skipping blank lines, using CHECK_EMPTY is more defensive. + output_lines.append( + "{} {}-EMPTY:".format(comment_marker, checkprefix) + ) continue if not check_inst_comments: # Do not waste time checking IR comments unless necessary. func_line = SCRUB_IR_COMMENT_RE.sub(r"", func_line) - # Skip blank lines instead of checking them. - if is_blank_line: - output_lines.append( - "{} {}: {}".format( - comment_marker, checkprefix, func_line - ) - ) - else: - check_suffix = "-NEXT" if not is_filtered else "" - output_lines.append( - "{} {}{}: {}".format( - comment_marker, checkprefix, check_suffix, 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 different check prefixes and also before the first # line of code in the test function. From 80f8e57c5691e75b28a85b81b7a5a2a6409a4638 Mon Sep 17 00:00:00 2001 From: Camsyn Date: Thu, 30 Oct 2025 21:24:17 +0800 Subject: [PATCH 2/8] Add a test --- .../update_test_checks/Inputs/check_empty.ll | 29 ++++++++++ .../Inputs/check_empty.ll.expected | 57 +++++++++++++++++++ .../update_test_checks/check_empty.test | 3 + 3 files changed, 89 insertions(+) create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll new file mode 100644 index 0000000000000..abaa0ce2dd3b4 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -S | FileCheck %s + +; Test whether the UTC check empty lines instead of skipping them. +define i32 @test(i32 %x) { +entry: + br label %block1 + +block1: + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %block2, label %exit1 + +block2: + br i1 %cmp, label %block3, label %exit2 + +block3: + br i1 %cmp, label %exit3, label %exit4 + +exit1: + ret i32 0 + +exit2: + ret i32 %x + +exit3: + ret i32 %x + +exit4: + ret i32 %x +} diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected new file mode 100644 index 0000000000000..dc2a37907039e --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt < %s -S | FileCheck %s + +; Test whether the UTC check empty lines instead of skipping them. +define i32 @test(i32 %x) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: br label %[[BLOCK1:.*]] +; CHECK-EMPTY: +; CHECK-NEXT: [[BLOCK1]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 0 +; CHECK-NEXT: br i1 [[CMP]], label %[[BLOCK2:.*]], label %[[EXIT1:.*]] +; CHECK-EMPTY: +; CHECK-NEXT: [[BLOCK2]]: +; CHECK-NEXT: br i1 [[CMP]], label %[[BLOCK3:.*]], label %[[EXIT2:.*]] +; CHECK-EMPTY: +; CHECK-NEXT: [[BLOCK3]]: +; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT3:.*]], label %[[EXIT4:.*]] +; CHECK-EMPTY: +; CHECK-NEXT: [[EXIT1]]: +; CHECK-NEXT: ret i32 0 +; CHECK-EMPTY: +; CHECK-NEXT: [[EXIT2]]: +; CHECK-NEXT: ret i32 [[X]] +; CHECK-EMPTY: +; CHECK-NEXT: [[EXIT3]]: +; CHECK-NEXT: ret i32 [[X]] +; CHECK-EMPTY: +; CHECK-NEXT: [[EXIT4]]: +; CHECK-NEXT: ret i32 [[X]] +; +entry: + br label %block1 + +block1: + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %block2, label %exit1 + +block2: + br i1 %cmp, label %block3, label %exit2 + +block3: + br i1 %cmp, label %exit3, label %exit4 + +exit1: + ret i32 0 + +exit2: + ret i32 %x + +exit3: + ret i32 %x + +exit4: + ret i32 %x +} diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test b/llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test new file mode 100644 index 0000000000000..61e85152db951 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test @@ -0,0 +1,3 @@ +## test whether the UTC generates CHECK-EMPTY for blank lines +# RUN: cp -f %S/Inputs/check_empty.ll %t.ll && %update_test_checks %t.ll +# RUN: diff -u %t.ll %S/Inputs/check_empty.ll.expected From 0169a6732bdaf7b196527479db978b94ace12b1b Mon Sep 17 00:00:00 2001 From: Camsyn Date: Fri, 31 Oct 2025 19:53:17 +0800 Subject: [PATCH 3/8] Gate the new change with version 7 --- .../Inputs/check_empty.ll.expected | 2 +- .../update_test_checks/check_empty.test | 2 +- llvm/utils/UpdateTestChecks/common.py | 43 ++++++++++++++----- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected index dc2a37907039e..f52687da3632b 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 7 ; RUN: opt < %s -S | FileCheck %s ; Test whether the UTC check empty lines instead of skipping them. diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test b/llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test index 61e85152db951..670bda27bb369 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/check_empty.test @@ -1,3 +1,3 @@ ## test whether the UTC generates CHECK-EMPTY for blank lines -# RUN: cp -f %S/Inputs/check_empty.ll %t.ll && %update_test_checks %t.ll +# RUN: cp -f %S/Inputs/check_empty.ll %t.ll && %update_test_checks %t.ll --version 7 # RUN: diff -u %t.ll %S/Inputs/check_empty.ll.expected diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 48f82b563f596..d0932c28b207e 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -29,7 +29,7 @@ 'none' and 'all'. 'smart' is the default. 5: Basic block labels are matched by FileCheck expressions 6: The semantics of TBAA checks has been incorporated in the check lines. -7: Indent switch-cases correctly. +7: Indent switch-cases correctly; CHECK-EMPTY instead of skipping blank lines. """ DEFAULT_VERSION = 6 @@ -2292,24 +2292,47 @@ def add_checks( ignore_all_comments=not check_inst_comments, ) + # This could be selectively enabled with an optional invocation argument. + # Disabled for now: better to check everything. Be safe rather than sorry. + + # Handle the first line of the function body as a special case because + # it's often just noise (a useless asm comment or entry label). + # if func_body[0].startswith("#") or func_body[0].startswith("entry:"): + # is_blank_line = True + # else: + # output_lines.append('%s %s: %s' % (comment_marker, checkprefix, func_body[0])) + # is_blank_line = False + + is_blank_line = False for func_line in func_body: if func_line.strip() == "": - # Instead of skipping blank lines, using CHECK_EMPTY is more defensive. - output_lines.append( - "{} {}-EMPTY:".format(comment_marker, checkprefix) - ) + if ginfo.get_version() >= 7: + output_lines.append( + "{} {}-EMPTY:".format(comment_marker, checkprefix) + ) + else: + is_blank_line = True continue if not check_inst_comments: # Do not waste time checking IR comments unless necessary. func_line = SCRUB_IR_COMMENT_RE.sub(r"", func_line) - check_suffix = "-NEXT" if not is_filtered else "" - output_lines.append( - "{} {}{}: {}".format( - comment_marker, checkprefix, check_suffix, func_line + # Skip blank lines instead of checking them. + if is_blank_line: + output_lines.append( + "{} {}: {}".format( + comment_marker, checkprefix, func_line + ) ) - ) + else: + 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 different check prefixes and also before the first # line of code in the test function. From b990bd968f05423582305cb61fc7ba6112c682fc Mon Sep 17 00:00:00 2001 From: Camsyn Date: Fri, 31 Oct 2025 21:05:03 +0800 Subject: [PATCH 4/8] Regenerate a test --- .../Inputs/switch_case.ll.expected | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/switch_case.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/switch_case.ll.expected index b1977e7ae2ee2..8cab0bbf304f3 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/switch_case.ll.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/switch_case.ll.expected @@ -12,13 +12,17 @@ define i8 @testi8(i8 %x) { ; CHECK-NEXT: i8 2, label %[[CASE3:.*]] ; CHECK-NEXT: i8 3, label %[[CASE3]] ; CHECK-NEXT: ] -; CHECK: [[DEFAULT]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[DEFAULT]]: ; CHECK-NEXT: ret i8 0 -; CHECK: [[CASE1]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE1]]: ; CHECK-NEXT: ret i8 1 -; CHECK: [[CASE2]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE2]]: ; CHECK-NEXT: ret i8 2 -; CHECK: [[CASE3]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE3]]: ; CHECK-NEXT: ret i8 3 ; switch i8 %x, label %default [ @@ -46,13 +50,17 @@ define i32 @testi32(i32 %x) { ; CHECK-NEXT: i32 2, label %[[CASE3:.*]] ; CHECK-NEXT: i32 3, label %[[CASE3]] ; CHECK-NEXT: ] -; CHECK: [[DEFAULT]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[DEFAULT]]: ; CHECK-NEXT: ret i32 0 -; CHECK: [[CASE1]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE1]]: ; CHECK-NEXT: ret i32 1 -; CHECK: [[CASE2]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE2]]: ; CHECK-NEXT: ret i32 2 -; CHECK: [[CASE3]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE3]]: ; CHECK-NEXT: ret i32 3 ; switch i32 %x, label %default [ @@ -80,13 +88,17 @@ define i128 @testi128(i128 %x) { ; CHECK-NEXT: i128 2, label %[[CASE3:.*]] ; CHECK-NEXT: i128 3, label %[[CASE3]] ; CHECK-NEXT: ] -; CHECK: [[DEFAULT]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[DEFAULT]]: ; CHECK-NEXT: ret i128 0 -; CHECK: [[CASE1]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE1]]: ; CHECK-NEXT: ret i128 1 -; CHECK: [[CASE2]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE2]]: ; CHECK-NEXT: ret i128 2 -; CHECK: [[CASE3]]: +; CHECK-EMPTY: +; CHECK-NEXT: [[CASE3]]: ; CHECK-NEXT: ret i128 3 ; switch i128 %x, label %default [ From 2804b2c3e483be2101576bdd95655b463b89ef88 Mon Sep 17 00:00:00 2001 From: Camsyn Date: Fri, 31 Oct 2025 21:26:56 +0800 Subject: [PATCH 5/8] Distinguish 'Fake' blank lines --- llvm/utils/UpdateTestChecks/common.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index d0932c28b207e..52d700bef0b75 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -2280,6 +2280,9 @@ def add_checks( # For IR output, change all defs to FileCheck variables, so we're immune # to variable naming fashions. else: + blank_line_indices = { + i for i, line in enumerate(func_body) if line.strip() == "" + } if ginfo.get_version() >= 7 else set() func_body = generalize_check_lines( func_body, ginfo, @@ -2305,9 +2308,13 @@ def add_checks( is_blank_line = False - for func_line in func_body: + for idx, func_line in enumerate(func_body): if func_line.strip() == "": - if ginfo.get_version() >= 7: + # We should distinguish if the line is a 'fake' blank line generated by + # generalize_check_lines removing comments. + # Fortunately, generalize_check_lines does not change the index of each line, + # we can record the indices of blank lines preemptively. + if idx in blank_line_indices: output_lines.append( "{} {}-EMPTY:".format(comment_marker, checkprefix) ) From 895f1d9f464b20dc6196b8585a5f3d108ac54ce9 Mon Sep 17 00:00:00 2001 From: Camsyn Date: Fri, 31 Oct 2025 21:41:15 +0800 Subject: [PATCH 6/8] Make formatter happy --- llvm/utils/UpdateTestChecks/common.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 52d700bef0b75..04a0f9f62c16a 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -2280,9 +2280,12 @@ def add_checks( # For IR output, change all defs to FileCheck variables, so we're immune # to variable naming fashions. else: - blank_line_indices = { - i for i, line in enumerate(func_body) if line.strip() == "" - } if ginfo.get_version() >= 7 else set() + if ginfo.get_version() >= 7: + # Record the indices of blank lines in the function body preemptively. + blank_line_indices = { i for i, line in enumerate(func_body) if line.strip() == "" } + else: + blank_line_indices = set() + func_body = generalize_check_lines( func_body, ginfo, From 6f0f7fb4c426ec04cbbf232f68d4372554b964ac Mon Sep 17 00:00:00 2001 From: Camsyn Date: Fri, 31 Oct 2025 21:45:04 +0800 Subject: [PATCH 7/8] Make formatter happy --- llvm/utils/UpdateTestChecks/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 04a0f9f62c16a..2dad16a8eebb7 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -2282,7 +2282,9 @@ def add_checks( else: if ginfo.get_version() >= 7: # Record the indices of blank lines in the function body preemptively. - blank_line_indices = { i for i, line in enumerate(func_body) if line.strip() == "" } + blank_line_indices = { + i for i, line in enumerate(func_body) if line.strip() == "" + } else: blank_line_indices = set() From 2fa0f8e9d5b1ea20c661c177faabc4367746eeeb Mon Sep 17 00:00:00 2001 From: Camsyn Date: Sat, 1 Nov 2025 15:28:25 +0800 Subject: [PATCH 8/8] Fix comments --- .../UpdateTestChecks/update_test_checks/Inputs/check_empty.ll | 2 +- .../update_test_checks/Inputs/check_empty.ll.expected | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll index abaa0ce2dd3b4..bfd216d1ced49 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -S | FileCheck %s -; Test whether the UTC check empty lines instead of skipping them. +; Test whether UTC checks empty lines instead of skipping them. define i32 @test(i32 %x) { entry: br label %block1 diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected index f52687da3632b..c5f822d10181a 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/check_empty.ll.expected @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 7 ; RUN: opt < %s -S | FileCheck %s -; Test whether the UTC check empty lines instead of skipping them. +; Test whether UTC checks empty lines instead of skipping them. define i32 @test(i32 %x) { ; CHECK-LABEL: define i32 @test( ; CHECK-SAME: i32 [[X:%.*]]) {