[flang] [llvm] [mlir] [MLIR][OpenMP] Lowering nontemporal clause to LLVM IR for SIMD directive (PR #118751)
Kaviya Rajendiran via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 22 05:28:30 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);
+ }
+ }
----------------
kaviya2510 wrote:
```
omp.simd nontemporal(%3 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)private(@_QFsimd_nontemporal_allocatableEi_private_i32 %2 -> %arg2 : !fir.ref<i32>) {
omp.loop_nest (%arg3) : i32 = (%c1_i32) to (%c100_i32) inclusive step (%c1_i32) {
%16 = fir.declare %arg2 {uniq_name = "_QFsimd_nontemporal_allocatableEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
fir.store %arg3 to %16 : !fir.ref<i32>
%17 = fir.load %3 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
%18 = fir.load %16 : !fir.ref<i32>
%19 = fir.convert %18 : (i32) -> i64
%20 = fir.box_addr %17 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
%c0_0 = arith.constant 0 : index
%21:3 = fir.box_dims %17, %c0_0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
%22 = fir.shape_shift %21#0, %21#1 : (index, index) -> !fir.shapeshift<1>
%23 = fir.array_coor %20(%22) %19 : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>, i64) -> !fir.ref<i32>
%24 = fir.load %23 : !fir.ref<i32>
%25 = fir.load %4 : !fir.ref<i32>
%26 = arith.addi %24, %25 : i32
%27 = fir.load %3 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
%28 = fir.load %16 : !fir.ref<i32>
%29 = fir.convert %28 : (i32) -> i64
%30 = fir.box_addr %27 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
%c0_1 = arith.constant 0 : index
%31:3 = fir.box_dims %27, %c0_1 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
%32 = fir.shape_shift %31#0, %31#1 : (index, index) -> !fir.shapeshift<1>
%33 = fir.array_coor %30(%32) %29 : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>, i64) -> !fir.ref<i32>
fir.store %26 to %33 : !fir.ref<i32>
omp.yield
}
}
```
My goal is to trace back and identify the base operand for fir.load or fir.store operation.
Above mlir, which is an example of an allocatable array, both `fir.load %24 = fir.load %23 : !fir.ref<i32>` and `fir.store fir.store %26 to %33 : !fir.ref<i32>` operate on a single memory reference (the first operand), so I focused on recursively analyzing only the first operand of their defining operations to resolve the base.
https://github.com/llvm/llvm-project/pull/118751
More information about the llvm-commits
mailing list