[Mlir-commits] [mlir] [mlir][cf] Fix switch case value round-tripping (PR #226660)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Sep 26 01:41:58 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Ziliang Zhang (ziliangzl)

<details>
<summary>Changes</summary>

Fixes #<!-- -->225658.

`cf.switch` printed negative case values as unsigned integers, producing text that could not be parsed back. Print case values as signed APInts, parse arbitrary-width values, and diagnose values outside the flag type range.

Tests cover custom and generic round-tripping plus signed, unsigned, and overflow boundaries for i1, i8, i64, and i128.

---
Full diff: https://github.com/llvm/llvm-project/pull/226660.diff


3 Files Affected:

- (modified) mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp (+10-3) 
- (modified) mlir/test/Dialect/ControlFlow/invalid.mlir (+96) 
- (modified) mlir/test/Dialect/ControlFlow/ops.mlir (+99-1) 


``````````diff
diff --git a/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp
index 9016d1929f859..b39fe1e2ca420 100644
--- a/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp
+++ b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp
@@ -647,10 +647,17 @@ static ParseResult parseSwitchOpCases(
   SmallVector<APInt> values;
   unsigned bitWidth = flagType.getIntOrFloatBitWidth();
   while (succeeded(parser.parseOptionalComma())) {
-    int64_t value = 0;
+    SMLoc valueLoc = parser.getCurrentLocation();
+    APInt value;
     if (failed(parser.parseInteger(value)))
       return failure();
-    values.push_back(APInt(bitWidth, value, /*isSigned=*/true));
+    // Signless integers accept negative values in the signed range and
+    // non-negative values in the unsigned range.
+    if ((value.isNegative() && !value.isSignedIntN(bitWidth)) ||
+        (!value.isNegative() && !value.isIntN(bitWidth)))
+      return parser.emitError(valueLoc)
+             << "case value does not fit in flag type " << flagType;
+    values.push_back(value.sextOrTrunc(bitWidth));
 
     Block *destination;
     SmallVector<OpAsmParser::UnresolvedOperand> operands;
@@ -693,7 +700,7 @@ static void printSwitchOpCases(
     p << ',';
     p.printNewline();
     p << "  ";
-    p << it.value().getLimitedValue();
+    it.value().print(p.getStream(), /*isSigned=*/true);
     p << ": ";
     p.printSuccessorAndUseList(caseDestinations[it.index()],
                                caseOperands[it.index()]);
diff --git a/mlir/test/Dialect/ControlFlow/invalid.mlir b/mlir/test/Dialect/ControlFlow/invalid.mlir
index 0a71c62ec31af..1ecd47b2702ff 100644
--- a/mlir/test/Dialect/ControlFlow/invalid.mlir
+++ b/mlir/test/Dialect/ControlFlow/invalid.mlir
@@ -70,6 +70,102 @@ func.func @switch_missing_default(%flag : i32, %caseOperand : i32) {
 
 // -----
 
+func.func @switch_i1_positive_overflow(%flag : i1) {
+  cf.switch %flag : i1, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i1'}}
+    2: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
+func.func @switch_i1_negative_overflow(%flag : i1) {
+  cf.switch %flag : i1, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i1'}}
+    -2: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
+func.func @switch_i8_positive_overflow(%flag : i8) {
+  cf.switch %flag : i8, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i8'}}
+    256: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
+func.func @switch_i8_negative_overflow(%flag : i8) {
+  cf.switch %flag : i8, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i8'}}
+    -129: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
+func.func @switch_i64_positive_overflow(%flag : i64) {
+  cf.switch %flag : i64, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i64'}}
+    18446744073709551616: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
+func.func @switch_i64_negative_overflow(%flag : i64) {
+  cf.switch %flag : i64, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i64'}}
+    -9223372036854775809: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
+func.func @switch_i128_positive_overflow(%flag : i128) {
+  cf.switch %flag : i128, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i128'}}
+    340282366920938463463374607431768211456: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
+func.func @switch_i128_negative_overflow(%flag : i128) {
+  cf.switch %flag : i128, [
+    default: ^bb1,
+    // expected-error at +1 {{case value does not fit in flag type 'i128'}}
+    -170141183460469231731687303715884105729: ^bb1
+  ]
+^bb1:
+  return
+}
+
+// -----
+
 // CHECK-LABEL: func @wrong_weights_number
 func.func @wrong_weights_number(%cond: i1) {
   // expected-error at +1 {{expects number of branch weights to match number of successors: 1 vs 2}}
diff --git a/mlir/test/Dialect/ControlFlow/ops.mlir b/mlir/test/Dialect/ControlFlow/ops.mlir
index 03091a95b456e..629ba89fb39b9 100644
--- a/mlir/test/Dialect/ControlFlow/ops.mlir
+++ b/mlir/test/Dialect/ControlFlow/ops.mlir
@@ -8,11 +8,13 @@ func.func @assert(%arg : i1) {
 }
 
 // CHECK-LABEL: func @switch(
+// CHECK: -1:
 func.func @switch(%flag : i32, %caseOperand : i32) {
   cf.switch %flag : i32, [
     default: ^bb1(%caseOperand : i32),
     42: ^bb2(%caseOperand : i32),
-    43: ^bb3(%caseOperand : i32)
+    43: ^bb3(%caseOperand : i32),
+    -1: ^bb4(%caseOperand : i32)
   ]
 
   ^bb1(%bb1arg : i32):
@@ -21,6 +23,8 @@ func.func @switch(%flag : i32, %caseOperand : i32) {
     return
   ^bb3(%bb3arg : i32):
     return
+  ^bb4(%bb4arg : i32):
+    return
 }
 
 // CHECK-LABEL: func @switch_i64(
@@ -39,6 +43,100 @@ func.func @switch_i64(%flag : i64, %caseOperand : i32) {
     return
 }
 
+// CHECK-LABEL: func @switch_i1_unsigned_boundary(
+// CHECK: -1:
+func.func @switch_i1_unsigned_boundary(%flag : i1) {
+  cf.switch %flag : i1, [
+    default: ^bb1,
+    1: ^bb1
+  ]
+
+  ^bb1:
+    return
+}
+
+// CHECK-LABEL: func @switch_i8_signed_boundaries(
+// CHECK: -128:
+// CHECK: 127:
+func.func @switch_i8_signed_boundaries(%flag : i8) {
+  cf.switch %flag : i8, [
+    default: ^bb1,
+    -128: ^bb1,
+    127: ^bb1
+  ]
+
+  ^bb1:
+    return
+}
+
+// CHECK-LABEL: func @switch_i8_unsigned_boundaries(
+// CHECK: -128:
+// CHECK: -1:
+func.func @switch_i8_unsigned_boundaries(%flag : i8) {
+  cf.switch %flag : i8, [
+    default: ^bb1,
+    128: ^bb1,
+    255: ^bb1
+  ]
+
+  ^bb1:
+    return
+}
+
+// CHECK-LABEL: func @switch_i64_signed_boundaries(
+// CHECK: -9223372036854775808:
+// CHECK: 9223372036854775807:
+func.func @switch_i64_signed_boundaries(%flag : i64) {
+  cf.switch %flag : i64, [
+    default: ^bb1,
+    -9223372036854775808: ^bb1,
+    9223372036854775807: ^bb1
+  ]
+
+  ^bb1:
+    return
+}
+
+// CHECK-LABEL: func @switch_i64_unsigned_boundary(
+// CHECK: -1:
+func.func @switch_i64_unsigned_boundary(%flag : i64) {
+  cf.switch %flag : i64, [
+    default: ^bb1,
+    18446744073709551615: ^bb1
+  ]
+
+  ^bb1:
+    return
+}
+
+// CHECK-LABEL: func @switch_i128_signed_boundaries(
+// CHECK: -170141183460469231731687303715884105728:
+// CHECK: 170141183460469231731687303715884105727:
+func.func @switch_i128_signed_boundaries(%flag : i128) {
+  cf.switch %flag : i128, [
+    default: ^bb1,
+    -170141183460469231731687303715884105728: ^bb1,
+    170141183460469231731687303715884105727: ^bb1
+  ]
+
+  ^bb1:
+    return
+}
+
+// CHECK-LABEL: func @switch_i128_unsigned_boundaries(
+// CHECK: -170141183460469231731687303715884105728:
+// CHECK: -1:
+func.func @switch_i128_unsigned_boundaries(%flag : i128) {
+  cf.switch %flag : i128, [
+    default: ^bb1,
+    170141183460469231731687303715884105728: ^bb1,
+    340282366920938463463374607431768211455: ^bb1
+  ]
+
+  ^bb1:
+    return
+}
+
 // CHECK-LABEL: func @switch_result_number
 func.func @switch_result_number(%arg0: i32) {
   %0:2 = "test.op_with_two_results"() : () -> (i32, i32)

``````````

</details>


https://github.com/llvm/llvm-project/pull/226660


More information about the Mlir-commits mailing list