13 changes: 12 additions & 1 deletion flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "flang/Optimizer/Dialect/CUF/CUFOps.h"
#include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h"
#include "flang/Optimizer/Dialect/CUF/CUFDialect.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
Expand Down Expand Up @@ -227,7 +228,17 @@ mlir::LogicalResult cuf::KernelOp::verify() {
getLowerbound().size() != getStep().size())
return emitOpError(
"expect same number of values in lowerbound, upperbound and step");

auto reduceAttrs = getReduceAttrs();
std::size_t reduceAttrsSize = reduceAttrs ? reduceAttrs->size() : 0;
if (getReduceOperands().size() != reduceAttrsSize)
return emitOpError("expect same number of values in reduce operands and "
"reduce attributes");
if (reduceAttrs) {
for (const auto &attr : reduceAttrs.value()) {
if (!mlir::isa<fir::ReduceAttr>(attr))
return emitOpError("expect reduce attributes to be ReduceAttr");
}
}
return mlir::success();
}

Expand Down
75 changes: 57 additions & 18 deletions flang/lib/Parser/prescan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,28 @@ void Prescanner::Statement() {
}
} else {
SkipSpaces();
// Check for a leading identifier that might be a keyword macro
// that will expand to anything indicating a non-source line, like
// a comment marker or directive sentinel. If so, disable line
// continuation, so that NextToken() won't consume anything from
// following lines.
if (IsLegalIdentifierStart(*at_)) {
CHECK(NextToken(tokens));
CHECK(tokens.SizeInTokens() == 1);
CharBlock id{tokens.TokenAt(0)};
if (preprocessor_.IsNameDefined(id) &&
!preprocessor_.IsFunctionLikeDefinition(id)) {
if (auto replaced{preprocessor_.MacroReplacement(tokens, *this)}) {
auto newLineClass{ClassifyLine(*replaced, GetCurrentProvenance())};
disableSourceContinuation_ =
newLineClass.kind != LineClassification::Kind::Source;
if (newLineClass.kind ==
LineClassification::Kind::CompilerDirective) {
directiveSentinel_ = newLineClass.sentinel;
}
}
}
}
}
break;
}
Expand All @@ -197,17 +219,13 @@ void Prescanner::Statement() {
Provenance newlineProvenance{GetCurrentProvenance()};
if (std::optional<TokenSequence> preprocessed{
preprocessor_.MacroReplacement(tokens, *this)}) {
// Reprocess the preprocessed line. Append a newline temporarily.
preprocessed->PutNextTokenChar('\n', newlineProvenance);
preprocessed->CloseToken();
const char *ppd{preprocessed->ToCharBlock().begin()};
LineClassification ppl{ClassifyLine(ppd)};
preprocessed->pop_back(); // remove the newline
// Reprocess the preprocessed line.
LineClassification ppl{ClassifyLine(*preprocessed, newlineProvenance)};
switch (ppl.kind) {
case LineClassification::Kind::Comment:
break;
case LineClassification::Kind::IncludeLine:
FortranInclude(ppd + ppl.payloadOffset);
FortranInclude(preprocessed->TokenAt(0).begin() + ppl.payloadOffset);
break;
case LineClassification::Kind::ConditionalCompilationDirective:
case LineClassification::Kind::IncludeDirective:
Expand Down Expand Up @@ -270,7 +288,8 @@ void Prescanner::Statement() {

void Prescanner::CheckAndEmitLine(
TokenSequence &tokens, Provenance newlineProvenance) {
tokens.CheckBadFortranCharacters(messages_, *this);
tokens.CheckBadFortranCharacters(
messages_, *this, disableSourceContinuation_);
// Parenthesis nesting check does not apply while any #include is
// active, nor on the lines before and after a top-level #include.
// Applications play shenanigans with line continuation before and
Expand Down Expand Up @@ -1243,7 +1262,9 @@ bool Prescanner::IsImplicitContinuation() const {
}

bool Prescanner::Continuation(bool mightNeedFixedFormSpace) {
if (*at_ == '\n' || *at_ == '&') {
if (disableSourceContinuation_) {
return false;
} else if (*at_ == '\n' || *at_ == '&') {
if (inFixedForm_) {
return FixedFormContinuation(mightNeedFixedFormSpace);
} else {
Expand All @@ -1255,8 +1276,9 @@ bool Prescanner::Continuation(bool mightNeedFixedFormSpace) {
BeginSourceLine(nextLine_);
NextLine();
return true;
} else {
return false;
}
return false;
}

std::optional<Prescanner::LineClassification>
Expand Down Expand Up @@ -1418,6 +1440,17 @@ Prescanner::LineClassification Prescanner::ClassifyLine(
return {LineClassification::Kind::Source};
}

Prescanner::LineClassification Prescanner::ClassifyLine(
TokenSequence &tokens, Provenance newlineProvenance) const {
// Append a newline temporarily.
tokens.PutNextTokenChar('\n', newlineProvenance);
tokens.CloseToken();
const char *ppd{tokens.ToCharBlock().begin()};
LineClassification classification{ClassifyLine(ppd)};
tokens.pop_back(); // remove the newline
return classification;
}

void Prescanner::SourceFormChange(std::string &&dir) {
if (dir == "!dir$ free") {
inFixedForm_ = false;
Expand Down Expand Up @@ -1445,7 +1478,7 @@ bool Prescanner::CompilerDirectiveContinuation(
return true;
}
CHECK(origSentinel != nullptr);
directiveSentinel_ = origSentinel; // so IsDirective() is true
directiveSentinel_ = origSentinel; // so InCompilerDirective() is true
const char *nextContinuation{
followingLine.kind == LineClassification::Kind::CompilerDirective
? FreeFormContinuationLine(true)
Expand All @@ -1457,7 +1490,6 @@ bool Prescanner::CompilerDirectiveContinuation(
auto origNextLine{nextLine_};
BeginSourceLine(nextLine_);
NextLine();
TokenSequence followingTokens;
if (nextContinuation) {
// What follows is !DIR$ & xxx; skip over the & so that it
// doesn't cause a spurious continuation.
Expand All @@ -1467,6 +1499,7 @@ bool Prescanner::CompilerDirectiveContinuation(
// but might become a directive continuation afterwards.
SkipSpaces();
}
TokenSequence followingTokens;
while (NextToken(followingTokens)) {
}
if (auto followingPrepro{
Expand All @@ -1475,25 +1508,31 @@ bool Prescanner::CompilerDirectiveContinuation(
}
followingTokens.RemoveRedundantBlanks();
std::size_t startAt{0};
std::size_t keep{followingTokens.SizeInTokens()};
std::size_t following{followingTokens.SizeInTokens()};
bool ok{false};
if (nextContinuation) {
ok = true;
} else {
if (keep >= 3 && followingTokens.TokenAt(0) == "!" &&
followingTokens.TokenAt(2) == "&") {
startAt = 2;
if (startAt < following && followingTokens.TokenAt(0) == "!") {
CharBlock sentinel{followingTokens.TokenAt(1)};
if (!sentinel.empty() &&
std::memcmp(sentinel.begin(), origSentinel, sentinel.size()) == 0) {
startAt = 3;
keep -= 3;
ok = true;
while (
startAt < following && followingTokens.TokenAt(startAt).IsBlank()) {
++startAt;
}
if (startAt < following && followingTokens.TokenAt(startAt) == "&") {
++startAt;
}
}
}
}
if (ok) {
tokens.pop_back(); // delete original '&'
tokens.Put(followingTokens, startAt, keep);
tokens.Put(followingTokens, startAt, following - startAt);
tokens.RemoveRedundantBlanks();
} else {
nextLine_ = origNextLine;
}
Expand Down
5 changes: 5 additions & 0 deletions flang/lib/Parser/prescan.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class Prescanner {
LineClassification(Kind k, std::size_t po = 0, const char *s = nullptr)
: kind{k}, payloadOffset{po}, sentinel{s} {}
LineClassification(LineClassification &&) = default;
LineClassification &operator=(LineClassification &&) = default;
Kind kind;
std::size_t payloadOffset; // byte offset of content
const char *sentinel; // if it's a compiler directive
Expand All @@ -117,6 +118,7 @@ class Prescanner {
parenthesisNesting_ = 0;
continuationLines_ = 0;
isPossibleMacroCall_ = false;
disableSourceContinuation_ = false;
}

Provenance GetProvenance(const char *sourceChar) const {
Expand Down Expand Up @@ -192,6 +194,8 @@ class Prescanner {
std::optional<LineClassification> IsFreeFormCompilerDirectiveLine(
const char *) const;
LineClassification ClassifyLine(const char *) const;
LineClassification ClassifyLine(
TokenSequence &, Provenance newlineProvenance) const;
void SourceFormChange(std::string &&);
bool CompilerDirectiveContinuation(TokenSequence &, const char *sentinel);
bool SourceLineContinuation(TokenSequence &);
Expand All @@ -211,6 +215,7 @@ class Prescanner {
int continuationLines_{0};
bool isPossibleMacroCall_{false};
bool afterIncludeDirective_{false};
bool disableSourceContinuation_{false};

Provenance startProvenance_;
const char *start_{nullptr}; // beginning of current source file content
Expand Down
5 changes: 4 additions & 1 deletion flang/lib/Parser/token-sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,8 @@ ProvenanceRange TokenSequence::GetProvenanceRange() const {
}

const TokenSequence &TokenSequence::CheckBadFortranCharacters(
Messages &messages, const Prescanner &prescanner) const {
Messages &messages, const Prescanner &prescanner,
bool allowAmpersand) const {
std::size_t tokens{SizeInTokens()};
for (std::size_t j{0}; j < tokens; ++j) {
CharBlock token{TokenAt(j)};
Expand All @@ -362,6 +363,8 @@ const TokenSequence &TokenSequence::CheckBadFortranCharacters(
++j;
continue;
}
} else if (ch == '&' && allowAmpersand) {
continue;
}
if (ch < ' ' || ch >= '\x7f') {
messages.Say(GetTokenProvenanceRange(j),
Expand Down
37 changes: 37 additions & 0 deletions flang/test/Lower/CUDA/cuda-kernel-do-reduction.cuf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
! Test CUDA Fortran kernel do reduction
! RUN: bbc -emit-fir -fcuda -o - %s | FileCheck %s

module mod1
contains
subroutine host_sub()
integer, parameter :: asize = 4
integer, device :: adev(asize)
integer :: ahost(asize)
integer :: q
integer, device :: add_reduce_var
integer, device :: mul_reduce_var
! CHECK: %[[VAL_0:.*]] = fir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QMmod1Fhost_subEadd_reduce_var"} : (!fir.ref<i32>) -> !fir.ref<i32>
! CHECK: %[[VAL_1:.*]] = fir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QMmod1Fhost_subEmul_reduce_var"} : (!fir.ref<i32>) -> !fir.ref<i32>
do i = 1, asize
ahost(i) = i
enddo
adev = ahost
add_reduce_var = 0.0
mul_reduce_var = 1.0
! CHECK: {{.*}} reduce(%[[VAL_0:.*]], %[[VAL_1:.*]] : !fir.ref<i32>, !fir.ref<i32> : [#fir.reduce_attr<add>, #fir.reduce_attr<multiply>]) {{.*}}
!$cuf kernel do <<< *, * >>> reduce(+:add_reduce_var) reduce(*:mul_reduce_var)
do i = 1, asize
add_reduce_var = add_reduce_var + adev(i)
mul_reduce_var = mul_reduce_var * adev(i)
end do
q = rsum
ahost = adev
print *, q
end
end

program test
use mod1
implicit none
call host_sub()
end program test
114 changes: 114 additions & 0 deletions flang/test/Lower/OpenMP/distribute.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
! REQUIRES: openmp_runtime

! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s

! CHECK-LABEL: func @_QPdistribute_simple
subroutine distribute_simple()
! CHECK: omp.teams
!$omp teams

! CHECK: omp.distribute {
!$omp distribute

! CHECK-NEXT: omp.loop_nest
do i = 1, 10
call foo()
! CHECK: omp.yield
end do

!$omp end distribute

! CHECK: omp.terminator
!$omp end teams
end subroutine distribute_simple

!===============================================================================
! `dist_schedule` clause
!===============================================================================

! CHECK-LABEL: func @_QPdistribute_dist_schedule
! CHECK-SAME: %[[X_ARG:.*]]: !fir.ref<i32>
subroutine distribute_dist_schedule(x)
! CHECK: %[[X_REF:.*]]:2 = hlfir.declare %[[X_ARG]]
integer, intent(in) :: x

! CHECK: omp.teams
!$omp teams

! STATIC SCHEDULE, CONSTANT CHUNK SIZE

! CHECK: %[[CONST_CHUNK_SIZE:.*]] = arith.constant 5 : i32
! CHECK: omp.distribute
! CHECK-SAME: dist_schedule_static
! CHECK-SAME: chunk_size(%[[CONST_CHUNK_SIZE]] : i32)
!$omp distribute dist_schedule(static, 5)

! CHECK-NEXT: omp.loop_nest
do i = 1, 10
call foo()
! CHECK: omp.yield
end do

!$omp end distribute

! STATIC SCHEDULE, VARIABLE CHUNK SIZE

! CHECK: %[[X:.*]] = fir.load %[[X_REF]]#0
! CHECK: omp.distribute
! CHECK-SAME: dist_schedule_static
! CHECK-SAME: chunk_size(%[[X]] : i32)
!$omp distribute dist_schedule(static, x)

! CHECK-NEXT: omp.loop_nest
do i = 1, 10
call foo()
! CHECK: omp.yield
end do

!$omp end distribute

! STATIC SCHEDULE, NO CHUNK SIZE

! CHECK: omp.distribute
! CHECK-SAME: dist_schedule_static
! CHECK-NOT: chunk_size
!$omp distribute dist_schedule(static)

! CHECK-NEXT: omp.loop_nest
do i = 1, 10
call foo()
! CHECK: omp.yield
end do

!$omp end distribute

! CHECK: omp.terminator
!$omp end teams
end subroutine distribute_dist_schedule

!===============================================================================
! `allocate` clause
!===============================================================================

! CHECK-LABEL: func @_QPdistribute_allocate
subroutine distribute_allocate()
use omp_lib
integer :: x
! CHECK: omp.teams
!$omp teams

! CHECK: omp.distribute
! CHECK-SAME: allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>)
!$omp distribute allocate(omp_high_bw_mem_alloc: x) private(x)

! CHECK-NEXT: omp.loop_nest
do i = 1, 10
x = i
! CHECK: omp.yield
end do

!$omp end distribute

! CHECK: omp.terminator
!$omp end teams
end subroutine distribute_allocate
168 changes: 164 additions & 4 deletions flang/test/Lower/OpenMP/if-clause.f90
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@ program main
! - DISTRIBUTE SIMD
! - PARALLEL SECTIONS
! - PARALLEL WORKSHARE
! - TARGET PARALLEL
! - TARGET TEAMS DISTRIBUTE
! - TARGET TEAMS DISTRIBUTE PARALLEL DO
! - TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD
! - TARGET TEAMS DISTRIBUTE SIMD
! - TARGET UPDATE
! - TASKLOOP
! - TASKLOOP SIMD
! - TEAMS DISTRIBUTE
! - TEAMS DISTRIBUTE PARALLEL DO
! - TEAMS DISTRIBUTE PARALLEL DO SIMD
! - TEAMS DISTRIBUTE SIMD
Expand All @@ -39,12 +36,16 @@ program main
!$omp end do simd

! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp do simd if(.true.)
do i = 1, 10
end do
!$omp end do simd

! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp do simd if(simd: .true.)
do i = 1, 10
end do
Expand Down Expand Up @@ -114,6 +115,8 @@ program main
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp parallel do simd if(.true.)
do i = 1, 10
end do
Expand All @@ -122,6 +125,8 @@ program main
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp parallel do simd if(parallel: .true.) if(simd: .false.)
do i = 1, 10
end do
Expand All @@ -141,6 +146,8 @@ program main
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp parallel do simd if(simd: .true.)
do i = 1, 10
end do
Expand Down Expand Up @@ -315,6 +322,8 @@ program main
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target parallel do simd if(.true.)
do i = 1, 10
end do
Expand All @@ -325,6 +334,8 @@ program main
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target parallel do simd if(target: .true.) if(parallel: .false.) &
!$omp& if(simd: .true.)
do i = 1, 10
Expand All @@ -350,11 +361,60 @@ program main
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
! CHECK: omp.wsloop
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target parallel do simd if(parallel: .true.) if(simd: .false.)
do i = 1, 10
end do
!$omp end target parallel do simd

! ----------------------------------------------------------------------------
! TARGET PARALLEL
! ----------------------------------------------------------------------------
! CHECK: omp.target
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.parallel
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target parallel
i = 1
!$omp end target parallel

! CHECK: omp.target
! CHECK-SAME: if({{.*}})
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
!$omp target parallel if(.true.)
i = 1
!$omp end target parallel

! CHECK: omp.target
! CHECK-SAME: if({{.*}})
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
!$omp target parallel if(target: .true.) if(parallel: .false.)
i = 1
!$omp end target parallel

! CHECK: omp.target
! CHECK-SAME: if({{.*}})
! CHECK: omp.parallel
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target parallel if(target: .true.)
i = 1
!$omp end target parallel

! CHECK: omp.target
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.parallel
! CHECK-SAME: if({{.*}})
!$omp target parallel if(parallel: .true.)
i = 1
!$omp end target parallel

! ----------------------------------------------------------------------------
! TARGET SIMD
! ----------------------------------------------------------------------------
Expand Down Expand Up @@ -408,9 +468,75 @@ program main
!$omp end target simd

! ----------------------------------------------------------------------------
! TARGET TEAMS
! TARGET TEAMS DISTRIBUTE
! ----------------------------------------------------------------------------
! CHECK: omp.target
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.teams
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target teams distribute
do i = 1, 10
end do
!$omp end target teams distribute

! CHECK: omp.target
! CHECK-SAME: if({{.*}})
! CHECK: omp.teams
! CHECK-SAME: if({{.*}})
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target teams distribute if(.true.)
do i = 1, 10
end do
!$omp end target teams distribute

! CHECK: omp.target
! CHECK-SAME: if({{.*}})
! CHECK: omp.teams
! CHECK-SAME: if({{.*}})
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target teams distribute if(target: .true.) if(teams: .false.)
do i = 1, 10
end do
!$omp end target teams distribute

! CHECK: omp.target
! CHECK-SAME: if({{.*}})
! CHECK: omp.teams
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target teams distribute if(target: .true.)
do i = 1, 10
end do
!$omp end target teams distribute

! CHECK: omp.target
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.teams
! CHECK-SAME: if({{.*}})
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp target teams distribute if(teams: .true.)
do i = 1, 10
end do
!$omp end target teams distribute

! ----------------------------------------------------------------------------
! TARGET TEAMS
! ----------------------------------------------------------------------------
! CHECK: omp.target
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
Expand Down Expand Up @@ -474,6 +600,40 @@ program main
!$omp task if(task: .true.)
!$omp end task

! ----------------------------------------------------------------------------
! TEAMS DISTRIBUTE
! ----------------------------------------------------------------------------
! CHECK: omp.teams
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp teams distribute
do i = 1, 10
end do
!$omp end teams distribute

! CHECK: omp.teams
! CHECK-SAME: if({{.*}})
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp teams distribute if(.true.)
do i = 1, 10
end do
!$omp end teams distribute

! CHECK: omp.teams
! CHECK-SAME: if({{.*}})
! CHECK: omp.distribute
! CHECK-NOT: if({{.*}})
! CHECK-SAME: {
!$omp teams distribute if(teams: .true.)
do i = 1, 10
end do
!$omp end teams distribute

! ----------------------------------------------------------------------------
! TEAMS
! ----------------------------------------------------------------------------
Expand Down
27 changes: 24 additions & 3 deletions flang/test/Lower/OpenMP/loop-combined.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
program main
integer :: i

! TODO When DISTRIBUTE, TASKLOOP and TEAMS are supported add:
! TODO When composite constructs are supported add:
! - DISTRIBUTE PARALLEL DO SIMD
! - DISTRIBUTE PARALLEL DO
! - DISTRIBUTE SIMD
! - TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD
! - TARGET TEAMS DISTRIBUTE PARALLEL DO
! - TARGET TEAMS DISTRIBUTE SIMD
! - TARGET TEAMS DISTRIBUTE
! - TASKLOOP SIMD
! - TEAMS DISTRIBUTE PARALLEL DO SIMD
! - TEAMS DISTRIBUTE PARALLEL DO
! - TEAMS DISTRIBUTE SIMD
! - TEAMS DISTRIBUTE

! ----------------------------------------------------------------------------
! DO SIMD
Expand Down Expand Up @@ -80,4 +78,27 @@ program main
do i = 1, 10
end do
!$omp end target simd

! ----------------------------------------------------------------------------
! TARGET TEAMS DISTRIBUTE
! ----------------------------------------------------------------------------

! CHECK: omp.target
! CHECK: omp.teams
! CHECK: omp.distribute
!$omp target teams distribute
do i = 1, 10
end do
!$omp end target teams distribute

! ----------------------------------------------------------------------------
! TEAMS DISTRIBUTE
! ----------------------------------------------------------------------------

! CHECK: omp.teams
! CHECK: omp.distribute
!$omp teams distribute
do i = 1, 10
end do
!$omp end teams distribute
end program main
100 changes: 100 additions & 0 deletions flang/test/Lower/pre-fir-tree09.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
! RUN: bbc -pft-test -o %t %s | FileCheck %s

module mm
!dir$ some directive 1
type t
logical :: tag
contains
final :: fin
end type
!dir$ some directive 2

contains
!dir$ some directive 3
subroutine fin(x)
type(t), intent(inout) :: x
x%tag =.true.
!dir$ some directive 4
call s1
call s2
print*, 'fin', x

contains
!dir$ some directive 5
subroutine s1
print*, 's1'
!dir$ some directive 6
end subroutine s1

!dir$ some directive 7
subroutine s2
!dir$ some directive 8
if (.true.) then
!dir$ some directive 9
print*, 's2'
!dir$ some directive 10
endif
!dir$ some directive 11
end subroutine s2
!dir$ some directive 12
end subroutine fin
!dir$ some directive 13
end module mm
!dir$ some directive 14

end

! CHECK: Module mm: module mm
! CHECK: CompilerDirective: !some directive 1
! CHECK: CompilerDirective: !some directive 2

! CHECK: Contains
! CHECK: CompilerDirective: !some directive 3

! CHECK: Subroutine fin: subroutine fin(x)
! CHECK: AssignmentStmt: x%tag =.true.
! CHECK: CompilerDirective: !some directive 4
! CHECK: CallStmt: call s1
! CHECK: CallStmt: call s2
! CHECK: PrintStmt: print*, 'fin', x
! CHECK: EndSubroutineStmt: end subroutine fin

! CHECK: Contains
! CHECK: CompilerDirective: !some directive 5

! CHECK: Subroutine s1: subroutine s1
! CHECK: PrintStmt: print*, 's1'
! CHECK: CompilerDirective: !some directive 6
! CHECK: EndSubroutineStmt: end subroutine s1
! CHECK: End Subroutine s1

! CHECK: CompilerDirective: !some directive 7

! CHECK: Subroutine s2: subroutine s2
! CHECK: CompilerDirective: !some directive 8
! CHECK: <<IfConstruct>> -> 7
! CHECK: IfThenStmt -> 7: if(.true.) then
! CHECK: ^CompilerDirective: !some directive 9
! CHECK: PrintStmt: print*, 's2'
! CHECK: CompilerDirective: !some directive 10
! CHECK: EndIfStmt: endif
! CHECK: <<End IfConstruct>>
! CHECK: CompilerDirective: !some directive 11
! CHECK: EndSubroutineStmt: end subroutine s2
! CHECK: End Subroutine s2

! CHECK: CompilerDirective: !some directive 12

! CHECK: End Contains
! CHECK: End Subroutine fin

! CHECK: CompilerDirective: !some directive 13

! CHECK: End Contains
! CHECK: End Module mm

! CHECK: CompilerDirective: !some directive 14

! CHECK: Program <anonymous>
! CHECK: EndProgramStmt: end
! CHECK: End Program <anonymous>
63 changes: 49 additions & 14 deletions flang/test/Preprocessing/directive-contin-with-pp.F90
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
! RUN: %flang -E %s 2>&1 | FileCheck %s
! RUN: %flang -fc1 -fdebug-unparse -fopenmp %s 2>&1 | FileCheck %s

#define DIR_START !dir$
#define DIR_CONT !dir$&
#define FIRST(x) DIR_START x
#define NEXT(x) DIR_CONT x
#define AMPER &
#define COMMENT !
#define OMP_START !$omp
#define OMP_CONT !$omp&

subroutine s(x1, x2, x3, x4, x5, x6, x7)
module m
contains
subroutine s(x1, x2, x3, x4, x5, x6, x7)

!dir$ ignore_tkr x1

Expand All @@ -24,18 +29,48 @@ subroutine s(x1, x2, x3, x4, x5, x6, x7)
FIRST(ignore_tkr &)
NEXT(x6)

FIRST(ignore_tkr &)
NEXT(x7 &)
NEXT(x8)
COMMENT blah &
COMMENT & more
stop 1

OMP_START parallel &
OMP_START do &
OMP_START reduction(+:x)
do j1 = 1, n
end do

OMP_START parallel &
OMP_START & do &
OMP_START & reduction(+:x)
do j2 = 1, n
end do

OMP_START parallel &
OMP_CONT do &
OMP_CONT reduction(+:x)
do j3 = 1, n
end do
end
end

!CHECK: subroutine s(x1, x2, x3, x4, x5, x6, x7)
!CHECK: !dir$ ignore_tkr x1
!CHECK: !dir$ ignore_tkr x2
!CHECK: !dir$ ignore_tkr x3
!CHECK: !dir$ ignore_tkr x4
!CHECK: !dir$ ignore_tkr x5
!CHECK: !dir$ ignore_tkr x6
!CHECK: !dir$ ignore_tkr x7 x8
!CHECK: end
!CHECK: MODULE m
!CHECK: CONTAINS
!CHECK: SUBROUTINE s (x1, x2, x3, x4, x5, x6, x7)
!CHECK: !DIR$ IGNORE_TKR x1
!CHECK: !DIR$ IGNORE_TKR x2
!CHECK: !DIR$ IGNORE_TKR x3
!CHECK: !DIR$ IGNORE_TKR x4
!CHECK: !DIR$ IGNORE_TKR x5
!CHECK: !DIR$ IGNORE_TKR x6
!CHECK: STOP 1_4
!CHECK: !$OMP PARALLEL DO REDUCTION(+:x)
!CHECK: DO j1=1_4,n
!CHECK: END DO
!CHECK: !$OMP PARALLEL DO REDUCTION(+:x)
!CHECK: DO j2=1_4,n
!CHECK: END DO
!CHECK: !$OMP PARALLEL DO REDUCTION(+:x)
!CHECK: DO j3=1_4,n
!CHECK: END DO
!CHECK: END SUBROUTINE
!CHECK: END MODULE
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/limits-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@
#endif // INT_MAX

#ifndef UINT_MAX
#define UINT_MAX (~0U)
#define UINT_MAX (INT_MAX * 2U + 1U)
#endif // UINT_MAX

#ifndef LONG_MAX
Expand All @@ -160,7 +160,7 @@
#endif // LONG_MAX

#ifndef ULONG_MAX
#define ULONG_MAX (~0UL)
#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
#endif // ULONG_MAX

#ifndef LLONG_MAX
Expand All @@ -172,7 +172,7 @@
#endif // LLONG_MAX

#ifndef ULLONG_MAX
#define ULLONG_MAX (~0ULL)
#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
#endif // ULLONG_MAX

// *_MIN macros
Expand Down
22 changes: 11 additions & 11 deletions libc/src/__support/fixedvector.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,45 +25,45 @@ template <typename T, size_t CAPACITY> class FixedVector {
constexpr FixedVector() = default;

using iterator = typename cpp::array<T, CAPACITY>::iterator;
constexpr FixedVector(iterator begin, iterator end) {
constexpr FixedVector(iterator begin, iterator end) : store{}, item_count{} {
for (; begin != end; ++begin)
push_back(*begin);
}

constexpr FixedVector(size_t count, const T &value) {
constexpr FixedVector(size_t count, const T &value) : store{}, item_count{} {
for (size_t i = 0; i < count; ++i)
push_back(value);
}

bool push_back(const T &obj) {
constexpr bool push_back(const T &obj) {
if (item_count == CAPACITY)
return false;
store[item_count] = obj;
++item_count;
return true;
}

const T &back() const { return store[item_count - 1]; }
constexpr const T &back() const { return store[item_count - 1]; }

T &back() { return store[item_count - 1]; }
constexpr T &back() { return store[item_count - 1]; }

bool pop_back() {
constexpr bool pop_back() {
if (item_count == 0)
return false;
--item_count;
return true;
}

T &operator[](size_t idx) { return store[idx]; }
constexpr T &operator[](size_t idx) { return store[idx]; }

const T &operator[](size_t idx) const { return store[idx]; }
constexpr const T &operator[](size_t idx) const { return store[idx]; }

bool empty() const { return item_count == 0; }
constexpr bool empty() const { return item_count == 0; }

size_t size() const { return item_count; }
constexpr size_t size() const { return item_count; }

// Empties the store for all practical purposes.
void reset() { item_count = 0; }
constexpr void reset() { item_count = 0; }

// This static method does not free up the resources held by |store|,
// say by calling `free` or something similar. It just does the equivalent
Expand Down
12 changes: 12 additions & 0 deletions libc/src/__support/macros/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

#include "properties/architectures.h"

#ifndef __has_attribute
#define __has_attribute(x) 0
#endif

#define LIBC_INLINE inline
#define LIBC_INLINE_VAR inline
#define LIBC_INLINE_ASM __asm__ __volatile__
Expand All @@ -30,4 +34,12 @@
#define LIBC_THREAD_LOCAL thread_local
#endif

#if __cplusplus >= 202002L
#define LIBC_CONSTINIT constinit
#elif __has_attribute(__require_constant_initialization__)
#define LIBC_CONSTINIT __attribute__((__require_constant_initialization__))
#else
#define LIBC_CONSTINIT
#endif

#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
12 changes: 12 additions & 0 deletions libc/src/stdio/baremetal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,16 @@ add_entrypoint_object(
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
)

add_entrypoint_object(
putchar
SRCS
putchar.cpp
HDRS
../putchar.h
DEPENDS
libc.src.__support.OSUtil.osutil
libc.src.__support.CPP.string_view
)
10 changes: 2 additions & 8 deletions libc/src/stdio/baremetal/printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,20 @@
//===----------------------------------------------------------------------===//

#include "src/stdio/printf.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/arg_list.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/printf_main.h"
#include "src/stdio/printf_core/writer.h"

#include <stdarg.h>

// TODO(https://github.com/llvm/llvm-project/issues/94685) unify baremetal hooks

// This is intended to be provided by the vendor.
extern "C" size_t __llvm_libc_raw_write(const char *s, size_t size);

namespace LIBC_NAMESPACE {

namespace {

LIBC_INLINE int raw_write_hook(cpp::string_view new_str, void *) {
size_t written = __llvm_libc_raw_write(new_str.data(), new_str.size());
if (written != new_str.size())
return printf_core::FILE_WRITE_ERROR;
write_to_stderr(new_str);
return printf_core::WRITE_OK;
}

Expand Down
23 changes: 23 additions & 0 deletions libc/src/stdio/baremetal/putchar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- Baremetal Implementation of putchar -------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "src/stdio/putchar.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/OSUtil/io.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, putchar, (int c)) {
char uc = static_cast<char>(c);

write_to_stderr(cpp::string_view(&uc, 1));

return 0;
}

} // namespace LIBC_NAMESPACE
1 change: 1 addition & 0 deletions libcxx/benchmarks/algorithms/pstl.stable_sort.bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include <algorithm>
#include <execution>

#include "common.h"

Expand Down
2 changes: 2 additions & 0 deletions libcxx/cmake/caches/Generic-msan.cmake
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
set(LLVM_USE_SANITIZER "MemoryWithOrigins" CACHE STRING "")
set(LIBCXX_TEST_PARAMS "long_tests=False" CACHE STRING "") # MSAN is really slow and tests can sometimes timeout otherwise
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
set(LIBCXXABI_USE_LLVM_UNWINDER OFF CACHE BOOL "") # MSAN is compiled against the system unwinder, which leads to false positives
4 changes: 3 additions & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_syncbuf`` ``201803L``
---------------------------------------------------------- -----------------
``__cpp_lib_three_way_comparison`` *unimplemented*
``__cpp_lib_three_way_comparison`` ``201711L``
---------------------------------------------------------- -----------------
``__cpp_lib_to_address`` ``201711L``
---------------------------------------------------------- -----------------
Expand Down Expand Up @@ -340,6 +340,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_mdspan`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_modules`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_move_only_function`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_optional`` ``202110L``
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx20Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"`P1236R1 <https://wg21.link/P1236R1>`__","CWG","Alternative Wording for P0907R4 Signed Integers are Two's Complement","San Diego","* *",""
"`P1248R1 <https://wg21.link/P1248R1>`__","LWG","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","San Diego","|Complete|","13.0"
"`P1285R0 <https://wg21.link/P1285R0>`__","LWG","Improving Completeness Requirements for Type Traits","San Diego","* *",""
"`P1353R0 <https://wg21.link/P1353R0>`__","CWG","Missing feature test macros","San Diego","* *",""
"`P1353R0 <https://wg21.link/P1353R0>`__","CWG","Missing feature test macros","San Diego","|In Progress|",""
"","","","","","",""
"`P0339R6 <https://wg21.link/P0339R6>`__","LWG","polymorphic_allocator<> as a vocabulary type","Kona","|Complete|","16.0"
"`P0340R3 <https://wg21.link/P0340R3>`__","LWG","Making std::underlying_type SFINAE-friendly","Kona","|Complete|","9.0"
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"`P2445R1 <https://wg21.link/P2445R1>`__","LWG","``forward_like``","July 2022","|Complete|","16.0"
"`P2446R2 <https://wg21.link/P2446R2>`__","LWG","``views::as_rvalue``","July 2022","|Complete|","16.0","|ranges|"
"`P2460R2 <https://wg21.link/P2460R2>`__","LWG","Relax requirements on ``wchar_t`` to match existing practices","July 2022","",""
"`P2465R3 <https://wg21.link/P2465R3>`__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","",""
"`P2465R3 <https://wg21.link/P2465R3>`__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","|Complete|","19.0",""
"`P2467R1 <https://wg21.link/P2467R1>`__","LWG","Support exclusive mode for ``fstreams``","July 2022","|Complete|","18.0",""
"`P2474R2 <https://wg21.link/P2474R2>`__","LWG","``views::repeat``","July 2022","|Complete|","17.0","|ranges|"
"`P2494R2 <https://wg21.link/P2494R2>`__","LWG","Relaxing range adaptors to allow for move only types","July 2022","|Complete|","17.0","|ranges|"
Expand Down
8 changes: 5 additions & 3 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ set(files
__algorithm/pop_heap.h
__algorithm/prev_permutation.h
__algorithm/pstl.h
__algorithm/pstl_frontend_dispatch.h
__algorithm/push_heap.h
__algorithm/ranges_adjacent_find.h
__algorithm/ranges_all_of.h
Expand Down Expand Up @@ -576,11 +575,12 @@ set(files
__numeric/transform_reduce.h
__ostream/basic_ostream.h
__ostream/print.h
__pstl/backend.h
__pstl/backend_fwd.h
__pstl/backends/default.h
__pstl/backends/libdispatch.h
__pstl/backends/serial.h
__pstl/backends/std_thread.h
__pstl/configuration.h
__pstl/configuration_fwd.h
__pstl/cpu_algos/any_of.h
__pstl/cpu_algos/cpu_traits.h
__pstl/cpu_algos/fill.h
Expand All @@ -590,6 +590,8 @@ set(files
__pstl/cpu_algos/stable_sort.h
__pstl/cpu_algos/transform.h
__pstl/cpu_algos/transform_reduce.h
__pstl/dispatch.h
__pstl/handle_exception.h
__random/bernoulli_distribution.h
__random/binomial_distribution.h
__random/cauchy_distribution.h
Expand Down
1,159 changes: 228 additions & 931 deletions libcxx/include/__algorithm/pstl.h

Large diffs are not rendered by default.

44 changes: 0 additions & 44 deletions libcxx/include/__algorithm/pstl_frontend_dispatch.h

This file was deleted.

18 changes: 10 additions & 8 deletions libcxx/include/__atomic/atomic_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,21 @@ struct __atomic_wait_poll_impl {

#ifndef _LIBCPP_HAS_NO_THREADS

_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*);
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*);
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile*);
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile*, __cxx_contention_t);
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
__libcpp_atomic_monitor(void const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__libcpp_atomic_wait(void const volatile*, __cxx_contention_t) _NOEXCEPT;

_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*);
__cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*);
__cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
__libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*);
__libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
__libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t);
__libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t) _NOEXCEPT;

template <class _AtomicWaitable, class _Poll>
struct __atomic_wait_backoff_impl {
Expand Down
211 changes: 73 additions & 138 deletions libcxx/include/__numeric/pstl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,7 @@
#ifndef _LIBCPP___NUMERIC_PSTL_H
#define _LIBCPP___NUMERIC_PSTL_H

#include <__algorithm/pstl_frontend_dispatch.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/operations.h>
#include <__iterator/cpp17_iterator_concepts.h>
#include <__iterator/iterator_traits.h>
#include <__numeric/transform_reduce.h>
#include <__pstl/configuration.h>
#include <__type_traits/is_execution_policy.h>
#include <__utility/move.h>
#include <optional>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -30,33 +20,66 @@ _LIBCPP_PUSH_MACROS

#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

# include <__functional/identity.h>
# include <__functional/operations.h>
# include <__iterator/cpp17_iterator_concepts.h>
# include <__iterator/iterator_traits.h>
# include <__pstl/backend.h>
# include <__pstl/dispatch.h>
# include <__pstl/handle_exception.h>
# include <__type_traits/enable_if.h>
# include <__type_traits/is_execution_policy.h>
# include <__type_traits/remove_cvref.h>
# include <__utility/forward.h>
# include <__utility/move.h>

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _ForwardIterator,
class _Tp,
class _BinaryOperation1,
class _BinaryOperation2,
class _BinaryOperation,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI optional<_Tp> __transform_reduce(
_ExecutionPolicy&&,
_ForwardIterator1&& __first1,
_ForwardIterator1&& __last1,
_ForwardIterator2&& __first2,
_Tp&& __init,
_BinaryOperation1&& __reduce,
_BinaryOperation2&& __transform) noexcept {
using _Backend = typename __select_backend<_RawPolicy>::type;
return std::__pstl_transform_reduce<_RawPolicy>(
_Backend{},
std::move(__first1),
std::move(__last1),
std::move(__first2),
_LIBCPP_HIDE_FROM_ABI _Tp reduce(
_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __op) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators");
using _Implementation = __pstl::__dispatch<__pstl::__reduce, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy),
std::move(__first),
std::move(__last),
std::move(__init),
std::move(__reduce),
std::move(__transform));
std::move(__op));
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _Tp
reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators");
using _Implementation = __pstl::__dispatch<__pstl::__reduce, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__init), plus{});
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_value_type<_ForwardIterator>
reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators");
using _Implementation = __pstl::__dispatch<__pstl::__reduce, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy),
std::move(__first),
std::move(__last),
__iter_value_type<_ForwardIterator>(),
plus{});
}

template <class _ExecutionPolicy,
Expand All @@ -77,18 +100,16 @@ _LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
_BinaryOperation2 __transform) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform_reduce requires ForwardIterators");
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform_reduce requires ForwardIterators");
auto __res = std::__transform_reduce(
__policy,
using _Implementation =
__pstl::__dispatch<__pstl::__transform_reduce_binary, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy),
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__init),
std::move(__reduce),
std::move(__transform));

if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}

// This overload doesn't get a customization point because it's trivial to detect (through e.g.
Expand All @@ -97,7 +118,8 @@ template <class _ExecutionPolicy,
class _ForwardIterator1,
class _ForwardIterator2,
class _Tp,
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0>
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
_ExecutionPolicy&& __policy,
_ForwardIterator1 __first1,
Expand All @@ -106,31 +128,16 @@ _LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
_Tp __init) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform_reduce requires ForwardIterators");
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform_reduce requires ForwardIterators");
return std::transform_reduce(__policy, __first1, __last1, __first2, __init, plus{}, multiplies{});
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _BinaryOperation,
class _UnaryOperation,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_Tp>> __transform_reduce(
_ExecutionPolicy&&,
_ForwardIterator&& __first,
_ForwardIterator&& __last,
_Tp&& __init,
_BinaryOperation&& __reduce,
_UnaryOperation&& __transform) noexcept {
using _Backend = typename __select_backend<_RawPolicy>::type;
return std::__pstl_transform_reduce<_RawPolicy>(
_Backend{},
std::move(__first),
std::move(__last),
using _Implementation =
__pstl::__dispatch<__pstl::__transform_reduce_binary, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy),
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__init),
std::move(__reduce),
std::move(__transform));
plus{},
multiplies{});
}

template <class _ExecutionPolicy,
Expand All @@ -148,86 +155,14 @@ _LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
_BinaryOperation __reduce,
_UnaryOperation __transform) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "transform_reduce requires ForwardIterators");
auto __res = std::__transform_reduce(
__policy, std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}

template <class>
void __pstl_reduce();

template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _BinaryOperation = plus<>,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Tp>
__reduce(_ExecutionPolicy&& __policy,
_ForwardIterator&& __first,
_ForwardIterator&& __last,
_Tp&& __init,
_BinaryOperation&& __op = {}) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce, _RawPolicy),
[&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Tp __g_init, _BinaryOperation __g_op) {
return std::__transform_reduce(
__policy, std::move(__g_first), std::move(__g_last), std::move(__g_init), std::move(__g_op), __identity{});
},
using _Implementation = __pstl::__dispatch<__pstl::__transform_reduce, __pstl::__current_configuration, _RawPolicy>;
return __pstl::__handle_exception<_Implementation>(
std::forward<_ExecutionPolicy>(__policy),
std::move(__first),
std::move(__last),
std::move(__init),
std::move(__op));
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _Tp,
class _BinaryOperation = plus<>,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _Tp
reduce(_ExecutionPolicy&& __policy,
_ForwardIterator __first,
_ForwardIterator __last,
_Tp __init,
_BinaryOperation __op = {}) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators");
auto __res = std::__reduce(__policy, std::move(__first), std::move(__last), std::move(__init), std::move(__op));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_value_type<_ForwardIterator>>
__reduce(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last) noexcept {
return std::__pstl_frontend_dispatch(
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce, _RawPolicy),
[&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last) {
return std::__reduce(
__policy, std::move(__g_first), std::move(__g_last), __iter_value_type<_ForwardIterator>());
},
std::move(__first),
std::move(__last));
}

template <class _ExecutionPolicy,
class _ForwardIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
_LIBCPP_HIDE_FROM_ABI __iter_value_type<_ForwardIterator>
reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) {
_LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators");
auto __res = std::__reduce(__policy, std::move(__first), std::move(__last));
if (!__res)
std::__throw_bad_alloc();
return *std::move(__res);
std::move(__reduce),
std::move(__transform));
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,30 @@
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___PSTL_CONFIGURATION_H
#define _LIBCPP___PSTL_CONFIGURATION_H
#ifndef _LIBCPP___PSTL_BACKEND_H
#define _LIBCPP___PSTL_BACKEND_H

#include <__config>
#include <__pstl/configuration_fwd.h>
#include <__pstl/backend_fwd.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#if defined(_LIBCPP_PSTL_BACKEND_SERIAL)
# include <__pstl/backends/default.h>
# include <__pstl/backends/serial.h>
#elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD)
# include <__pstl/backends/default.h>
# include <__pstl/backends/std_thread.h>
#elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH)
# include <__pstl/backends/default.h>
# include <__pstl/backends/libdispatch.h>
#endif

#endif // _LIBCPP___PSTL_CONFIGURATION_H
_LIBCPP_POP_MACROS

#endif // _LIBCPP___PSTL_BACKEND_H
301 changes: 301 additions & 0 deletions libcxx/include/__pstl/backend_fwd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___PSTL_BACKEND_FWD_H
#define _LIBCPP___PSTL_BACKEND_FWD_H

#include <__config>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

//
// This header declares available PSTL backends and the functions that must be implemented in order for the
// PSTL algorithms to be provided.
//
// Backends often do not implement the full set of functions themselves -- a configuration of the PSTL is
// usually a set of backends "stacked" together which each implement some algorithms under some execution
// policies. It is only necessary for the "stack" of backends to implement all algorithms under all execution
// policies, but a single backend is not required to implement everything on its own.
//
// The signatures used by each backend function are documented below.
//
// Exception handling
// ==================
//
// PSTL backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from
// their implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions
// are turned into a program termination at the front-end level. When a backend returns a disengaged `optional` to the
// frontend, the frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to
// the user.
//

_LIBCPP_BEGIN_NAMESPACE_STD
namespace __pstl {

template <class... _Backends>
struct __backend_configuration;

struct __default_backend_tag;
struct __libdispatch_backend_tag;
struct __serial_backend_tag;
struct __std_thread_backend_tag;

#if defined(_LIBCPP_PSTL_BACKEND_SERIAL)
using __current_configuration = __backend_configuration<__serial_backend_tag, __default_backend_tag>;
#elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD)
using __current_configuration = __backend_configuration<__std_thread_backend_tag, __default_backend_tag>;
#elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH)
using __current_configuration = __backend_configuration<__libdispatch_backend_tag, __default_backend_tag>;
#else

// ...New vendors can add parallel backends here...

# error "Invalid PSTL backend configuration"
#endif

template <class _Backend, class _ExecutionPolicy>
struct __find_if;
// template <class _Policy, class _ForwardIterator, class _Predicate>
// optional<_ForwardIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __find_if_not;
// template <class _Policy, class _ForwardIterator, class _Predicate>
// optional<_ForwardIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __find;
// template <class _Policy, class _ForwardIterator, class _Tp>
// optional<_ForwardIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __any_of;
// template <class _Policy, class _ForwardIterator, class _Predicate>
// optional<bool>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __all_of;
// template <class _Policy, class _ForwardIterator, class _Predicate>
// optional<bool>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __none_of;
// template <class _Policy, class _ForwardIterator, class _Predicate>
// optional<bool>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __is_partitioned;
// template <class _Policy, class _ForwardIterator, class _Predicate>
// optional<bool>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __for_each;
// template <class _Policy, class _ForwardIterator, class _Function>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __func) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __for_each_n;
// template <class _Policy, class _ForwardIterator, class _Size, class _Function>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _Size __size, _Function __func) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __fill;
// template <class _Policy, class _ForwardIterator, class _Tp>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __fill_n;
// template <class _Policy, class _ForwardIterator, class _Size, class _Tp>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __replace;
// template <class _Policy, class _ForwardIterator, class _Tp>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _Tp const& __old, _Tp const& __new) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __replace_if;
// template <class _Policy, class _ForwardIterator, class _Predicate, class _Tp>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _Predicate __pred, _Tp const& __new_value) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __generate;
// template <class _Policy, class _ForwardIterator, class _Generator>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __generate_n;
// template <class _Policy, class _ForwardIterator, class _Size, class _Generator>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Generator __gen) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __merge;
// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Comp>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
// _ForwardOutIterator __result, _Comp __comp) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __stable_sort;
// template <class _Policy, class _RandomAccessIterator, class _Comp>
// optional<__empty>
// operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __sort;
// template <class _Policy, class _RandomAccessIterator, class _Comp>
// optional<__empty>
// operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __transform;
// template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _UnaryOperation>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _ForwardOutIterator __result,
// _UnaryOperation __op) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __transform_binary;
// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2,
// class _ForwardOutIterator,
// class _BinaryOperation>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
// _ForwardIterator2 __first2,
// _ForwardOutIterator __result,
// _BinaryOperation __op) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __replace_copy_if;
// template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Predicate, class _Tp>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _ForwardOutIterator __out_it,
// _Predicate __pred,
// _Tp const& __new_value) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __replace_copy;
// template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _Tp>
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _ForwardOutIterator __out_it,
// _Tp const& __old_value,
// _Tp const& __new_value) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __move;
// template <class _Policy, class _ForwardIterator, class _ForwardOutIterator>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _ForwardOutIterator __out_it) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __copy;
// template <class _Policy, class _ForwardIterator, class _ForwardOutIterator>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _ForwardOutIterator __out_it) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __copy_n;
// template <class _Policy, class _ForwardIterator, class _Size, class _ForwardOutIterator>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _ForwardOutIterator __out_it) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __rotate_copy;
// template <class _Policy, class _ForwardIterator, class _ForwardOutIterator>
// optional<_ForwardOutIterator>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
// _ForwardOutIterator __out_it) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __transform_reduce;
// template <class _Policy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
// optional<_Tp>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _Tp __init,
// _BinaryOperation __reduce,
// _UnaryOperation __transform) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __transform_reduce_binary;
// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2,
// class _Tp, class _BinaryOperation1, class _BinaryOperation2>
// optional<_Tp> operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
// _ForwardIterator2 __first2,
// _Tp __init,
// _BinaryOperation1 __reduce,
// _BinaryOperation2 __transform) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __count_if;
// template <class _Policy, class _ForwardIterator, class _Predicate>
// optional<__iter_diff_t<_ForwardIterator>>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __count;
// template <class _Policy, class _ForwardIterator, class _Tp>
// optional<__iter_diff_t<_ForwardIterator>>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __equal_3leg;
// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
// optional<bool>
// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
// _ForwardIterator2 __first2,
// _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __equal;
// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
// optional<bool>
// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
// _ForwardIterator2 __first2, _ForwardIterator2 __last2,
// _Predicate __pred) const noexcept;

template <class _Backend, class _ExecutionPolicy>
struct __reduce;
// template <class _Policy, class _ForwardIterator, class _Tp, class _BinaryOperation>
// optional<_Tp>
// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
// _Tp __init, _BinaryOperation __op) const noexcept;

} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___PSTL_BACKEND_FWD_H
503 changes: 503 additions & 0 deletions libcxx/include/__pstl/backends/default.h

Large diffs are not rendered by default.

74 changes: 55 additions & 19 deletions libcxx/include/__pstl/backends/libdispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@
#include <__memory/construct_at.h>
#include <__memory/unique_ptr.h>
#include <__numeric/reduce.h>
#include <__pstl/configuration_fwd.h>
#include <__pstl/backend_fwd.h>
#include <__pstl/cpu_algos/any_of.h>
#include <__pstl/cpu_algos/cpu_traits.h>
#include <__pstl/cpu_algos/fill.h>
#include <__pstl/cpu_algos/find_if.h>
#include <__pstl/cpu_algos/for_each.h>
#include <__pstl/cpu_algos/merge.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
#include <__utility/empty.h>
#include <__utility/exception_guard.h>
#include <__utility/move.h>
Expand All @@ -36,8 +44,6 @@
_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD
namespace __pstl {

Expand Down Expand Up @@ -134,15 +140,15 @@ struct __cpu_traits<__libdispatch_backend_tag> {

unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges(
[&]() -> __merge_range_t* {
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try {
# endif
#endif
return std::allocator<__merge_range_t>().allocate(__n_ranges);
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
} catch (const std::bad_alloc&) {
return nullptr;
}
# endif
#endif
}(),
__destroy);

Expand Down Expand Up @@ -341,21 +347,51 @@ struct __cpu_traits<__libdispatch_backend_tag> {
static constexpr size_t __lane_size = 64;
};

// Mandatory implementations of the computational basis
template <class _ExecutionPolicy>
struct __find_if<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_find_if<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __for_each<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_for_each<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __merge<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_merge<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __stable_sort<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_stable_sort<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform_binary<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform_binary<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform_reduce<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform_reduce<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform_reduce_binary<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform_reduce_binary<__libdispatch_backend_tag, _ExecutionPolicy> {};

// Not mandatory, but better optimized
template <class _ExecutionPolicy>
struct __any_of<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_any_of<__libdispatch_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __fill<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_fill<__libdispatch_backend_tag, _ExecutionPolicy> {};

} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD

#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

_LIBCPP_POP_MACROS

// Implement PSTL algorithms based on the __cpu_traits specialized above
#include <__pstl/cpu_algos/any_of.h>
#include <__pstl/cpu_algos/fill.h>
#include <__pstl/cpu_algos/find_if.h>
#include <__pstl/cpu_algos/for_each.h>
#include <__pstl/cpu_algos/merge.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>

#endif // _LIBCPP___PSTL_BACKENDS_LIBDISPATCH_H
187 changes: 137 additions & 50 deletions libcxx/include/__pstl/backends/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,85 +10,172 @@
#ifndef _LIBCPP___PSTL_BACKENDS_SERIAL_H
#define _LIBCPP___PSTL_BACKENDS_SERIAL_H

#include <__algorithm/find_if.h>
#include <__algorithm/for_each.h>
#include <__algorithm/merge.h>
#include <__algorithm/stable_sort.h>
#include <__algorithm/transform.h>
#include <__config>
#include <__pstl/configuration_fwd.h>
#include <__pstl/cpu_algos/cpu_traits.h>
#include <__numeric/transform_reduce.h>
#include <__pstl/backend_fwd.h>
#include <__utility/empty.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <cstddef>
#include <optional>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

_LIBCPP_PUSH_MACROS
# include <__undef_macros>
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD
namespace __pstl {

template <>
struct __cpu_traits<__serial_backend_tag> {
template <class _RandomAccessIterator, class _Fp>
_LIBCPP_HIDE_FROM_ABI static optional<__empty>
__for_each(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) {
__f(__first, __last);
//
// This partial PSTL backend runs everything serially.
//
// TODO: Right now, the serial backend must be used with another backend
// like the "default backend" because it doesn't implement all the
// necessary PSTL operations. It would be better to dispatch all
// algorithms to their serial counterpart directly, since this can
// often be more efficient than the "default backend"'s implementation
// if we end up running serially anyways.
//

template <class _ExecutionPolicy>
struct __find_if<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _ForwardIterator, class _Pred>
_LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept {
return std::find_if(std::move(__first), std::move(__last), std::forward<_Pred>(__pred));
}
};

template <class _ExecutionPolicy>
struct __for_each<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _ForwardIterator, class _Function>
_LIBCPP_HIDE_FROM_ABI optional<__empty>
operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Function&& __func) const noexcept {
std::for_each(std::move(__first), std::move(__last), std::forward<_Function>(__func));
return __empty{};
}
};

template <class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce>
_LIBCPP_HIDE_FROM_ABI static optional<_Tp>
__transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) {
return __reduce(std::move(__first), std::move(__last), std::move(__init));
template <class _ExecutionPolicy>
struct __merge<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardOutIterator, class _Comp>
_LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> operator()(
_Policy&&,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_ForwardOutIterator __outit,
_Comp&& __comp) const noexcept {
return std::merge(
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__last2),
std::move(__outit),
std::forward<_Comp>(__comp));
}
};

template <class _RandomAccessIterator, class _Compare, class _LeafSort>
_LIBCPP_HIDE_FROM_ABI static optional<__empty>
__stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) {
__leaf_sort(__first, __last, __comp);
template <class _ExecutionPolicy>
struct __stable_sort<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _RandomAccessIterator, class _Comp>
_LIBCPP_HIDE_FROM_ABI optional<__empty>
operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp&& __comp) const noexcept {
std::stable_sort(std::move(__first), std::move(__last), std::forward<_Comp>(__comp));
return __empty{};
}
};

_LIBCPP_HIDE_FROM_ABI static void __cancel_execution() {}

template <class _RandomAccessIterator1,
class _RandomAccessIterator2,
class _RandomAccessIterator3,
class _Compare,
class _LeafMerge>
_LIBCPP_HIDE_FROM_ABI static optional<__empty>
__merge(_RandomAccessIterator1 __first1,
_RandomAccessIterator1 __last1,
_RandomAccessIterator2 __first2,
_RandomAccessIterator2 __last2,
_RandomAccessIterator3 __outit,
_Compare __comp,
_LeafMerge __leaf_merge) {
__leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp);
return __empty{};
template <class _ExecutionPolicy>
struct __transform<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _ForwardIterator, class _ForwardOutIterator, class _UnaryOperation>
_LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> operator()(
_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __outit, _UnaryOperation&& __op)
const noexcept {
return std::transform(
std::move(__first), std::move(__last), std::move(__outit), std::forward<_UnaryOperation>(__op));
}
};

template <class _ExecutionPolicy>
struct __transform_binary<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy,
class _ForwardIterator1,
class _ForwardIterator2,
class _ForwardOutIterator,
class _BinaryOperation>
_LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator>
operator()(_Policy&&,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardOutIterator __outit,
_BinaryOperation&& __op) const noexcept {
return std::transform(
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__outit),
std::forward<_BinaryOperation>(__op));
}
};

template <class _ExecutionPolicy>
struct __transform_reduce<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
_LIBCPP_HIDE_FROM_ABI optional<_Tp>
operator()(_Policy&&,
_ForwardIterator __first,
_ForwardIterator __last,
_Tp __init,
_BinaryOperation&& __reduce,
_UnaryOperation&& __transform) const noexcept {
return std::transform_reduce(
std::move(__first),
std::move(__last),
std::move(__init),
std::forward<_BinaryOperation>(__reduce),
std::forward<_UnaryOperation>(__transform));
}
};

static constexpr size_t __lane_size = 64;
template <class _ExecutionPolicy>
struct __transform_reduce_binary<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy,
class _ForwardIterator1,
class _ForwardIterator2,
class _Tp,
class _BinaryOperation1,
class _BinaryOperation2>
_LIBCPP_HIDE_FROM_ABI optional<_Tp> operator()(
_Policy&&,
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_Tp __init,
_BinaryOperation1&& __reduce,
_BinaryOperation2&& __transform) const noexcept {
return std::transform_reduce(
std::move(__first1),
std::move(__last1),
std::move(__first2),
std::move(__init),
std::forward<_BinaryOperation1>(__reduce),
std::forward<_BinaryOperation2>(__transform));
}
};

} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17

// Implement PSTL algorithms based on the __cpu_traits specialized above
#include <__pstl/cpu_algos/any_of.h>
#include <__pstl/cpu_algos/fill.h>
#include <__pstl/cpu_algos/find_if.h>
#include <__pstl/cpu_algos/for_each.h>
#include <__pstl/cpu_algos/merge.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>

#endif // _LIBCPP___PSTL_BACKENDS_SERIAL_H
77 changes: 58 additions & 19 deletions libcxx/include/__pstl/backends/std_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@
#ifndef _LIBCPP___PSTL_BACKENDS_STD_THREAD_H
#define _LIBCPP___PSTL_BACKENDS_STD_THREAD_H

#include <__assert>
#include <__config>
#include <__pstl/configuration_fwd.h>
#include <__pstl/backend_fwd.h>
#include <__pstl/cpu_algos/any_of.h>
#include <__pstl/cpu_algos/cpu_traits.h>
#include <__pstl/cpu_algos/fill.h>
#include <__pstl/cpu_algos/find_if.h>
#include <__pstl/cpu_algos/for_each.h>
#include <__pstl/cpu_algos/merge.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
#include <__utility/empty.h>
#include <__utility/move.h>
#include <cstddef>
Expand All @@ -25,14 +32,16 @@
_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

// This backend implementation is for testing purposes only and not meant for production use. This will be replaced
// by a proper implementation once the PSTL implementation is somewhat stable.

_LIBCPP_BEGIN_NAMESPACE_STD
namespace __pstl {

//
// This partial backend implementation is for testing purposes only and not meant for production use. This will be
// replaced by a proper implementation once the PSTL implementation is somewhat stable.
//
// This is intended to be used on top of the "default backend".
//

template <>
struct __cpu_traits<__std_thread_backend_tag> {
template <class _RandomAccessIterator, class _Fp>
Expand Down Expand Up @@ -77,21 +86,51 @@ struct __cpu_traits<__std_thread_backend_tag> {
static constexpr size_t __lane_size = 64;
};

// Mandatory implementations of the computational basis
template <class _ExecutionPolicy>
struct __find_if<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_find_if<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __for_each<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_for_each<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __merge<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_merge<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __stable_sort<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_stable_sort<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform_binary<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform_binary<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform_reduce<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform_reduce<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __transform_reduce_binary<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_transform_reduce_binary<__std_thread_backend_tag, _ExecutionPolicy> {};

// Not mandatory, but better optimized
template <class _ExecutionPolicy>
struct __any_of<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_any_of<__std_thread_backend_tag, _ExecutionPolicy> {};

template <class _ExecutionPolicy>
struct __fill<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_fill<__std_thread_backend_tag, _ExecutionPolicy> {};

} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD

#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17

_LIBCPP_POP_MACROS

// Implement PSTL algorithms based on the __cpu_traits specialized above
#include <__pstl/cpu_algos/any_of.h>
#include <__pstl/cpu_algos/fill.h>
#include <__pstl/cpu_algos/find_if.h>
#include <__pstl/cpu_algos/for_each.h>
#include <__pstl/cpu_algos/merge.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>

#endif // _LIBCPP___PSTL_BACKENDS_STD_THREAD_H
245 changes: 0 additions & 245 deletions libcxx/include/__pstl/configuration_fwd.h

This file was deleted.

56 changes: 28 additions & 28 deletions libcxx/include/__pstl/cpu_algos/any_of.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,32 @@
#define _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H

#include <__algorithm/any_of.h>
#include <__algorithm/find_if.h>
#include <__assert>
#include <__atomic/atomic.h>
#include <__atomic/memory_order.h>
#include <__config>
#include <__functional/operations.h>
#include <__iterator/concepts.h>
#include <__pstl/configuration_fwd.h>
#include <__pstl/backend_fwd.h>
#include <__pstl/cpu_algos/cpu_traits.h>
#include <__type_traits/is_execution_policy.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#include <cstdint>
#include <optional>

#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

_LIBCPP_PUSH_MACROS
# include <__undef_macros>
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD
namespace __pstl {

template <class _Backend, class _Index, class _Brick>
_LIBCPP_HIDE_FROM_ABI optional<bool> __parallel_or(_Index __first, _Index __last, _Brick __f) {
std::atomic<bool> __found(false);
auto __ret = __pstl::__cpu_traits<_Backend>::__for_each(__first, __last, [__f, &__found](_Index __i, _Index __j) {
auto __ret = __cpu_traits<_Backend>::__for_each(__first, __last, [__f, &__found](_Index __i, _Index __j) {
if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) {
__found.store(true, std::memory_order_relaxed);
__pstl::__cpu_traits<_Backend>::__cancel_execution();
__cpu_traits<_Backend>::__cancel_execution();
}
});
if (!__ret)
Expand Down Expand Up @@ -70,30 +68,32 @@ _LIBCPP_HIDE_FROM_ABI bool __simd_or(_Index __first, _DifferenceType __n, _Pred
return false;
}

template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
_LIBCPP_HIDE_FROM_ABI optional<bool>
__pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return std::__parallel_or<__cpu_backend_tag>(
__first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
auto __res = std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>(
__cpu_backend_tag{}, __brick_first, __brick_last, __pred);
_LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
return *std::move(__res);
});
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return std::__simd_or(__first, __last - __first, __pred);
} else {
return std::any_of(__first, __last, __pred);
template <class _Backend, class _RawExecutionPolicy>
struct __cpu_parallel_any_of {
template <class _Policy, class _ForwardIterator, class _Predicate>
_LIBCPP_HIDE_FROM_ABI optional<bool>
operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept {
if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> &&
__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return __pstl::__parallel_or<_Backend>(
__first, __last, [&__policy, &__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
using _AnyOfUnseq = __pstl::__any_of<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>;
auto __res = _AnyOfUnseq()(std::__remove_parallel_policy(__policy), __brick_first, __brick_last, __pred);
_LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!");
return *std::move(__res);
});
} else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> &&
__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
return __pstl::__simd_or(__first, __last - __first, __pred);
} else {
return std::any_of(__first, __last, __pred);
}
}
}
};

} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

#endif // _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H
Loading