[Mlir-commits] [mlir] [mlirbc] Fix use-list ordering during deserialization (PR #191942)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Apr 13 21:51:10 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
@llvm/pr-subscribers-mlir-core
Author: Jacques Pienaar (jpienaar)
<details>
<summary>Changes</summary>
This CL fixes an issue in the MLIR bytecode reader where use-lists were correctly reconstructed when they had permutations that are not own inverse. Fixed the use-list reconstruction mapping logic in to correctly restore the stable memory order of uses, both full shuffle and index-pair encodings consistently.
Gemini/LLM assisted.
---
Full diff: https://github.com/llvm/llvm-project/pull/191942.diff
2 Files Affected:
- (modified) mlir/lib/Bytecode/Reader/BytecodeReader.cpp (+27-4)
- (modified) mlir/test/Bytecode/uselist_orders.mlir (+20)
``````````diff
diff --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
index caa17ea57b950..00c53dae83ea8 100644
--- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
+++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
@@ -2309,6 +2309,7 @@ LogicalResult BytecodeReader::Impl::sortUseListOrder(Value value) {
// If the encoding was a pair of indices `(src, dst)` for every permutation,
// reconstruct the shuffle vector for every use. Initialize the shuffle vector
// as identity, and then apply the mapping encoded in the indices.
+ // This produces shuffle[oldIdx] = newPos (i.e., old_index -> new_position).
if (customOrder.isIndexPairEncoding) {
// Return failure if the number of indices was not representing pairs.
if (shuffle.size() & 1)
@@ -2337,10 +2338,32 @@ LogicalResult BytecodeReader::Impl::sortUseListOrder(Value value) {
accumulator != (((numUses - 1) * numUses) >> 1))
return failure();
- // Apply the current ordering map onto the shuffle vector to get the final
- // use-list sorting indices before shuffling.
- shuffle = SmallVector<unsigned, 4>(llvm::map_range(
- currentOrder, [&](auto item) { return shuffle[item.first]; }));
+ // Compose the shuffle with the current memory layout to produce the final
+ // indices for shuffleUseList. shuffleUseList(indices) places the use at
+ // current position i into position indices[i], so we need to compute
+ // finalShuffle[readerMemIdx] = writerMemIdx.
+ //
+ // The two encoding paths have different shuffle conventions:
+ //
+ // Index-pair encoding (already normalized above):
+ // shuffle[writerMemIdx] = sortedPos (old_index -> new_position)
+ //
+ // Full-shuffle encoding (writer's native format):
+ // shuffle[sortedPos] = writerMemIdx (new_position -> old_index)
+ //
+ // In both cases, currentOrder[sortedPos].first gives the readerMemIdx for
+ // a given sorted position. We fold the permutation inversion for the
+ // full-shuffle case directly into the composition to avoid an extra pass.
+ SmallVector<unsigned, 4> finalShuffle(numUses);
+ if (customOrder.isIndexPairEncoding) {
+ for (size_t writerMemIdx = 0; writerMemIdx < numUses; ++writerMemIdx)
+ finalShuffle[currentOrder[shuffle[writerMemIdx]].first] = writerMemIdx;
+ } else {
+ for (size_t sortedPos = 0; sortedPos < numUses; ++sortedPos)
+ finalShuffle[currentOrder[sortedPos].first] = shuffle[sortedPos];
+ }
+ shuffle = std::move(finalShuffle);
+
value.shuffleUseList(shuffle);
return success();
}
diff --git a/mlir/test/Bytecode/uselist_orders.mlir b/mlir/test/Bytecode/uselist_orders.mlir
index b8f4c3df6542c..73049d5d66173 100644
--- a/mlir/test/Bytecode/uselist_orders.mlir
+++ b/mlir/test/Bytecode/uselist_orders.mlir
@@ -1,4 +1,5 @@
// RUN: mlir-opt %s -split-input-file --test-verify-uselistorder -verify-diagnostics
+// RUN: mlir-opt %s -split-input-file --test-verify-uselistorder="rng-seed=54" -verify-diagnostics
// COM: --test-verify-uselistorder will randomly shuffle the uselist of every
// value and do a roundtrip to bytecode. An error is returned if the
@@ -61,3 +62,22 @@ test.graph_region {
%1 = "test.bar"(%2) : (i32) -> i32
%2 = "test.baz"() : () -> i32
}
+
+// -----
+
+// This is a reproducer test (for the fixed seed run) for use-def list
+// ordering.
+func.func @test_with_8_uses(%arg0 : i32) -> i32 {
+ %0 = arith.constant 45 : i32
+ %1 = "test.addi"(%arg0, %0) : (i32, i32) -> i32
+ %2 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ %3 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ %4 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ %5 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ %6 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ %7 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ %8 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ %9 = "test.addi"(%1, %0) : (i32, i32) -> i32
+ return %9 : i32
+}
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/191942
More information about the Mlir-commits
mailing list