From 18ad761df0f7bfff2ab64a16ab6374a9cd644f32 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Fri, 27 Mar 2026 14:59:42 +0100 Subject: [PATCH] [mlir] Fix generate-test-checks.py: don't put attr refs in CHECK-LABEL (#188985) Two related bugs in generate-test-checks.py when a top-level operation carries attribute alias references (e.g. `#map`, `#map1`) in its signature: 1. The attribute reference substitution (replacing `#map` with `#[[$ATTR_0]]`) ran *before* the pending attribute definitions were processed, so the names were not yet available and the references were left as-is in the output. 2. CHECK-LABEL lines do not support FileCheck variable references (e.g. `#[[$ATTR_0]]`), so even after substitution the generated check would be syntactically wrong. Fix both issues: - In the CHECK-LABEL branch, re-apply `process_attribute_references` to the label prefix and SSA-split rest after flushing pending attribute definitions, so that names are resolved. - Split the label prefix at attribute reference boundaries; keep only the text before the first reference in the CHECK-LABEL line and emit the remainder on a CHECK-SAME line. Before: // CHECK-LABEL: func.func @test() attributes {amap = #map, bmap = #map1} { After: // CHECK-LABEL: func.func @test() attributes {amap = // CHECK-SAME: #[[$ATTR_0]], bmap = #[[$ATTR_1]]} { Fixes #162310 Assisted-by: Claude Code --- mlir/utils/generate-test-checks.py | 53 +++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/mlir/utils/generate-test-checks.py b/mlir/utils/generate-test-checks.py index 22774468bb40..d8d2cb020c27 100755 --- a/mlir/utils/generate-test-checks.py +++ b/mlir/utils/generate-test-checks.py @@ -63,6 +63,11 @@ ATTR_RE = re.compile(ATTR_RE_STR) ATTR_DEF_RE_STR = r'\s*' + ATTR_RE_STR + r'\s*=' ATTR_DEF_RE = re.compile(ATTR_DEF_RE_STR) +# Regex matching a FileCheck attribute variable reference produced by this script, +# e.g. #[[$ATTR_0]] or #[[$ATTR_0:.+]]. Used to detect references that cannot +# appear in a CHECK-LABEL line (CHECK-LABEL does not support variable references). +ATTR_REF_IN_LABEL_RE = re.compile(r"(#\[\[\$[^\]]*\]\])") + # Class used to generate and manage string substitution blocks for SSA value # names. @@ -446,26 +451,52 @@ def main(): output_line += process_line(ssa_split[1:], variable_namer) else: - # Emit any pending attribute definitions at the start of this scope + # Emit any pending attribute definitions at the start of this scope. + # This must happen *before* re-processing the label line's attribute + # references below, so that names are available for substitution. for attr in pending_attr_defs: attr_line = process_attribute_definition(attr, attribute_namer) if attr_line: output_segments[-1].append(attr_line) pending_attr_defs.clear() - # Output the first line chunk that does not contain an SSA name for the - # label. - output_line = "// " + args.check_prefix + "-LABEL: " + ssa_split[0] + "\n" + # Re-apply attribute reference substitution now that names have been + # generated by the pending attribute definitions above. The first call + # at line 431 may have run before the names were defined. + label_prefix = process_attribute_references(ssa_split[0], attribute_namer) + ssa_rest = [ + process_attribute_references(arg, attribute_namer) + for arg in ssa_split[1:] + ] + + # CHECK-LABEL does not support FileCheck variable references such as + # #[[$ATTR_0]]. If the label prefix contains attribute references, split + # at the first one: keep only the text before it in the CHECK-LABEL line + # and move the remainder to a following CHECK-SAME line. + label_attr_parts = ATTR_REF_IN_LABEL_RE.split(label_prefix) + + output_line = ( + "// " + + args.check_prefix + + "-LABEL: " + + label_attr_parts[0].rstrip() + + "\n" + ) + + # Pad continuation lines to align with the end of the label prefix + # (capped at 20 chars to avoid excessive indentation). + label_length = len(label_attr_parts[0]) + pad_depth = label_length if label_length < 21 else 4 + + # Emit any attribute references from the label prefix as CHECK-SAME. + if len(label_attr_parts) > 1: + output_line += "// " + args.check_prefix + "-SAME: " + output_line += " " * pad_depth + output_line += "".join(label_attr_parts[1:]).rstrip() + "\n" # Process the rest of the input line on separate check lines. - for argument in ssa_split[1:]: + for argument in ssa_rest: output_line += "// " + args.check_prefix + "-SAME: " - - # Pad to align with the original position in the line (i.e. where the label ends), - # unless the label is more than 20 chars long, in which case pad with 4 spaces - # (this is to avoid deep indentation). - label_length = len(ssa_split[0]) - pad_depth = label_length if label_length < 21 else 4 output_line += " " * pad_depth # Process the rest of the line. Use the original SSA name to generate the LIT