[flang-commits] [flang] [mlir] [OpenMP][MLIR] OMPEarlyOutliningPass removal (PR #67319)

Akash Banerjee via flang-commits flang-commits at lists.llvm.org
Mon Nov 6 05:20:01 PST 2023


https://github.com/TIFitis updated https://github.com/llvm/llvm-project/pull/67319

>From 77a35382d087a23727d3c8a546ccbd73f28de2ed Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Mon, 25 Sep 2023 12:31:30 +0100
Subject: [PATCH] [OpenMP][MLIR]OMPEarlyOutliningPass removal

This patch removes the OMPEarlyOutliningPass as it is no longer required. The implicit map operand capture has now been moved to the PFT lowering stage.

Depends on #67318.
---
 .../flang/Optimizer/Transforms/Passes.h       |   2 -
 .../flang/Optimizer/Transforms/Passes.td      |  12 -
 flang/include/flang/Tools/CLOptions.inc       |   4 +-
 flang/lib/Optimizer/Transforms/CMakeLists.txt |   1 -
 .../Transforms/OMPEarlyOutlining.cpp          | 303 ------------------
 .../OpenMP/FIR/omp-target-early-outlining.f90 |  89 -----
 .../Lower/OpenMP/function-filtering-2.f90     |   2 -
 .../test/Lower/OpenMP/function-filtering.f90  |   5 -
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      |   2 +
 9 files changed, 3 insertions(+), 417 deletions(-)
 delete mode 100644 flang/lib/Optimizer/Transforms/OMPEarlyOutlining.cpp
 delete mode 100644 flang/test/Lower/OpenMP/FIR/omp-target-early-outlining.f90

diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h
index 30d97be3800c191..92bc7246eca7005 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.h
+++ b/flang/include/flang/Optimizer/Transforms/Passes.h
@@ -75,8 +75,6 @@ std::unique_ptr<mlir::Pass>
 createAlgebraicSimplificationPass(const mlir::GreedyRewriteConfig &config);
 std::unique_ptr<mlir::Pass> createPolymorphicOpConversionPass();
 
-std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
-createOMPEarlyOutliningPass();
 std::unique_ptr<mlir::Pass> createOMPFunctionFilteringPass();
 std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
 createOMPMarkDeclareTargetPass();
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index 6d211a535b53f70..6e23b87b7e276e9 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -318,18 +318,6 @@ def LoopVersioning : Pass<"loop-versioning", "mlir::func::FuncOp"> {
   let dependentDialects = [ "fir::FIROpsDialect" ];
 }
 
-def OMPEarlyOutliningPass
-    : Pass<"omp-early-target-outlining", "mlir::ModuleOp"> {
-  let summary = "Outlines all target ops into separate functions";
-  let description = [{
-    This pass outlines all omp.target operations into individual functions.
-    It is invoked in the front end after the initial FIR has been constructed.
-    This pass is only needed when compiling for the target device to prevent
-    the optimizer to perform transforms across target region boundaries.
-  }];
-  let constructor = "::fir::createOMPEarlyOutliningPass()";
-}
-
 def OMPMarkDeclareTargetPass
     : Pass<"omp-mark-declare-target", "mlir::ModuleOp"> {
   let summary = "Marks all functions called by an OpenMP declare target function as declare target";
diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc
index 2ed716382feb43f..c452c023b4a80ce 100644
--- a/flang/include/flang/Tools/CLOptions.inc
+++ b/flang/include/flang/Tools/CLOptions.inc
@@ -274,10 +274,8 @@ inline void createHLFIRToFIRPassPipeline(
 inline void createOpenMPFIRPassPipeline(
     mlir::PassManager &pm, bool isTargetDevice) {
   pm.addPass(fir::createOMPMarkDeclareTargetPass());
-  if (isTargetDevice) {
-    pm.addPass(fir::createOMPEarlyOutliningPass());
+  if (isTargetDevice)
     pm.addPass(fir::createOMPFunctionFilteringPass());
-  }
 }
 
 #if !defined(FLANG_EXCLUDE_CODEGEN)
diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt
index 98314fa7a2087fe..03b67104a93b575 100644
--- a/flang/lib/Optimizer/Transforms/CMakeLists.txt
+++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt
@@ -17,7 +17,6 @@ add_flang_library(FIRTransforms
   AddDebugFoundation.cpp
   PolymorphicOpConversion.cpp
   LoopVersioning.cpp
-  OMPEarlyOutlining.cpp
   OMPFunctionFiltering.cpp
   OMPMarkDeclareTarget.cpp
   VScaleAttr.cpp
diff --git a/flang/lib/Optimizer/Transforms/OMPEarlyOutlining.cpp b/flang/lib/Optimizer/Transforms/OMPEarlyOutlining.cpp
deleted file mode 100644
index 92fbdd0bbf5d4a1..000000000000000
--- a/flang/lib/Optimizer/Transforms/OMPEarlyOutlining.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-#include "flang/Optimizer/Dialect/FIRDialect.h"
-#include "flang/Optimizer/Dialect/FIROps.h"
-#include "flang/Optimizer/Dialect/FIRType.h"
-#include "flang/Optimizer/HLFIR/HLFIROps.h"
-#include "flang/Optimizer/Support/InternalNames.h"
-#include "flang/Optimizer/Transforms/Passes.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
-#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
-#include "mlir/IR/BuiltinDialect.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/IR/IRMapping.h"
-#include "mlir/IR/Operation.h"
-#include "mlir/IR/SymbolTable.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Support/LLVM.h"
-#include "mlir/Transforms/RegionUtils.h"
-#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
-
-namespace fir {
-#define GEN_PASS_DEF_OMPEARLYOUTLININGPASS
-#include "flang/Optimizer/Transforms/Passes.h.inc"
-} // namespace fir
-
-namespace {
-class OMPEarlyOutliningPass
-    : public fir::impl::OMPEarlyOutliningPassBase<OMPEarlyOutliningPass> {
-
-  std::string getOutlinedFnName(llvm::StringRef parentName, unsigned count) {
-    return std::string(parentName) + "_omp_outline_" + std::to_string(count);
-  }
-
-  // Given a value this function will iterate over an operators results
-  // and return the relevant index for the result the value corresponds to.
-  // There may be a simpler way to do this however.
-  static unsigned getResultIndex(mlir::Value value, mlir::Operation *op) {
-    for (unsigned i = 0; i < op->getNumResults(); ++i) {
-      if (op->getResult(i) == value)
-        return i;
-    }
-    return 0;
-  }
-
-  static bool isAddressOfGlobalDeclareTarget(mlir::Value value) {
-    if (fir::AddrOfOp addressOfOp =
-            mlir::dyn_cast_if_present<fir::AddrOfOp>(value.getDefiningOp()))
-      if (fir::GlobalOp gOp = mlir::dyn_cast_if_present<fir::GlobalOp>(
-              addressOfOp->getParentOfType<mlir::ModuleOp>().lookupSymbol(
-                  addressOfOp.getSymbol())))
-        if (auto declareTargetGlobal =
-                llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
-                    gOp.getOperation()))
-          if (declareTargetGlobal.isDeclareTarget())
-            return true;
-    return false;
-  }
-
-  // Currently used for cloning arguments that are nested. Should be
-  // extendable where required, perhaps via operation
-  // specialisation/overloading, if something needs specialised handling.
-  // NOTE: Results in duplication of some values that would otherwise be
-  // a single SSA value shared between operations, this is tidied up on
-  // lowering to some extent.
-  static mlir::Operation *
-  cloneArgAndChildren(mlir::OpBuilder &builder, mlir::Operation *op,
-                      llvm::SetVector<mlir::Value> &inputs,
-                      mlir::Block::BlockArgListType &newInputs) {
-    mlir::IRMapping valueMap;
-    for (mlir::Value opValue : op->getOperands()) {
-      if (opValue.getDefiningOp()) {
-        unsigned resIdx = getResultIndex(opValue, opValue.getDefiningOp());
-        valueMap.map(opValue,
-                     cloneArgAndChildren(builder, opValue.getDefiningOp(),
-                                         inputs, newInputs)
-                         ->getResult(resIdx));
-      } else {
-        for (auto inArg : llvm::zip(inputs, newInputs)) {
-          if (opValue == std::get<0>(inArg))
-            valueMap.map(opValue, std::get<1>(inArg));
-        }
-      }
-    }
-
-    return builder.clone(*op, valueMap);
-  }
-
-  static void cloneMapOpVariables(mlir::OpBuilder &builder,
-                                  mlir::IRMapping &valueMap,
-                                  mlir::IRMapping &mapInfoMap,
-                                  llvm::SetVector<mlir::Value> &inputs,
-                                  mlir::Block::BlockArgListType &newInputs,
-                                  mlir::Value varPtr) {
-    if (fir::BoxAddrOp boxAddrOp =
-            mlir::dyn_cast_if_present<fir::BoxAddrOp>(varPtr.getDefiningOp())) {
-      mlir::Value newV =
-          cloneArgAndChildren(builder, boxAddrOp, inputs, newInputs)
-              ->getResult(0);
-      mapInfoMap.map(varPtr, newV);
-      valueMap.map(boxAddrOp, newV);
-      return;
-    }
-
-    // Clone into the outlined function all hlfir.declare ops that define inputs
-    // to the target region and set up remapping of its inputs and outputs.
-    if (auto declareOp = mlir::dyn_cast_if_present<hlfir::DeclareOp>(
-            varPtr.getDefiningOp())) {
-      auto clone = llvm::cast<hlfir::DeclareOp>(
-          cloneArgAndChildren(builder, declareOp, inputs, newInputs));
-      mlir::Value newBase = clone.getBase();
-      mlir::Value newOrigBase = clone.getOriginalBase();
-      mapInfoMap.map(varPtr, newOrigBase);
-      valueMap.map(declareOp.getBase(), newBase);
-      valueMap.map(declareOp.getOriginalBase(), newOrigBase);
-      return;
-    }
-
-    if (isAddressOfGlobalDeclareTarget(varPtr)) {
-      fir::AddrOfOp addrOp =
-          mlir::dyn_cast<fir::AddrOfOp>(varPtr.getDefiningOp());
-      mlir::Value newV = builder.clone(*addrOp)->getResult(0);
-      mapInfoMap.map(varPtr, newV);
-      valueMap.map(addrOp, newV);
-      return;
-    }
-
-    for (auto inArg : llvm::zip(inputs, newInputs)) {
-      if (varPtr == std::get<0>(inArg))
-        mapInfoMap.map(varPtr, std::get<1>(inArg));
-    }
-  }
-
-  mlir::func::FuncOp outlineTargetOp(mlir::OpBuilder &builder,
-                                     mlir::omp::TargetOp &targetOp,
-                                     mlir::func::FuncOp &parentFunc,
-                                     unsigned count) {
-    // NOTE: once implicit captures are handled appropriately in the initial
-    // PFT lowering if it is possible, we can remove the usage of
-    // getUsedValuesDefinedAbove and instead just iterate over the target op's
-    // operands (or just the map arguments) and perhaps refactor this function
-    // a little.
-    // Collect inputs
-    llvm::SetVector<mlir::Value> inputs;
-    mlir::Region &targetRegion = targetOp.getRegion();
-    mlir::getUsedValuesDefinedAbove(targetRegion, inputs);
-
-    // Collect all map info. Even non-used maps must be collected to avoid ICEs.
-    for (mlir::Value oper : targetOp->getOperands()) {
-      if (auto mapEntry =
-              mlir::dyn_cast<mlir::omp::MapInfoOp>(oper.getDefiningOp())) {
-        if (!inputs.contains(mapEntry.getVarPtr()))
-          inputs.insert(mapEntry.getVarPtr());
-      }
-    }
-
-    // Filter out declare-target and map entries which are specially handled
-    // at the moment, so we do not wish these to end up as function arguments
-    // which would just be more noise in the IR.
-    llvm::SmallVector<mlir::Value> blockArgs;
-    for (llvm::SetVector<mlir::Value>::iterator iter = inputs.begin(); iter != inputs.end();) {
-      if (mlir::isa_and_nonnull<mlir::omp::MapInfoOp>(iter->getDefiningOp()) ||
-          isAddressOfGlobalDeclareTarget(*iter)) {
-        iter = inputs.erase(iter);
-      } else if (auto declareOp = mlir::dyn_cast_if_present<hlfir::DeclareOp>(
-                     iter->getDefiningOp())) {
-        // Gather hlfir.declare arguments to be added later, after the
-        // hlfir.declare operation itself has been removed as an input.
-        blockArgs.push_back(declareOp.getMemref());
-        if (mlir::Value shape = declareOp.getShape())
-          blockArgs.push_back(shape);
-        for (mlir::Value typeParam : declareOp.getTypeparams())
-          blockArgs.push_back(typeParam);
-        iter = inputs.erase(iter);
-      } else {
-        ++iter;
-      }
-    }
-
-    // Add function arguments to the list of inputs if they are used by an
-    // hlfir.declare operation.
-    for (mlir::Value arg : blockArgs) {
-      if (!arg.getDefiningOp() && !inputs.contains(arg))
-        inputs.insert(arg);
-    }
-
-    // Create new function and initialize
-    mlir::FunctionType funcType = builder.getFunctionType(
-        mlir::TypeRange(inputs.getArrayRef()), mlir::TypeRange());
-    std::string parentName(parentFunc.getName());
-    std::string funcName = getOutlinedFnName(parentName, count);
-    mlir::Location loc = targetOp.getLoc();
-    mlir::func::FuncOp newFunc =
-        mlir::func::FuncOp::create(loc, funcName, funcType);
-    mlir::Block *entryBlock = newFunc.addEntryBlock();
-    builder.setInsertionPointToStart(entryBlock);
-    mlir::Block::BlockArgListType newInputs = entryBlock->getArguments();
-
-    // Set the declare target information, the outlined function
-    // is always a host function.
-    if (auto parentDTOp = llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
-            parentFunc.getOperation()))
-      if (auto newDTOp = llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
-              newFunc.getOperation()))
-        newDTOp.setDeclareTarget(mlir::omp::DeclareTargetDeviceType::host,
-                                 parentDTOp.getDeclareTargetCaptureClause());
-
-    // Set the early outlining interface parent name
-    if (auto earlyOutlineOp =
-            llvm::dyn_cast<mlir::omp::EarlyOutliningInterface>(
-                newFunc.getOperation()))
-      earlyOutlineOp.setParentName(parentName);
-
-    // The value map for the newly generated Target Operation, we must
-    // remap most of the input.
-    mlir::IRMapping valueMap;
-
-    // Special handling for map, declare target and regular map variables
-    // are handled slightly differently for the moment, declare target has
-    // its addressOfOp cloned over, whereas we skip it for the regular map
-    // variables. We need knowledge of which global is linked to the map
-    // operation for declare target, whereas we aren't bothered for the
-    // regular map variables for the moment. We could treat both the same,
-    // however, cloning across the minimum for the moment to avoid
-    // optimisations breaking segments of the lowering seems prudent as this
-    // was the original intent of the pass.
-    for (mlir::Value oper : targetOp->getOperands()) {
-      if (auto mapEntry =
-              mlir::dyn_cast<mlir::omp::MapInfoOp>(oper.getDefiningOp())) {
-        mlir::IRMapping mapInfoMap;
-        for (mlir::Value bound : mapEntry.getBounds()) {
-          if (auto mapEntryBound = mlir::dyn_cast<mlir::omp::DataBoundsOp>(
-                  bound.getDefiningOp())) {
-            mapInfoMap.map(bound, cloneArgAndChildren(builder, mapEntryBound,
-                                                      inputs, newInputs)
-                                      ->getResult(0));
-          }
-        }
-
-        cloneMapOpVariables(builder, valueMap, mapInfoMap, inputs, newInputs,
-                            mapEntry.getVarPtr());
-
-        if (mapEntry.getVarPtrPtr())
-          cloneMapOpVariables(builder, valueMap, mapInfoMap, inputs, newInputs,
-                              mapEntry.getVarPtrPtr());
-
-        valueMap.map(
-            mapEntry,
-            builder.clone(*mapEntry.getOperation(), mapInfoMap)->getResult(0));
-      }
-    }
-
-    for (auto inArg : llvm::zip(inputs, newInputs))
-      valueMap.map(std::get<0>(inArg), std::get<1>(inArg));
-
-    // Clone the target op into the new function
-    builder.clone(*(targetOp.getOperation()), valueMap);
-
-    // Create return op
-    builder.create<mlir::func::ReturnOp>(loc);
-
-    return newFunc;
-  }
-
-  // Returns true if a target region was found in the function.
-  bool outlineTargetOps(mlir::OpBuilder &builder,
-                        mlir::func::FuncOp &functionOp,
-                        mlir::ModuleOp &moduleOp,
-                        llvm::SmallVectorImpl<mlir::func::FuncOp> &newFuncs) {
-    unsigned count = 0;
-    for (auto TargetOp : functionOp.getOps<mlir::omp::TargetOp>()) {
-      mlir::func::FuncOp outlinedFunc =
-          outlineTargetOp(builder, TargetOp, functionOp, count);
-      newFuncs.push_back(outlinedFunc);
-      count++;
-    }
-    return count > 0;
-  }
-
-  void runOnOperation() override {
-    mlir::ModuleOp moduleOp = getOperation();
-    mlir::MLIRContext *context = &getContext();
-    mlir::OpBuilder builder(context);
-    llvm::SmallVector<mlir::func::FuncOp> newFuncs;
-
-    for (auto functionOp :
-         llvm::make_early_inc_range(moduleOp.getOps<mlir::func::FuncOp>())) {
-      bool outlined = outlineTargetOps(builder, functionOp, moduleOp, newFuncs);
-      if (outlined)
-        functionOp.erase();
-    }
-
-    for (auto newFunc : newFuncs)
-      moduleOp.push_back(newFunc);
-  }
-};
-
-} // namespace
-
-namespace fir {
-std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
-createOMPEarlyOutliningPass() {
-  return std::make_unique<OMPEarlyOutliningPass>();
-}
-} // namespace fir
diff --git a/flang/test/Lower/OpenMP/FIR/omp-target-early-outlining.f90 b/flang/test/Lower/OpenMP/FIR/omp-target-early-outlining.f90
deleted file mode 100644
index 14bf911b3e5410c..000000000000000
--- a/flang/test/Lower/OpenMP/FIR/omp-target-early-outlining.f90
+++ /dev/null
@@ -1,89 +0,0 @@
-!REQUIRES: amdgpu-registered-target
-
-!RUN: %flang_fc1 -triple amdgcn-amd-amdhsa -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
-!RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
-!RUN: bbc -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s 
-!RUN: bbc -emit-fir -fopenmp -fopenmp-is-gpu -fopenmp-is-target-device %s -o - | FileCheck %s 
-
-!CHECK: func.func @_QPtarget_function
-
-!CHECK:  func.func @_QPwrite_index_omp_outline_0(%[[ARG0:.*]]: !fir.ref<i32>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QPwrite_index"} {
-!CHECK-NEXT: %[[map_info0:.*]] = omp.map_info var_ptr(%[[ARG0]]{{.*}}
-!CHECK-NEXT: omp.target  map_entries(%[[map_info0]]{{.*}} {
-!CHECK: %[[CONSTANT_VALUE_10:.*]] = arith.constant 10 : i32
-!CHECK: fir.store %[[CONSTANT_VALUE_10]] to %[[ARG0]] : !fir.ref<i32>
-!CHECK: omp.terminator
-!CHECK-NEXT: }
-!CHECK-NEXT: return
-
-!CHECK:  func.func @_QPwrite_index_omp_outline_1(%[[ARG1:.*]]: !fir.ref<i32>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QPwrite_index"} {
-!CHECK-NEXT: %[[map_info1:.*]] = omp.map_info var_ptr(%[[ARG1]]{{.*}}
-!CHECK-NEXT: omp.target  map_entries(%[[map_info1]]{{.*}} {
-!CHECK: %[[CONSTANT_VALUE_20:.*]] = arith.constant 20 : i32
-!CHECK: fir.store %[[CONSTANT_VALUE_20]] to %[[ARG1]] : !fir.ref<i32>
-!CHECK: omp.terminator
-!CHECK-NEXT: }
-!CHECK-NEXT: return
-
-
-SUBROUTINE WRITE_INDEX(INT_ARRAY)
-        INTEGER :: INT_ARRAY(*)
-        INTEGER :: NEW_LEN
-!$omp target map(from:new_len)
-        NEW_LEN = 10
-!$omp end target
-!$omp target map(from:new_len)
-        NEW_LEN = 20
-!$omp end target
-        do INDEX_ = 1, NEW_LEN
-                INT_ARRAY(INDEX_) = INDEX_
-        end do
-end subroutine WRITE_INDEX
-
-SUBROUTINE TARGET_FUNCTION()
-!$omp declare target
-END
-
-!CHECK: func.func @_QParray_bounds_omp_outline_0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<!fir.array<10xi32>>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QParray_bounds"} {
-!CHECK: %[[C1:.*]] = arith.constant 1 : index
-!CHECK: %[[C4:.*]] = arith.constant 4 : index
-!CHECK: %[[C1_0:.*]] = arith.constant 1 : index
-!CHECK: %[[C1_1:.*]] = arith.constant 1 : index
-!CHECK: %[[BOUNDS:.*]] = omp.bounds   lower_bound(%[[C1]] : index) upper_bound(%[[C4]] : index) stride(%[[C1_1]] : index) start_idx(%[[C1_1]] : index)
-!CHECK: %[[ENTRY:.*]] = omp.map_info var_ptr(%[[ARG1]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>)   map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"}
-!CHECK: omp.target   map_entries(%[[ENTRY]] : !fir.ref<!fir.array<10xi32>>) {
-!CHECK:  %c2_i32 = arith.constant 2 : i32
-!CHECK:  %2 = fir.convert %c2_i32 : (i32) -> index
-!CHECK:  %c5_i32 = arith.constant 5 : i32
-!CHECK:  %3 = fir.convert %c5_i32 : (i32) -> index
-!CHECK:  %c1_2 = arith.constant 1 : index
-!CHECK:  %4 = fir.convert %2 : (index) -> i32
-!CHECK:  %5:2 = fir.do_loop %arg2 = %2 to %3 step %c1_2 iter_args(%arg3 = %4) -> (index, i32) {
-!CHECK:    fir.store %arg3 to %[[ARG0]] : !fir.ref<i32>
-!CHECK:    %6 = fir.load %[[ARG0]] : !fir.ref<i32>
-!CHECK:    %7 = fir.load %[[ARG0]] : !fir.ref<i32>
-!CHECK:    %8 = fir.convert %7 : (i32) -> i64
-!CHECK:    %c1_i64 = arith.constant 1 : i64
-!CHECK:    %9 = arith.subi %8, %c1_i64 : i64
-!CHECK:    %10 = fir.coordinate_of %[[ARG1]], %9 : (!fir.ref<!fir.array<10xi32>>, i64) -> !fir.ref<i32>
-!CHECK:    fir.store %6 to %10 : !fir.ref<i32>
-!CHECK:    %11 = arith.addi %arg2, %c1_2 : index
-!CHECK:    %12 = fir.convert %c1_2 : (index) -> i32
-!CHECK:    %13 = fir.load %[[ARG0]] : !fir.ref<i32>
-!CHECK:    %14 = arith.addi %13, %12 : i32
-!CHECK:    fir.result %11, %14 : index, i32
-!CHECK:  }
-!CHECK: fir.store %5#1 to %[[ARG0]] : !fir.ref<i32>
-!CHECK:  omp.terminator
-!CHECK: }
-!CHECK:return
-!CHECK:}
-
-SUBROUTINE ARRAY_BOUNDS()
-        INTEGER :: sp_write(10) = (/0,0,0,0,0,0,0,0,0,0/)
-!$omp target map(tofrom:sp_write(2:5))
-        do i = 2, 5
-                sp_write(i) = i
-        end do
-!$omp end target
-end subroutine ARRAY_BOUNDS
diff --git a/flang/test/Lower/OpenMP/function-filtering-2.f90 b/flang/test/Lower/OpenMP/function-filtering-2.f90
index 8219be5ad1e40ca..17cd0d44c01b4bc 100644
--- a/flang/test/Lower/OpenMP/function-filtering-2.f90
+++ b/flang/test/Lower/OpenMP/function-filtering-2.f90
@@ -26,9 +26,7 @@ subroutine no_declaretarget()
 end subroutine no_declaretarget
 
 ! MLIR-HOST: func.func @{{.*}}main(
-! MLIR-HOST-NOT: func.func @{{.*}}main_omp_outline{{.*}}()
 ! MLIR-DEVICE-NOT: func.func @{{.*}}main(
-! MLIR-DEVICE: func.func @{{.*}}main_omp_outline{{.*}}() attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QQmain"}
 ! MLIR-ALL: return
 
 ! LLVM-HOST: define {{.*}} @{{.*}}main{{.*}}(
diff --git a/flang/test/Lower/OpenMP/function-filtering.f90 b/flang/test/Lower/OpenMP/function-filtering.f90
index 3de14aa4709fc4c..e550348e50692c5 100644
--- a/flang/test/Lower/OpenMP/function-filtering.f90
+++ b/flang/test/Lower/OpenMP/function-filtering.f90
@@ -34,14 +34,9 @@ end function host_fn
 
 ! MLIR-HOST: func.func @{{.*}}target_subr(
 ! MLIR-HOST: return
-! MLIR-HOST-NOT: func.func @{{.*}}target_subr_omp_outline_0(
-! MLIR-DEVICE-NOT: func.func @{{.*}}target_subr(
-! MLIR-DEVICE: func.func @{{.*}}target_subr_omp_outline_0(
 ! MLIR-DEVICE: return
 
-! LLVM-ALL-NOT: define {{.*}} @{{.*}}target_subr_omp_outline_0{{.*}}(
 ! LLVM-HOST: define {{.*}} @{{.*}}target_subr{{.*}}(
-! LLVM-DEVICE-NOT: {{.*}} @{{.*}}target_subr{{.*}}(
 ! LLVM-ALL: define {{.*}} @__omp_offloading_{{.*}}_{{.*}}_target_subr__{{.*}}(
 subroutine target_subr(x)
   integer, intent(out) :: x
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 1daf60b8659bb66..422bbded2cbfc13 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -2459,6 +2459,8 @@ convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
       if (declareType == omp::DeclareTargetDeviceType::host) {
         llvm::Function *llvmFunc =
             moduleTranslation.lookupFunction(funcOp.getName());
+        llvmFunc->replaceAllUsesWith(
+            llvm::UndefValue::get(llvmFunc->getType()));
         llvmFunc->dropAllReferences();
         llvmFunc->eraseFromParent();
       }



More information about the flang-commits mailing list