[flang] [llvm] [mlir] [MLIR][OpenMP] Lowering nontemporal clause to LLVM IR for SIMD directive (PR #118751)
Tom Eccles via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 22 08:15:01 PDT 2025
================
@@ -0,0 +1,76 @@
+//===- LowerNontemporal.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Add nontemporal attributes to load and stores of variables marked as
+// nontemporal.
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
+#include "flang/Optimizer/OpenMP/Passes.h"
+#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
+
+using namespace mlir;
+
+namespace flangomp {
+#define GEN_PASS_DEF_LOWERNONTEMPORALPASS
+#include "flang/Optimizer/OpenMP/Passes.h.inc"
+} // namespace flangomp
+
+namespace {
+class LowerNontemporalPass
+ : public flangomp::impl::LowerNontemporalPassBase<LowerNontemporalPass> {
+ void addNonTemporalAttr(omp::SimdOp simdOp) {
+ if (simdOp.getNontemporalVars().empty())
+ return;
+
+ std::function<mlir::Value(mlir::Value)> getBaseOperand =
+ [&](mlir::Value operand) -> mlir::Value {
+ if (mlir::isa<mlir::BlockArgument>(operand) ||
+ (mlir::isa<fir::AllocaOp>(operand.getDefiningOp())) ||
+ (mlir::isa<fir::DeclareOp>(operand.getDefiningOp())))
+ return operand;
+
+ Operation *definingOp = operand.getDefiningOp();
+ if (definingOp) {
+ for (Value srcOp : definingOp->getOperands()) {
+ return getBaseOperand(srcOp);
+ }
+ }
----------------
tblah wrote:
Better to focus on specific operations in my opinion. I do not think there is any general meaning for how the first operand to the FIR operation relates to the operation result(s): it is just a coincidence that many of the current operations have the property you used. I am worried that in the future a new operation could be added which did not treat its first operand in the same way and that could lead to some difficult to detect bugs.
Off the top of my head, it isn't important whether your pass happens immediately before or after CodeGenRewrite (which turns fir.array_coor into fircg.ext_array_coor (etc)). What I wanted to achieve is for this to happen quite late in the pipeline so that anything that adds new data loads/stores (e.g. simplify intrinsics pass) has already run.
I don't mind if you want to handle both `fircg` and `fir` operations or only `fircg` variants. Doing something like the following would make it very low overhead to support more operation types:
```c++
llvm::TypeSwitch<Operation *>(defOp)
.Case<fir::ArrayCoorOp, fircg::ArrayCoorOp, fir::ConvertOp, [...]>([&](auto op) {
// use first operand
});
```
https://github.com/llvm/llvm-project/pull/118751
More information about the llvm-commits
mailing list