[llvm-branch-commits] [flang] [mlir] [MLIR][OpenMP] Simplify OpenMP device codegen (PR #137201)
Kareem Ergawy via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jun 16 21:57:25 PDT 2025
================
@@ -5488,40 +5483,172 @@ convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
return success();
}
-// Returns true if the operation is inside a TargetOp or
-// is part of a declare target function.
-static bool isTargetDeviceOp(Operation *op) {
+namespace {
+
+/// Implementation of the dialect interface that converts operations belonging
+/// to the OpenMP dialect to LLVM IR.
+class OpenMPDialectLLVMIRTranslationInterface
+ : public LLVMTranslationDialectInterface {
+public:
+ using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
+
+ /// Translates the given operation to LLVM IR using the provided IR builder
+ /// and saving the state in `moduleTranslation`.
+ LogicalResult
+ convertOperation(Operation *op, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation) const final;
+
+ /// Given an OpenMP MLIR attribute, create the corresponding LLVM-IR,
+ /// runtime calls, or operation amendments
+ LogicalResult
+ amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
+ NamedAttribute attribute,
+ LLVM::ModuleTranslation &moduleTranslation) const final;
+};
+
+} // namespace
+
+LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
+ Operation *op, ArrayRef<llvm::Instruction *> instructions,
+ NamedAttribute attribute,
+ LLVM::ModuleTranslation &moduleTranslation) const {
+ return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
+ attribute.getName())
+ .Case("omp.is_target_device",
+ [&](Attribute attr) {
+ if (auto deviceAttr = dyn_cast<BoolAttr>(attr)) {
+ llvm::OpenMPIRBuilderConfig &config =
+ moduleTranslation.getOpenMPBuilder()->Config;
+ config.setIsTargetDevice(deviceAttr.getValue());
+ return success();
+ }
+ return failure();
+ })
+ .Case("omp.is_gpu",
+ [&](Attribute attr) {
+ if (auto gpuAttr = dyn_cast<BoolAttr>(attr)) {
+ llvm::OpenMPIRBuilderConfig &config =
+ moduleTranslation.getOpenMPBuilder()->Config;
+ config.setIsGPU(gpuAttr.getValue());
+ return success();
+ }
+ return failure();
+ })
+ .Case("omp.host_ir_filepath",
+ [&](Attribute attr) {
+ if (auto filepathAttr = dyn_cast<StringAttr>(attr)) {
+ llvm::OpenMPIRBuilder *ompBuilder =
+ moduleTranslation.getOpenMPBuilder();
+ ompBuilder->loadOffloadInfoMetadata(filepathAttr.getValue());
+ return success();
+ }
+ return failure();
+ })
+ .Case("omp.flags",
+ [&](Attribute attr) {
+ if (auto rtlAttr = dyn_cast<omp::FlagsAttr>(attr))
+ return convertFlagsAttr(op, rtlAttr, moduleTranslation);
+ return failure();
+ })
+ .Case("omp.version",
+ [&](Attribute attr) {
+ if (auto versionAttr = dyn_cast<omp::VersionAttr>(attr)) {
+ llvm::OpenMPIRBuilder *ompBuilder =
+ moduleTranslation.getOpenMPBuilder();
+ ompBuilder->M.addModuleFlag(llvm::Module::Max, "openmp",
+ versionAttr.getVersion());
+ return success();
+ }
+ return failure();
+ })
+ .Case("omp.declare_target",
+ [&](Attribute attr) {
+ if (auto declareTargetAttr =
+ dyn_cast<omp::DeclareTargetAttr>(attr))
+ return convertDeclareTargetAttr(op, declareTargetAttr,
+ moduleTranslation);
+ return failure();
+ })
+ .Case("omp.requires",
+ [&](Attribute attr) {
+ if (auto requiresAttr = dyn_cast<omp::ClauseRequiresAttr>(attr)) {
+ using Requires = omp::ClauseRequires;
+ Requires flags = requiresAttr.getValue();
+ llvm::OpenMPIRBuilderConfig &config =
+ moduleTranslation.getOpenMPBuilder()->Config;
+ config.setHasRequiresReverseOffload(
+ bitEnumContainsAll(flags, Requires::reverse_offload));
+ config.setHasRequiresUnifiedAddress(
+ bitEnumContainsAll(flags, Requires::unified_address));
+ config.setHasRequiresUnifiedSharedMemory(
+ bitEnumContainsAll(flags, Requires::unified_shared_memory));
+ config.setHasRequiresDynamicAllocators(
+ bitEnumContainsAll(flags, Requires::dynamic_allocators));
+ return success();
+ }
+ return failure();
+ })
+ .Case("omp.target_triples",
+ [&](Attribute attr) {
+ if (auto triplesAttr = dyn_cast<ArrayAttr>(attr)) {
+ llvm::OpenMPIRBuilderConfig &config =
+ moduleTranslation.getOpenMPBuilder()->Config;
+ config.TargetTriples.clear();
+ config.TargetTriples.reserve(triplesAttr.size());
+ for (Attribute tripleAttr : triplesAttr) {
+ if (auto tripleStrAttr = dyn_cast<StringAttr>(tripleAttr))
+ config.TargetTriples.emplace_back(tripleStrAttr.getValue());
+ else
+ return failure();
+ }
+ return success();
+ }
+ return failure();
+ })
+ .Default([](Attribute) {
+ // Fall through for omp attributes that do not require lowering.
+ return success();
+ })(attribute.getValue());
+
+ return failure();
+}
+
+// Returns true if the operation is not inside a TargetOp, it is part of a
+// function and that function is not declare target.
+static bool isHostDeviceOp(Operation *op) {
// Assumes no reverse offloading
if (op->getParentOfType<omp::TargetOp>())
- return true;
-
- // Certain operations return results, and whether utilised in host or
- // target there is a chance an LLVM Dialect operation depends on it
- // by taking it in as an operand, so we must always lower these in
- // some manner or result in an ICE (whether they end up in a no-op
- // or otherwise).
- if (mlir::isa<omp::ThreadprivateOp>(op))
- return true;
+ return false;
- if (auto parentFn = op->getParentOfType<LLVM::LLVMFuncOp>())
+ if (auto parentFn = op->getParentOfType<LLVM::LLVMFuncOp>()) {
if (auto declareTargetIface =
llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(
parentFn.getOperation()))
if (declareTargetIface.isDeclareTarget() &&
declareTargetIface.getDeclareTargetDeviceType() !=
mlir::omp::DeclareTargetDeviceType::host)
- return true;
+ return false;
+
+ return true;
+ }
return false;
----------------
ergawy wrote:
Shouldn't this be flipped to `true` now? At this path we are neither inside a `target` op nor inside a declare target function.
https://github.com/llvm/llvm-project/pull/137201
More information about the llvm-branch-commits
mailing list