[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