[Mlir-commits] [mlir] 8dd8c4a - [mlir][Transforms] Inliner: Extra checks for unstructured control flow

Matthias Springer llvmlistbot at llvm.org
Wed Aug 30 06:37:12 PDT 2023


Author: Matthias Springer
Date: 2023-08-30T15:28:29+02:00
New Revision: 8dd8c4adba79cdaeeb096cafff6040da9c0a4797

URL: https://github.com/llvm/llvm-project/commit/8dd8c4adba79cdaeeb096cafff6040da9c0a4797
DIFF: https://github.com/llvm/llvm-project/commit/8dd8c4adba79cdaeeb096cafff6040da9c0a4797.diff

LOG: [mlir][Transforms] Inliner: Extra checks for unstructured control flow

Do not inline IR with multiple blocks into ops that may not support unstructured control flow.

This fixes #64978.

Differential Revision: https://reviews.llvm.org/D159072

Added: 
    

Modified: 
    mlir/lib/Transforms/Inliner.cpp
    mlir/test/Transforms/inlining.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Transforms/Inliner.cpp b/mlir/lib/Transforms/Inliner.cpp
index a7dcd2b0e87d23..e6eb483e234000 100644
--- a/mlir/lib/Transforms/Inliner.cpp
+++ b/mlir/lib/Transforms/Inliner.cpp
@@ -451,8 +451,24 @@ static bool shouldInline(ResolvedCall &resolvedCall) {
 
   // Don't allow inlining if the target is an ancestor of the call. This
   // prevents inlining recursively.
-  if (resolvedCall.targetNode->getCallableRegion()->isAncestor(
-          resolvedCall.call->getParentRegion()))
+  Region *callableRegion = resolvedCall.targetNode->getCallableRegion();
+  if (callableRegion->isAncestor(resolvedCall.call->getParentRegion()))
+    return false;
+
+  // Don't allow inlining if the callee has multiple blocks (unstructured
+  // control flow) but we cannot be sure that the caller region supports that.
+  bool calleeHasMultipleBlocks =
+      llvm::hasNItemsOrMore(*callableRegion, /*N=*/2);
+  // If both parent ops have the same type, it is safe to inline. Otherwise,
+  // decide based on whether the op has the SingleBlock trait or not.
+  // Note: This check does currently not account for SizedRegion/MaxSizedRegion.
+  auto callerRegionSupportsMultipleBlocks = [&]() {
+    return callableRegion->getParentOp()->getName() ==
+               resolvedCall.call->getParentOp()->getName() ||
+           !resolvedCall.call->getParentOp()
+                ->mightHaveTrait<OpTrait::SingleBlock>();
+  };
+  if (calleeHasMultipleBlocks && !callerRegionSupportsMultipleBlocks())
     return false;
 
   // Otherwise, inline.

diff  --git a/mlir/test/Transforms/inlining.mlir b/mlir/test/Transforms/inlining.mlir
index f7eaa478cdbba2..a0b4e0082b5439 100644
--- a/mlir/test/Transforms/inlining.mlir
+++ b/mlir/test/Transforms/inlining.mlir
@@ -227,6 +227,18 @@ func.func @func_with_block_args_location_callee2(%arg0 : i32) {
   return
 }
 
+// CHECK-LABEL: func @func_with_block_args_location_callee3
+func.func @func_with_block_args_location_callee3(%arg0 : i32) {
+  "test.dummy_op"() ({
+    // Call cannot be inlined because "test.dummy" may not support unstructured
+    // control flow in its body.
+    // CHECK: call @func_with_block_args_location
+    call @func_with_block_args_location(%arg0) : (i32) -> ()
+    "test.terminator"() : () -> ()
+  }) : () -> ()
+  return
+}
+
 // Check that we can handle argument and result attributes.
 test.conversion_func_op @handle_attr_callee_fn_multi_arg(%arg0 : i16, %arg1 : i16 {"test.handle_argument"}) -> (i16 {"test.handle_result"}, i16) {
   %0 = arith.addi %arg0, %arg1 : i16


        


More information about the Mlir-commits mailing list