[Mlir-commits] [mlir] [MLIR][LLVM] Block address support (PR #134335)

Bruno Cardoso Lopes llvmlistbot at llvm.org
Fri Apr 4 12:37:20 PDT 2025


bcardosolopes wrote:

> What happens if MLIR merges two block (e.g. when running region simplify) with different tags? I guess this could still be exported but the LLVM IR before and after MLIR would be semantically different since two block addresses would be merged into one block address. Does LLVM proper also merge block addresses if two blocks can be merged?

Given the snippet:

```
llvm.func @fn(%cond : i1, %arg0 : i32, %arg1 : i32) -> i32 {
  llvm.cond_br %cond, ^bb1, ^bb2
^bb1:
  llvm.return %arg0 : i32
^bb2:
  llvm.return %arg1 : i32
}
````

Region simplify works nicely:

```
$ mlir-opt /tmp/x.mlir -pass-pipeline='builtin.module(llvm.func(canonicalize{region-simplify=aggressive}))'
module {
  llvm.func @fn(%arg0: i1, %arg1: i32, %arg2: i32) -> i32 {
    llvm.cond_br %arg0, ^bb1(%arg1 : i32), ^bb1(%arg2 : i32)
  ^bb1(%0: i32):  // 2 preds: ^bb0, ^bb0
    llvm.return %0 : i32
  }
}
```

If I introduce the blocktags, the opt is blocked:

```
$ mlir-opt /tmp/x.mlir  -pass-pipeline='builtin.module(llvm.func(canonicalize{region-simplify=aggressive}))'
module {
  llvm.mlir.global private @g() {addr_space = 0 : i32, dso_local} : !llvm.ptr {
    %0 = llvm.blockaddress <function = @fn, tag = <id = 0>> : !llvm.ptr
    llvm.return %0 : !llvm.ptr
  }
  llvm.mlir.global private @h() {addr_space = 0 : i32, dso_local} : !llvm.ptr {
    %0 = llvm.blockaddress <function = @fn, tag = <id = 1>> : !llvm.ptr
    llvm.return %0 : !llvm.ptr
  }
  llvm.func @fn(%arg0: i1, %arg1: i32, %arg2: i32) -> i32 {
    llvm.cond_br %arg0, ^bb1, ^bb2
  ^bb1:  // pred: ^bb0
    llvm.blocktag <id = 0>
    llvm.return %arg1 : i32
  ^bb2:  // pred: ^bb0
    llvm.blocktag <id = 1>
    llvm.return %arg2 : i32
  }
}
```

Seems like the optimization is already conservative enough? LLVM proper is slightly more smart but it also "blocks" the full optimization in face of blockaddresses: https://godbolt.org/z/TP4K35zo8 (comment the globals to double check)

I would like to also write a test for even more simple block merging (something like https://godbolt.org/z/c5o78o6Y9), but canonicalize can't seem to do the job, how do call `mlir-opt` to transform this:
```
llvm.func @fn() {
  llvm.br ^bb1
^bb1:
  llvm.br ^bb2
^bb2:
  llvm.return
}
```
into
```
llvm.func @fn() {
  llvm.return
}
```
?

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


More information about the Mlir-commits mailing list