[Mlir-commits] [mlir] [MLIR][EmitC] Fix crash in SwitchOp::getEntrySuccessorRegions on unsigned integer type (PR #188546)

Mehdi Amini llvmlistbot at llvm.org
Thu Mar 26 06:35:24 PDT 2026


https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/188546

>From ededfe2fe3af8a09bf7bd4a4a4148df38c73ba1d Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Wed, 25 Mar 2026 08:25:45 -0700
Subject: [PATCH] [MLIR][EmitC] Fix crash in SwitchOp::getEntrySuccessorRegions
 on unsigned integer type

SwitchOp::getEntrySuccessorRegions and getRegionInvocationBounds called
IntegerAttr::getInt() to retrieve the constant switch argument, but
getInt() asserts that the attribute type must be a signless integer or
index. For unsigned integer types (e.g. ui32), this assertion fired and
crashed the process.

Fix by selecting the appropriate accessor based on the attribute type:
getInt() for signless/index, getSInt() for signed, and getUInt() (cast
to int64_t) for unsigned integer types. Unknown types fall back to the
conservative "all regions possible" path.

The same fix is applied to getRegionInvocationBounds, which had an
identical call to getInt().

Fixes #187973

Assisted-by: Claude Code
---
 mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 31 +++++++++++++++++++++++++++--
 mlir/test/Transforms/sccp.mlir      | 21 +++++++++++++++++++
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 6979f34c1e047..8def84fc49378 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1551,6 +1551,19 @@ void SwitchOp::getSuccessorRegions(
   llvm::append_range(successors, getRegions());
 }
 
+/// Returns the int64_t value of an IntegerAttr regardless of whether its type
+/// is signless, signed, or unsigned. Returns std::nullopt for unknown types.
+static std::optional<int64_t> getIntAttrValue(IntegerAttr attr) {
+  Type type = attr.getType();
+  if (type.isIndex() || type.isSignlessInteger())
+    return attr.getInt();
+  if (type.isSignedInteger())
+    return attr.getSInt();
+  if (type.isUnsignedInteger())
+    return static_cast<int64_t>(attr.getUInt());
+  return std::nullopt;
+}
+
 void SwitchOp::getEntrySuccessorRegions(
     ArrayRef<Attribute> operands,
     SmallVectorImpl<RegionSuccessor> &successors) {
@@ -1563,10 +1576,17 @@ void SwitchOp::getEntrySuccessorRegions(
     return;
   }
 
+  std::optional<int64_t> argValue = getIntAttrValue(arg);
+  if (!argValue) {
+    // Unknown type; conservatively treat all regions as possible.
+    llvm::append_range(successors, getRegions());
+    return;
+  }
+
   // Otherwise, try to find a case with a matching value. If not, the
   // default region is the only successor.
   for (auto [caseValue, caseRegion] : llvm::zip(getCases(), getCaseRegions())) {
-    if (caseValue == arg.getInt()) {
+    if (caseValue == *argValue) {
       successors.emplace_back(&caseRegion);
       return;
     }
@@ -1583,8 +1603,15 @@ void SwitchOp::getRegionInvocationBounds(
     return;
   }
 
+  std::optional<int64_t> maybeIntValue = getIntAttrValue(operandValue);
+  if (!maybeIntValue) {
+    // Unknown type; conservatively treat all regions as possible.
+    bounds.append(getNumRegions(), InvocationBounds(/*lb=*/0, /*ub=*/1));
+    return;
+  }
+
   unsigned liveIndex = getNumRegions() - 1;
-  const auto *iteratorToInt = llvm::find(getCases(), operandValue.getInt());
+  const auto *iteratorToInt = llvm::find(getCases(), *maybeIntValue);
 
   liveIndex = iteratorToInt != getCases().end()
                   ? std::distance(getCases().begin(), iteratorToInt)
diff --git a/mlir/test/Transforms/sccp.mlir b/mlir/test/Transforms/sccp.mlir
index 138acbb42d1a9..f5a5183593d03 100644
--- a/mlir/test/Transforms/sccp.mlir
+++ b/mlir/test/Transforms/sccp.mlir
@@ -286,3 +286,24 @@ func.func @no_crash_acc_kernel_environment(%data: memref<8xi32>) {
   }
   return
 }
+
+// -----
+
+// Regression test for https://github.com/llvm/llvm-project/issues/187973
+// SwitchOp::getEntrySuccessorRegions must not call IntegerAttr::getInt() on
+// an unsigned integer type — that function asserts signless/index only.
+
+// CHECK-LABEL: no_crash_emitc_switch_unsigned_condition
+func.func @no_crash_emitc_switch_unsigned_condition() {
+  // CHECK: emitc.constant
+  %0 = "emitc.constant"() {value = 1 : ui32} : () -> ui32
+  // CHECK: emitc.switch
+  emitc.switch %0 : ui32
+  case 2 {
+    emitc.yield
+  }
+  default {
+    emitc.yield
+  }
+  return
+}



More information about the Mlir-commits mailing list