26
26
#include " mlir/Interfaces/DataLayoutInterfaces.h"
27
27
#include " mlir/Tools/mlir-translate/Translation.h"
28
28
29
+ #include " llvm/ADT/DepthFirstIterator.h"
29
30
#include " llvm/ADT/PostOrderIterator.h"
30
31
#include " llvm/ADT/ScopeExit.h"
31
32
#include " llvm/ADT/StringSet.h"
@@ -132,18 +133,17 @@ static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder,
132
133
return failure ();
133
134
}
134
135
135
- // / Get a topologically sorted list of blocks for the given function .
136
+ // / Get a topologically sorted list of blocks for the given basic blocks .
136
137
static SetVector<llvm::BasicBlock *>
137
- getTopologicallySortedBlocks (llvm::Function *func ) {
138
+ getTopologicallySortedBlocks (ArrayRef< llvm::BasicBlock *> basicBlocks ) {
138
139
SetVector<llvm::BasicBlock *> blocks;
139
- for (llvm::BasicBlock &bb : *func ) {
140
- if (!blocks.contains (&bb )) {
141
- llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal (&bb );
140
+ for (llvm::BasicBlock *basicBlock : basicBlocks ) {
141
+ if (!blocks.contains (basicBlock )) {
142
+ llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal (basicBlock );
142
143
blocks.insert (traversal.begin (), traversal.end ());
143
144
}
144
145
}
145
- assert (blocks.size () == func->size () && " some blocks are not sorted" );
146
-
146
+ assert (blocks.size () == basicBlocks.size () && " some blocks are not sorted" );
147
147
return blocks;
148
148
}
149
149
@@ -1859,11 +1859,26 @@ LogicalResult ModuleImport::processFunction(llvm::Function *func) {
1859
1859
if (func->isDeclaration ())
1860
1860
return success ();
1861
1861
1862
- // Eagerly create all blocks.
1863
- for (llvm::BasicBlock &bb : *func) {
1864
- Block *block =
1865
- builder.createBlock (&funcOp.getBody (), funcOp.getBody ().end ());
1866
- mapBlock (&bb, block);
1862
+ // Collect the set of basic blocks reachable from the function's entry block.
1863
+ // This step is crucial as LLVM IR can contain unreachable blocks that
1864
+ // self-dominate. As a result, an operation might utilize a variable it
1865
+ // defines, which the import does not support. Given that MLIR lacks block
1866
+ // label support, we can safely remove unreachable blocks, as there are no
1867
+ // indirect branch instructions that could potentially target these blocks.
1868
+ llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
1869
+ for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext (func, reachable))
1870
+ (void )basicBlock;
1871
+
1872
+ // Eagerly create all reachable blocks.
1873
+ SmallVector<llvm::BasicBlock *> reachableBasicBlocks;
1874
+ for (llvm::BasicBlock &basicBlock : *func) {
1875
+ // Skip unreachable blocks.
1876
+ if (!reachable.contains (&basicBlock))
1877
+ continue ;
1878
+ Region &body = funcOp.getBody ();
1879
+ Block *block = builder.createBlock (&body, body.end ());
1880
+ mapBlock (&basicBlock, block);
1881
+ reachableBasicBlocks.push_back (&basicBlock);
1867
1882
}
1868
1883
1869
1884
// Add function arguments to the entry block.
@@ -1876,10 +1891,11 @@ LogicalResult ModuleImport::processFunction(llvm::Function *func) {
1876
1891
// Process the blocks in topological order. The ordered traversal ensures
1877
1892
// operands defined in a dominating block have a valid mapping to an MLIR
1878
1893
// value once a block is translated.
1879
- SetVector<llvm::BasicBlock *> blocks = getTopologicallySortedBlocks (func);
1894
+ SetVector<llvm::BasicBlock *> blocks =
1895
+ getTopologicallySortedBlocks (reachableBasicBlocks);
1880
1896
setConstantInsertionPointToStart (lookupBlock (blocks.front ()));
1881
- for (llvm::BasicBlock *bb : blocks)
1882
- if (failed (processBasicBlock (bb , lookupBlock (bb ))))
1897
+ for (llvm::BasicBlock *basicBlock : blocks)
1898
+ if (failed (processBasicBlock (basicBlock , lookupBlock (basicBlock ))))
1883
1899
return failure ();
1884
1900
1885
1901
// Process the debug intrinsics that require a delayed conversion after
0 commit comments