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

CHANDRA GHALE via flang-commits flang-commits at lists.llvm.org
Wed Jul 29 02:56:26 PDT 2026


================
@@ -5489,17 +5525,56 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::emitScanReduction(
         ScanRedInfo->Span,
         llvm::ConstantInt::get(ScanRedInfo->Span->getType(), 1));
     Builder.SetInsertPoint(InputBB);
-    Builder.CreateBr(LoopBB);
+    // Combine the original variable's incoming value (orig-val) into the first
+    // buffer element before computing the prefix sum. Per the OpenMP scan
+    // semantics orig-val is a single prefix element that must be reflected in
+    // every inclusive/exclusive scan result and in the final reduction value.
+    // Folding it in here lets the log-scan prefix computation propagate it into
+    // every element (and into the finals' read of `buffer[Span]`), regardless
+    // of whether an iteration's input phase accumulates into or overwrites the
+    // reduction variable. `select(Span > 0, 1, 0)` keeps the access in bounds
+    // when Span == 0: buffer[0] is otherwise unused and the finals' zero-trip
+    // guard discards it.
+    llvm::Value *HasElem = Builder.CreateICmpUGT(
+        ScanRedInfo->Span, llvm::ConstantInt::get(IndexTy, 0));
+    llvm::Value *FirstIdx =
+        Builder.CreateSelect(HasElem, llvm::ConstantInt::get(IndexTy, 1),
+                             llvm::ConstantInt::get(IndexTy, 0));
+    for (ReductionInfo RedInfo : ReductionInfos) {
+      Value *ReductionVal = RedInfo.PrivateVariable;
+      Value *BuffPtr = (*(ScanRedInfo->ScanBuffPtrs))[ReductionVal];
+      Value *Buff = Builder.CreateLoad(Builder.getPtrTy(), BuffPtr);
+      Type *DestTy = RedInfo.ElementType;
+      Value *ElemPtr =
+          Builder.CreateInBoundsGEP(DestTy, Buff, FirstIdx, "arrayOffset");
+      Value *OrigVal = Builder.CreateLoad(DestTy, RedInfo.Variable);
+      Value *Elem = Builder.CreateLoad(DestTy, ElemPtr);
----------------
chandraghale wrote:

Fixed. The masked region now branches around the seed entirely when Span == 0 (via a new omp.scan.seed block entered only when Span > 0), so buffer[0] is never loaded or passed to the reduction combiner — eliminating the UB for input-sensitive user-defined combiners, while zero-trip loops still correctly preserve orig-val.

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


More information about the flang-commits mailing list