llvm / llvm/llvm-project

[MLIR][cf] `cf.switch` custom syntax cannot round-trip case values wider than 64 bits

Open
#220,609 0 comments 0 reactions 0 assignees View on GitHub
mlir:cf
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Reproduced at c5ba1bf401fff557ad9fdcda0dba64d1e0a4c4af.

## Summary

`cf.switch` accepts an arbitrary integer flag type and its generic form can represent case values wider than 64 bits. Its custom printer saturates such values through `APInt::getLimitedValue()`, while its custom parser reads case values through an `int64_t`. Consequently, valid generic IR loses information when printed with the custom syntax and the printed output cannot be parsed.

## Reproducer

```mlir
"builtin.module"() ({
"func.func"() <{function_type = () -> i32, sym_name = "switch_i128_large_cases"}> ({
%flag = "arith.constant"() <{value = 18446744073709551617 : i128}> : () -> i128
%zero = "arith.constant"() <{value = 0 : i32}> : () -> i32
%one = "arith.constant"() <{value = 1 : i32}> : () -> i32
%two = "arith.constant"() <{value = 2 : i32}> : () -> i32
"cf.switch"(%flag, %zero, %one, %two)[^bb1, ^bb1, ^bb1] <{case_operand_segments = array, case_values = dense<[18446744073709551616, 18446744073709551617]> : vector<2xi128>, operandSegmentSizes = array}> : (i128, i32, i32, i32) -> ()
^bb1(%result: i32):
"func.return"(%result) : (i32) -> ()
}) : () -> ()
}) : () -> ()
```

## Command

```shell
build/bin/mlir-opt input.mlir | build/bin/mlir-opt
```

## Actual behavior

The first invocation prints both distinct case values as `18446744073709551615`. The second invocation then fails:

```text
error: custom op 'cf.switch' integer value too large
```

Running `-canonicalize` directly on the generic input succeeds and selects the second case, showing that the in-memory `APInt` values and the existing exact fold comparison remain distinct.

## Expected behavior

The custom syntax should preserve both i128 case values and round-trip without an error or semantic change.

## Note

PR #129266 removed `getLimitedValue()` from the LLVM dialect's `llvm.switch` custom printer so that its `APInt` case values round-trip. The corresponding ControlFlow dialect printer still uses `getLimitedValue()`.

Contributor guide

Open the contributing guide

Research direction

Start with the cf.switch custom printer and parser, using the provided generic i128 reproducer and the `build/bin/mlir-opt input.mlir | build/bin/mlir-opt` command. Compare the handling of case values with the existing exact fold comparison and the noted llvm.switch change. Done means distinct wide case values survive custom printing and the output parses and round-trips without semantic change.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.