[flang-commits] [flang] [llvm] [mlir] [openmp] [Flang][OpenMP] Lower scan directive and inscan reduction modifier (PR #206747)

via flang-commits flang-commits at lists.llvm.org
Thu Jul 23 13:49:13 PDT 2026


================
@@ -670,6 +707,97 @@ findCurrentLoopInfo(LLVM::ModuleTranslation &moduleTranslation) {
   return loopInfo;
 }
 
+/// Find the scan loop information structure for the scan loop nest being
+/// translated. It will return a `null` value unless called from the
+/// translation function for a loop wrapper operation after successfully
+/// translating its body.
+static llvm::CanonicalLoopInfo *
+findCurrentScanLoopInfo(LLVM::ModuleTranslation &moduleTranslation) {
+  llvm::CanonicalLoopInfo *scanLoopInfo = nullptr;
+  moduleTranslation.stackWalk<OpenMPLoopInfoStackFrame>(
+      [&](OpenMPLoopInfoStackFrame &frame) {
+        scanLoopInfo = frame.scanloopInfo;
+        return WalkResult::interrupt();
+      });
+  return scanLoopInfo;
+}
+
+/// Find the `ScanInfo` stored on the loop stack frame. Upon encountering an
+/// `inscan` reduction modifier, `scanInfoInitialize` initializes the
+/// `ScanInfo`, which is then used when a `scan` directive is encountered in the
+/// body of the loop nest.
+static llvm::ScanInfo *
+findScanInfo(LLVM::ModuleTranslation &moduleTranslation) {
+  llvm::ScanInfo *scanInfo = nullptr;
+  moduleTranslation.stackWalk<OpenMPLoopInfoStackFrame>(
+      [&](OpenMPLoopInfoStackFrame &frame) {
+        scanInfo = frame.scanInfo;
+        return WalkResult::interrupt();
+      });
+  return scanInfo;
+}
+
+/// The types of reduction variables are used for lowering a `scan` directive
+/// that appears in the body of the loop. The types are stored in the loop frame
+/// when the reduction clause is encountered and used when the `scan` directive
+/// is encountered.
+static llvm::DenseMap<llvm::Value *, llvm::Type *> *
+findReductionVarTypes(LLVM::ModuleTranslation &moduleTranslation) {
+  llvm::DenseMap<llvm::Value *, llvm::Type *> *reductionVarToType = nullptr;
+  moduleTranslation.stackWalk<OpenMPLoopInfoStackFrame>(
+      [&](OpenMPLoopInfoStackFrame &frame) {
+        if (!frame.reductionVarToType)
+          frame.reductionVarToType =
+              std::make_unique<llvm::DenseMap<llvm::Value *, llvm::Type *>>();
+        reductionVarToType = frame.reductionVarToType.get();
+        return WalkResult::interrupt();
+      });
+  return reductionVarToType;
+}
+
+/// Scan reduction requires a shared buffer to be allocated to perform the
+/// reduction. The allocation needs to be done outside the parallel region in
+/// which the scan operation is used.
+static llvm::OpenMPIRBuilder::InsertPointTy
+findParallelAllocaIP(llvm::IRBuilderBase &builder,
----------------
chichunchen wrote:

Orphand worksharing loop seems not handled properly. findParallelAllocaIp() cannot find the enclosing omp.parallel and fallback to the entry block of run_scan.

```
  subroutine run_scan(result, x, n)
    implicit none
    integer :: n, result(n), x, i

    !$omp do reduction(inscan, +: x)
    do i = 1, n
      x = x + 1
      !$omp scan inclusive(x)
      result(i) = x
    end do
    !$omp end do
  end subroutine

  program example
    implicit none
    integer :: x, result(8)

    x = 0

    !$omp parallel shared(x, result)
    call run_scan(result, x, 8)
    !$omp end parallel
  end program
```

https://github.com/llvm/llvm-project/pull/206747


More information about the flang-commits mailing list