[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
Mon Aug 3 04:05:23 PDT 2026
================
@@ -5489,17 +5525,63 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::emitScanReduction(
ScanRedInfo->Span,
llvm::ConstantInt::get(ScanRedInfo->Span->getType(), 1));
Builder.SetInsertPoint(InputBB);
- Builder.CreateBr(LoopBB);
+ // Branch around the orig-val seed load and combine when the loop has zero
+ // logical iterations. When Span == 0 no scan-buffer entry is populated, so
+ // loading buffer[0] and feeding it to a (possibly input-sensitive
+ // user-defined) reduction combiner would be undefined behavior. In that
+ // case skip straight to the exit; the finals' zero-trip guard preserves
+ // orig-val as the result.
+ llvm::Value *HasElem = Builder.CreateICmpUGT(
+ ScanRedInfo->Span, llvm::ConstantInt::get(IndexTy, 0));
+ llvm::BasicBlock *SeedBB =
+ BasicBlock::Create(CurFn->getContext(), "omp.scan.seed", CurFn, ExitBB);
+ Builder.CreateCondBr(HasElem, SeedBB, ExitBB);
+ Builder.SetInsertPoint(SeedBB);
+ // 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. Span > 0 is guaranteed here, so buffer[1] is valid.
+ 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(
----------------
chandraghale wrote:
You're right — the combiner operands were reversed at both sites. ReductionGen's first operand is omp_out (the accumulator), so the earlier prefix element must go first; I've swapped them in the orig-val seed (OrigVal, Elem) and the prefix computation (RHS, LHS). Verified with your left reducer (now b=10 10 10, x=10) and added a noncommutative sub-combiner lit test so +'s commutativity can't mask this again
https://github.com/llvm/llvm-project/pull/206747
More information about the flang-commits
mailing list