[all-commits] [llvm/llvm-project] 067916: [mlir][Transforms] Check successor operand types b...

William Moses via All-commits all-commits at lists.llvm.org
Sat Aug 8 21:04:28 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 067916bf4ddcfc328f343ae9aa0aa5983981ca1e
      https://github.com/llvm/llvm-project/commit/067916bf4ddcfc328f343ae9aa0aa5983981ca1e
  Author: William Moses <gh at wsmoses.com>
  Date:   2026-08-08 (Sat, 08 Aug 2026)

  Changed paths:
    M mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
    M mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
    M mlir/lib/Transforms/Utils/RegionUtils.cpp
    A mlir/test/Dialect/LLVMIR/block-merge-successor-operand-types.mlir

  Log Message:
  -----------
  [mlir][Transforms] Check successor operand types before merging identical blocks (#215036)

Merging identical blocks threads their differing values through the
predecessors' terminators as new successor operands, but the only
legality question asked of a predecessor was whether its terminator
implements `BranchOpInterface` (`ableToUpdatePredOperands`). The
transform's implicit assumption is that such a terminator can forward
operands of **any** type — false for dialects whose branch ops constrain
successor operand types. The LLVM dialect terminators declare theirs as
`Variadic<LLVM_Type>`, so merging two blocks that differ in, say, an
index-typed operand rewrote a verifying `llvm.cond_br` into one that no
longer verifies.

Reproducer (mixed-dialect IR of the kind a progressive lowering/raising
pipeline carries), via `mlir-opt
-pass-pipeline='builtin.module(func.func(canonicalize{region-simplify=aggressive}))'`:

```mlir
func.func @f(%m: memref<4xf32>, %c: i1) {
  %f = arith.constant 1.0 : f32
  %i0 = arith.constant 0 : index
  %i1 = arith.constant 1 : index
  llvm.cond_br %c, ^a, ^b
^a:
  memref.store %f, %m[%i0] : memref<4xf32>
  llvm.return
^b:
  memref.store %f, %m[%i1] : memref<4xf32>
  llvm.return
}
```

previously produced

```
error: 'llvm.cond_br' op operand #1 must be variadic of LLVM dialect-compatible type, but got 'index'
note: see current operation: "llvm.cond_br"(%arg1, %1, %2)[^bb1, ^bb1] ...
```

i.e. the transform manufactured IR that cannot verify. (Any greedy
driver running at `GreedySimplifyRegionLevel::Aggressive` — the
`applyPatternsGreedily` default — hits this; downstream we currently
work around it by dropping to `Normal`.)

This adds `mayForwardTypeToSuccessor(unsigned index, Type type)` to
`BranchOpInterface`, default permissive, and makes block merging refuse
a cluster when any predecessor terminator refuses any of the would-be
block argument types. The LLVM dialect terminators (`br`, `cond_br`,
`switch`, `invoke`, `indirectbr`) override it with `isCompatibleType`.
The new test pins both directions: the index-typed merge is refused, an
i32-typed merge through `llvm.cond_br` still happens.

Assisted-by: Claude



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list