llvm-project/clang/lib/AST/OpenMPClause.cpp
Matheus Izvekov 91cdd35008
[clang] Improve nested name specifier AST representation (#147835)
This is a major change on how we represent nested name qualifications in
the AST.

* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.

This patch offers a great performance benefit.

It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.

This has great results on compile-time-tracker as well:

![image](https://github.com/user-attachments/assets/700dce98-2cab-4aa8-97d1-b038c0bee831)

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.

It has some other miscelaneous drive-by fixes.

About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.

There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.

How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.

The rest and bulk of the changes are mostly consequences of the changes
in API.

PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.

Fixes #136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
2025-08-09 05:06:53 -03:00

2966 lines
104 KiB
C++

//===- OpenMPClause.cpp - Classes for OpenMP clauses ----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the subclesses of Stmt class declared in OpenMPClause.h
//
//===----------------------------------------------------------------------===//
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
#include <optional>
using namespace clang;
using namespace llvm;
using namespace omp;
OMPClause::child_range OMPClause::children() {
switch (getClauseKind()) {
default:
break;
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) \
case Enum: \
return static_cast<Class *>(this)->children();
#include "llvm/Frontend/OpenMP/OMP.inc"
}
llvm_unreachable("unknown OMPClause");
}
OMPClause::child_range OMPClause::used_children() {
switch (getClauseKind()) {
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) \
case Enum: \
return static_cast<Class *>(this)->used_children();
#define CLAUSE_NO_CLASS(Enum, Str) \
case Enum: \
break;
#include "llvm/Frontend/OpenMP/OMP.inc"
}
llvm_unreachable("unknown OMPClause");
}
OMPClauseWithPreInit *OMPClauseWithPreInit::get(OMPClause *C) {
auto *Res = OMPClauseWithPreInit::get(const_cast<const OMPClause *>(C));
return Res ? const_cast<OMPClauseWithPreInit *>(Res) : nullptr;
}
const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
switch (C->getClauseKind()) {
case OMPC_schedule:
return static_cast<const OMPScheduleClause *>(C);
case OMPC_dist_schedule:
return static_cast<const OMPDistScheduleClause *>(C);
case OMPC_firstprivate:
return static_cast<const OMPFirstprivateClause *>(C);
case OMPC_lastprivate:
return static_cast<const OMPLastprivateClause *>(C);
case OMPC_reduction:
return static_cast<const OMPReductionClause *>(C);
case OMPC_task_reduction:
return static_cast<const OMPTaskReductionClause *>(C);
case OMPC_in_reduction:
return static_cast<const OMPInReductionClause *>(C);
case OMPC_linear:
return static_cast<const OMPLinearClause *>(C);
case OMPC_if:
return static_cast<const OMPIfClause *>(C);
case OMPC_num_threads:
return static_cast<const OMPNumThreadsClause *>(C);
case OMPC_num_teams:
return static_cast<const OMPNumTeamsClause *>(C);
case OMPC_thread_limit:
return static_cast<const OMPThreadLimitClause *>(C);
case OMPC_device:
return static_cast<const OMPDeviceClause *>(C);
case OMPC_grainsize:
return static_cast<const OMPGrainsizeClause *>(C);
case OMPC_num_tasks:
return static_cast<const OMPNumTasksClause *>(C);
case OMPC_final:
return static_cast<const OMPFinalClause *>(C);
case OMPC_priority:
return static_cast<const OMPPriorityClause *>(C);
case OMPC_novariants:
return static_cast<const OMPNovariantsClause *>(C);
case OMPC_nocontext:
return static_cast<const OMPNocontextClause *>(C);
case OMPC_filter:
return static_cast<const OMPFilterClause *>(C);
case OMPC_ompx_dyn_cgroup_mem:
return static_cast<const OMPXDynCGroupMemClause *>(C);
case OMPC_default:
case OMPC_proc_bind:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_sizes:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
case OMPC_private:
case OMPC_shared:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
case OMPC_ordered:
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_capture:
case OMPC_compare:
case OMPC_fail:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
case OMPC_release:
case OMPC_relaxed:
case OMPC_depend:
case OMPC_threads:
case OMPC_simd:
case OMPC_map:
case OMPC_nogroup:
case OMPC_hint:
case OMPC_defaultmap:
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_use_device_addr:
case OMPC_is_device_ptr:
case OMPC_has_device_addr:
case OMPC_unified_address:
case OMPC_unified_shared_memory:
case OMPC_reverse_offload:
case OMPC_dynamic_allocators:
case OMPC_atomic_default_mem_order:
case OMPC_self_maps:
case OMPC_at:
case OMPC_severity:
case OMPC_message:
case OMPC_device_type:
case OMPC_match:
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
case OMPC_detach:
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
case OMPC_when:
case OMPC_bind:
case OMPC_ompx_bare:
break;
default:
break;
}
return nullptr;
}
OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(OMPClause *C) {
auto *Res = OMPClauseWithPostUpdate::get(const_cast<const OMPClause *>(C));
return Res ? const_cast<OMPClauseWithPostUpdate *>(Res) : nullptr;
}
const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) {
switch (C->getClauseKind()) {
case OMPC_lastprivate:
return static_cast<const OMPLastprivateClause *>(C);
case OMPC_reduction:
return static_cast<const OMPReductionClause *>(C);
case OMPC_task_reduction:
return static_cast<const OMPTaskReductionClause *>(C);
case OMPC_in_reduction:
return static_cast<const OMPInReductionClause *>(C);
case OMPC_linear:
return static_cast<const OMPLinearClause *>(C);
case OMPC_schedule:
case OMPC_dist_schedule:
case OMPC_firstprivate:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_sizes:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
case OMPC_private:
case OMPC_shared:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
case OMPC_ordered:
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_capture:
case OMPC_compare:
case OMPC_fail:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
case OMPC_release:
case OMPC_relaxed:
case OMPC_depend:
case OMPC_device:
case OMPC_threads:
case OMPC_simd:
case OMPC_map:
case OMPC_num_teams:
case OMPC_thread_limit:
case OMPC_priority:
case OMPC_grainsize:
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_defaultmap:
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_use_device_addr:
case OMPC_is_device_ptr:
case OMPC_has_device_addr:
case OMPC_unified_address:
case OMPC_unified_shared_memory:
case OMPC_reverse_offload:
case OMPC_dynamic_allocators:
case OMPC_atomic_default_mem_order:
case OMPC_self_maps:
case OMPC_at:
case OMPC_severity:
case OMPC_message:
case OMPC_device_type:
case OMPC_match:
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
case OMPC_novariants:
case OMPC_nocontext:
case OMPC_detach:
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
case OMPC_when:
case OMPC_bind:
break;
default:
break;
}
return nullptr;
}
/// Gets the address of the original, non-captured, expression used in the
/// clause as the preinitializer.
static Stmt **getAddrOfExprAsWritten(Stmt *S) {
if (!S)
return nullptr;
if (auto *DS = dyn_cast<DeclStmt>(S)) {
assert(DS->isSingleDecl() && "Only single expression must be captured.");
if (auto *OED = dyn_cast<OMPCapturedExprDecl>(DS->getSingleDecl()))
return OED->getInitAddress();
}
return nullptr;
}
OMPClause::child_range OMPIfClause::used_children() {
if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
return child_range(C, C + 1);
return child_range(&Condition, &Condition + 1);
}
OMPClause::child_range OMPGrainsizeClause::used_children() {
if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
return child_range(C, C + 1);
return child_range(&Grainsize, &Grainsize + 1);
}
OMPClause::child_range OMPNumTasksClause::used_children() {
if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
return child_range(C, C + 1);
return child_range(&NumTasks, &NumTasks + 1);
}
OMPClause::child_range OMPFinalClause::used_children() {
if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
return child_range(C, C + 1);
return children();
}
OMPClause::child_range OMPPriorityClause::used_children() {
if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
return child_range(C, C + 1);
return child_range(&Priority, &Priority + 1);
}
OMPClause::child_range OMPNovariantsClause::used_children() {
if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
return child_range(C, C + 1);
return children();
}
OMPClause::child_range OMPNocontextClause::used_children() {
if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
return child_range(C, C + 1);
return children();
}
OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num,
unsigned NumLoops,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
auto *Clause =
new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc);
for (unsigned I = 0; I < NumLoops; ++I) {
Clause->setLoopNumIterations(I, nullptr);
Clause->setLoopCounter(I, nullptr);
}
return Clause;
}
OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C,
unsigned NumLoops) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
auto *Clause = new (Mem) OMPOrderedClause(NumLoops);
for (unsigned I = 0; I < NumLoops; ++I) {
Clause->setLoopNumIterations(I, nullptr);
Clause->setLoopCounter(I, nullptr);
}
return Clause;
}
void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop,
Expr *NumIterations) {
assert(NumLoop < NumberOfLoops && "out of loops number.");
getTrailingObjects()[NumLoop] = NumIterations;
}
ArrayRef<Expr *> OMPOrderedClause::getLoopNumIterations() const {
return getTrailingObjects(NumberOfLoops);
}
void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) {
assert(NumLoop < NumberOfLoops && "out of loops number.");
getTrailingObjects()[NumberOfLoops + NumLoop] = Counter;
}
Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) {
assert(NumLoop < NumberOfLoops && "out of loops number.");
return getTrailingObjects()[NumberOfLoops + NumLoop];
}
const Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) const {
assert(NumLoop < NumberOfLoops && "out of loops number.");
return getTrailingObjects()[NumberOfLoops + NumLoop];
}
OMPUpdateClause *OMPUpdateClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc) {
return new (C) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/false);
}
OMPUpdateClause *
OMPUpdateClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ArgumentLoc,
OpenMPDependClauseKind DK, SourceLocation EndLoc) {
void *Mem =
C.Allocate(totalSizeToAlloc<SourceLocation, OpenMPDependClauseKind>(2, 1),
alignof(OMPUpdateClause));
auto *Clause =
new (Mem) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/true);
Clause->setLParenLoc(LParenLoc);
Clause->setArgumentLoc(ArgumentLoc);
Clause->setDependencyKind(DK);
return Clause;
}
OMPUpdateClause *OMPUpdateClause::CreateEmpty(const ASTContext &C,
bool IsExtended) {
if (!IsExtended)
return new (C) OMPUpdateClause(/*IsExtended=*/false);
void *Mem =
C.Allocate(totalSizeToAlloc<SourceLocation, OpenMPDependClauseKind>(2, 1),
alignof(OMPUpdateClause));
auto *Clause = new (Mem) OMPUpdateClause(/*IsExtended=*/true);
Clause->IsExtended = true;
return Clause;
}
void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
llvm::copy(VL, varlist_end());
}
OMPPrivateClause *
OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) {
// Allocate space for private variables and initializer expressions.
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * VL.size()));
OMPPrivateClause *Clause =
new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setPrivateCopies(PrivateVL);
return Clause;
}
OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * N));
return new (Mem) OMPPrivateClause(N);
}
void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
llvm::copy(VL, varlist_end());
}
void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of inits is not the same as the preallocated buffer");
llvm::copy(VL, getPrivateCopies().end());
}
OMPFirstprivateClause *
OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
ArrayRef<Expr *> InitVL, Stmt *PreInit) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * VL.size()));
OMPFirstprivateClause *Clause =
new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setPrivateCopies(PrivateVL);
Clause->setInits(InitVL);
Clause->setPreInitStmt(PreInit);
return Clause;
}
OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * N));
return new (Mem) OMPFirstprivateClause(N);
}
void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) {
assert(PrivateCopies.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
llvm::copy(PrivateCopies, varlist_end());
}
void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
"not the same as the "
"preallocated buffer");
llvm::copy(SrcExprs, getPrivateCopies().end());
}
void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
assert(DstExprs.size() == varlist_size() && "Number of destination "
"expressions is not the same as "
"the preallocated buffer");
llvm::copy(DstExprs, getSourceExprs().end());
}
void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
assert(AssignmentOps.size() == varlist_size() &&
"Number of assignment expressions is not the same as the preallocated "
"buffer");
llvm::copy(AssignmentOps, getDestinationExprs().end());
}
OMPLastprivateClause *OMPLastprivateClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps,
OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc,
SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
OMPLastprivateClause *Clause = new (Mem) OMPLastprivateClause(
StartLoc, LParenLoc, EndLoc, LPKind, LPKindLoc, ColonLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setSourceExprs(SrcExprs);
Clause->setDestinationExprs(DstExprs);
Clause->setAssignmentOps(AssignmentOps);
Clause->setPreInitStmt(PreInit);
Clause->setPostUpdateExpr(PostUpdate);
return Clause;
}
OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
return new (Mem) OMPLastprivateClause(N);
}
OMPSharedClause *OMPSharedClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> VL) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
OMPSharedClause *Clause =
new (Mem) OMPSharedClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
}
OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPSharedClause(N);
}
void OMPLinearClause::setPrivates(ArrayRef<Expr *> PL) {
assert(PL.size() == varlist_size() &&
"Number of privates is not the same as the preallocated buffer");
llvm::copy(PL, varlist_end());
}
void OMPLinearClause::setInits(ArrayRef<Expr *> IL) {
assert(IL.size() == varlist_size() &&
"Number of inits is not the same as the preallocated buffer");
llvm::copy(IL, getPrivates().end());
}
void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) {
assert(UL.size() == varlist_size() &&
"Number of updates is not the same as the preallocated buffer");
llvm::copy(UL, getInits().end());
}
void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) {
assert(FL.size() == varlist_size() &&
"Number of final updates is not the same as the preallocated buffer");
llvm::copy(FL, getUpdates().end());
}
void OMPLinearClause::setUsedExprs(ArrayRef<Expr *> UE) {
assert(
UE.size() == varlist_size() + 1 &&
"Number of used expressions is not the same as the preallocated buffer");
llvm::copy(UE, getFinals().end() + 2);
}
OMPLinearClause *OMPLinearClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
SourceLocation ColonLoc, SourceLocation StepModifierLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PL,
ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit,
Expr *PostUpdate) {
// Allocate space for 5 lists (Vars, Inits, Updates, Finals), 2 expressions
// (Step and CalcStep), list of used expression + step.
void *Mem =
C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size() + 2 + VL.size() + 1));
OMPLinearClause *Clause =
new (Mem) OMPLinearClause(StartLoc, LParenLoc, Modifier, ModifierLoc,
ColonLoc, StepModifierLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setPrivates(PL);
Clause->setInits(IL);
// Fill update and final expressions with zeroes, they are provided later,
// after the directive construction.
std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(),
nullptr);
std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(),
nullptr);
std::fill(Clause->getUsedExprs().begin(), Clause->getUsedExprs().end(),
nullptr);
Clause->setStep(Step);
Clause->setCalcStep(CalcStep);
Clause->setPreInitStmt(PreInit);
Clause->setPostUpdateExpr(PostUpdate);
return Clause;
}
OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
unsigned NumVars) {
// Allocate space for 5 lists (Vars, Inits, Updates, Finals), 2 expressions
// (Step and CalcStep), list of used expression + step.
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * NumVars + 2 + NumVars +1));
return new (Mem) OMPLinearClause(NumVars);
}
OMPClause::child_range OMPLinearClause::used_children() {
// Range includes only non-nullptr elements.
return child_range(
reinterpret_cast<Stmt **>(getUsedExprs().begin()),
reinterpret_cast<Stmt **>(llvm::find(getUsedExprs(), nullptr)));
}
OMPAlignedClause *
OMPAlignedClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, Expr *A) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
OMPAlignedClause *Clause = new (Mem)
OMPAlignedClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setAlignment(A);
return Clause;
}
OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C,
unsigned NumVars) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumVars + 1));
return new (Mem) OMPAlignedClause(NumVars);
}
OMPAlignClause *OMPAlignClause::Create(const ASTContext &C, Expr *A,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
return new (C) OMPAlignClause(A, StartLoc, LParenLoc, EndLoc);
}
void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
"not the same as the "
"preallocated buffer");
llvm::copy(SrcExprs, varlist_end());
}
void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
assert(DstExprs.size() == varlist_size() && "Number of destination "
"expressions is not the same as "
"the preallocated buffer");
llvm::copy(DstExprs, getSourceExprs().end());
}
void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
assert(AssignmentOps.size() == varlist_size() &&
"Number of assignment expressions is not the same as the preallocated "
"buffer");
llvm::copy(AssignmentOps, getDestinationExprs().end());
}
OMPCopyinClause *OMPCopyinClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size()));
OMPCopyinClause *Clause =
new (Mem) OMPCopyinClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setSourceExprs(SrcExprs);
Clause->setDestinationExprs(DstExprs);
Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N));
return new (Mem) OMPCopyinClause(N);
}
void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
"not the same as the "
"preallocated buffer");
llvm::copy(SrcExprs, varlist_end());
}
void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
assert(DstExprs.size() == varlist_size() && "Number of destination "
"expressions is not the same as "
"the preallocated buffer");
llvm::copy(DstExprs, getSourceExprs().end());
}
void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
assert(AssignmentOps.size() == varlist_size() &&
"Number of assignment expressions is not the same as the preallocated "
"buffer");
llvm::copy(AssignmentOps, getDestinationExprs().end());
}
OMPCopyprivateClause *OMPCopyprivateClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size()));
OMPCopyprivateClause *Clause =
new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setSourceExprs(SrcExprs);
Clause->setDestinationExprs(DstExprs);
Clause->setAssignmentOps(AssignmentOps);
return Clause;
}
OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N));
return new (Mem) OMPCopyprivateClause(N);
}
void OMPReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
assert(Privates.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
llvm::copy(Privates, varlist_end());
}
void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
assert(
LHSExprs.size() == varlist_size() &&
"Number of LHS expressions is not the same as the preallocated buffer");
llvm::copy(LHSExprs, getPrivates().end());
}
void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
assert(
RHSExprs.size() == varlist_size() &&
"Number of RHS expressions is not the same as the preallocated buffer");
llvm::copy(RHSExprs, getLHSExprs().end());
}
void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
assert(ReductionOps.size() == varlist_size() && "Number of reduction "
"expressions is not the same "
"as the preallocated buffer");
llvm::copy(ReductionOps, getRHSExprs().end());
}
void OMPReductionClause::setInscanCopyOps(ArrayRef<Expr *> Ops) {
assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction.");
assert(Ops.size() == varlist_size() && "Number of copy "
"expressions is not the same "
"as the preallocated buffer");
llvm::copy(Ops, getReductionOps().end());
}
void OMPReductionClause::setInscanCopyArrayTemps(
ArrayRef<Expr *> CopyArrayTemps) {
assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction.");
assert(CopyArrayTemps.size() == varlist_size() &&
"Number of copy temp expressions is not the same as the preallocated "
"buffer");
llvm::copy(CopyArrayTemps, getInscanCopyOps().end());
}
void OMPReductionClause::setInscanCopyArrayElems(
ArrayRef<Expr *> CopyArrayElems) {
assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction.");
assert(CopyArrayElems.size() == varlist_size() &&
"Number of copy temp expressions is not the same as the preallocated "
"buffer");
llvm::copy(CopyArrayElems, getInscanCopyArrayTemps().end());
}
OMPReductionClause *OMPReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ModifierLoc, SourceLocation EndLoc, SourceLocation ColonLoc,
OpenMPReductionClauseModifier Modifier, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps,
ArrayRef<Expr *> CopyOps, ArrayRef<Expr *> CopyArrayTemps,
ArrayRef<Expr *> CopyArrayElems, Stmt *PreInit, Expr *PostUpdate,
ArrayRef<bool> IsPrivateVarReduction,
OpenMPOriginalSharingModifier OrignalSharingModifier) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *, bool>(
(Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * VL.size(), VL.size()));
auto *Clause = new (Mem) OMPReductionClause(
StartLoc, LParenLoc, ModifierLoc, EndLoc, ColonLoc, Modifier,
OrignalSharingModifier, VL.size(), QualifierLoc, NameInfo);
Clause->setVarRefs(VL);
Clause->setPrivates(Privates);
Clause->setLHSExprs(LHSExprs);
Clause->setRHSExprs(RHSExprs);
Clause->setReductionOps(ReductionOps);
Clause->setPreInitStmt(PreInit);
Clause->setPostUpdateExpr(PostUpdate);
Clause->setPrivateVariableReductionFlags(IsPrivateVarReduction);
if (Modifier == OMPC_REDUCTION_inscan) {
Clause->setInscanCopyOps(CopyOps);
Clause->setInscanCopyArrayTemps(CopyArrayTemps);
Clause->setInscanCopyArrayElems(CopyArrayElems);
} else {
assert(CopyOps.empty() &&
"copy operations are expected in inscan reductions only.");
assert(CopyArrayTemps.empty() &&
"copy array temps are expected in inscan reductions only.");
assert(CopyArrayElems.empty() &&
"copy array temps are expected in inscan reductions only.");
}
return Clause;
}
OMPReductionClause *
OMPReductionClause::CreateEmpty(const ASTContext &C, unsigned N,
OpenMPReductionClauseModifier Modifier) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *, bool>(
(Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * N, N));
auto *Clause = new (Mem) OMPReductionClause(N);
Clause->setModifier(Modifier);
return Clause;
}
void OMPTaskReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
assert(Privates.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
llvm::copy(Privates, varlist_end());
}
void OMPTaskReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
assert(
LHSExprs.size() == varlist_size() &&
"Number of LHS expressions is not the same as the preallocated buffer");
llvm::copy(LHSExprs, getPrivates().end());
}
void OMPTaskReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
assert(
RHSExprs.size() == varlist_size() &&
"Number of RHS expressions is not the same as the preallocated buffer");
llvm::copy(RHSExprs, getLHSExprs().end());
}
void OMPTaskReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
assert(ReductionOps.size() == varlist_size() && "Number of task reduction "
"expressions is not the same "
"as the preallocated buffer");
llvm::copy(ReductionOps, getRHSExprs().end());
}
OMPTaskReductionClause *OMPTaskReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit,
Expr *PostUpdate) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
OMPTaskReductionClause *Clause = new (Mem) OMPTaskReductionClause(
StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
Clause->setVarRefs(VL);
Clause->setPrivates(Privates);
Clause->setLHSExprs(LHSExprs);
Clause->setRHSExprs(RHSExprs);
Clause->setReductionOps(ReductionOps);
Clause->setPreInitStmt(PreInit);
Clause->setPostUpdateExpr(PostUpdate);
return Clause;
}
OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
return new (Mem) OMPTaskReductionClause(N);
}
void OMPInReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
assert(Privates.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
llvm::copy(Privates, varlist_end());
}
void OMPInReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
assert(
LHSExprs.size() == varlist_size() &&
"Number of LHS expressions is not the same as the preallocated buffer");
llvm::copy(LHSExprs, getPrivates().end());
}
void OMPInReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
assert(
RHSExprs.size() == varlist_size() &&
"Number of RHS expressions is not the same as the preallocated buffer");
llvm::copy(RHSExprs, getLHSExprs().end());
}
void OMPInReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
assert(ReductionOps.size() == varlist_size() && "Number of in reduction "
"expressions is not the same "
"as the preallocated buffer");
llvm::copy(ReductionOps, getRHSExprs().end());
}
void OMPInReductionClause::setTaskgroupDescriptors(
ArrayRef<Expr *> TaskgroupDescriptors) {
assert(TaskgroupDescriptors.size() == varlist_size() &&
"Number of in reduction descriptors is not the same as the "
"preallocated buffer");
llvm::copy(TaskgroupDescriptors, getReductionOps().end());
}
OMPInReductionClause *OMPInReductionClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps,
ArrayRef<Expr *> TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * VL.size()));
OMPInReductionClause *Clause = new (Mem) OMPInReductionClause(
StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
Clause->setVarRefs(VL);
Clause->setPrivates(Privates);
Clause->setLHSExprs(LHSExprs);
Clause->setRHSExprs(RHSExprs);
Clause->setReductionOps(ReductionOps);
Clause->setTaskgroupDescriptors(TaskgroupDescriptors);
Clause->setPreInitStmt(PreInit);
Clause->setPostUpdateExpr(PostUpdate);
return Clause;
}
OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * N));
return new (Mem) OMPInReductionClause(N);
}
OMPSizesClause *OMPSizesClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> Sizes) {
OMPSizesClause *Clause = CreateEmpty(C, Sizes.size());
Clause->setLocStart(StartLoc);
Clause->setLParenLoc(LParenLoc);
Clause->setLocEnd(EndLoc);
Clause->setSizesRefs(Sizes);
return Clause;
}
OMPSizesClause *OMPSizesClause::CreateEmpty(const ASTContext &C,
unsigned NumSizes) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumSizes));
return new (Mem) OMPSizesClause(NumSizes);
}
OMPPermutationClause *OMPPermutationClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> Args) {
OMPPermutationClause *Clause = CreateEmpty(C, Args.size());
Clause->setLocStart(StartLoc);
Clause->setLParenLoc(LParenLoc);
Clause->setLocEnd(EndLoc);
Clause->setArgRefs(Args);
return Clause;
}
OMPPermutationClause *OMPPermutationClause::CreateEmpty(const ASTContext &C,
unsigned NumLoops) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumLoops));
return new (Mem) OMPPermutationClause(NumLoops);
}
OMPFullClause *OMPFullClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc) {
OMPFullClause *Clause = CreateEmpty(C);
Clause->setLocStart(StartLoc);
Clause->setLocEnd(EndLoc);
return Clause;
}
OMPFullClause *OMPFullClause::CreateEmpty(const ASTContext &C) {
return new (C) OMPFullClause();
}
OMPPartialClause *OMPPartialClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
Expr *Factor) {
OMPPartialClause *Clause = CreateEmpty(C);
Clause->setLocStart(StartLoc);
Clause->setLParenLoc(LParenLoc);
Clause->setLocEnd(EndLoc);
Clause->setFactor(Factor);
return Clause;
}
OMPPartialClause *OMPPartialClause::CreateEmpty(const ASTContext &C) {
return new (C) OMPPartialClause();
}
OMPAllocateClause *OMPAllocateClause::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc,
OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc,
OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc,
SourceLocation EndLoc, ArrayRef<Expr *> VL) {
// Allocate space for private variables and initializer expressions.
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
auto *Clause = new (Mem) OMPAllocateClause(
StartLoc, LParenLoc, Allocator, Alignment, ColonLoc, Modifier1,
Modifier1Loc, Modifier2, Modifier2Loc, EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
}
OMPAllocateClause *OMPAllocateClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPAllocateClause(N);
}
OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> VL) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
OMPFlushClause *Clause =
new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
}
OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPFlushClause(N);
}
OMPDepobjClause *OMPDepobjClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc,
Expr *Depobj) {
auto *Clause = new (C) OMPDepobjClause(StartLoc, LParenLoc, RParenLoc);
Clause->setDepobj(Depobj);
return Clause;
}
OMPDepobjClause *OMPDepobjClause::CreateEmpty(const ASTContext &C) {
return new (C) OMPDepobjClause();
}
OMPDependClause *
OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
DependDataTy Data, Expr *DepModifier,
ArrayRef<Expr *> VL, unsigned NumLoops) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *>(VL.size() + /*depend-modifier*/ 1 + NumLoops),
alignof(OMPDependClause));
OMPDependClause *Clause = new (Mem)
OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
Clause->setDependencyKind(Data.DepKind);
Clause->setDependencyLoc(Data.DepLoc);
Clause->setColonLoc(Data.ColonLoc);
Clause->setOmpAllMemoryLoc(Data.OmpAllMemoryLoc);
Clause->setModifier(DepModifier);
Clause->setVarRefs(VL);
for (unsigned I = 0 ; I < NumLoops; ++I)
Clause->setLoopData(I, nullptr);
return Clause;
}
OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N,
unsigned NumLoops) {
void *Mem =
C.Allocate(totalSizeToAlloc<Expr *>(N + /*depend-modifier*/ 1 + NumLoops),
alignof(OMPDependClause));
return new (Mem) OMPDependClause(N, NumLoops);
}
void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
assert((getDependencyKind() == OMPC_DEPEND_sink ||
getDependencyKind() == OMPC_DEPEND_source) &&
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
auto *It = std::next(getVarRefs().end(), NumLoop + 1);
*It = Cnt;
}
Expr *OMPDependClause::getLoopData(unsigned NumLoop) {
assert((getDependencyKind() == OMPC_DEPEND_sink ||
getDependencyKind() == OMPC_DEPEND_source) &&
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
auto *It = std::next(getVarRefs().end(), NumLoop + 1);
return *It;
}
const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const {
assert((getDependencyKind() == OMPC_DEPEND_sink ||
getDependencyKind() == OMPC_DEPEND_source) &&
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
const auto *It = std::next(getVarRefs().end(), NumLoop + 1);
return *It;
}
void OMPDependClause::setModifier(Expr *DepModifier) {
*getVarRefs().end() = DepModifier;
}
Expr *OMPDependClause::getModifier() { return *getVarRefs().end(); }
unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
MappableExprComponentListsRef ComponentLists) {
unsigned TotalNum = 0u;
for (auto &C : ComponentLists)
TotalNum += C.size();
return TotalNum;
}
unsigned OMPClauseMappableExprCommon::getUniqueDeclarationsTotalNumber(
ArrayRef<const ValueDecl *> Declarations) {
llvm::SmallPtrSet<const ValueDecl *, 8> UniqueDecls;
for (const ValueDecl *D : Declarations) {
const ValueDecl *VD = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
UniqueDecls.insert(VD);
}
return UniqueDecls.size();
}
OMPMapClause *OMPMapClause::Create(
const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapModifiers,
ArrayRef<SourceLocation> MapModifiersLoc,
NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId,
OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
Sizes.NumComponentLists = ComponentLists.size();
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
// 2 x NumVars x Expr* - we have an original list expression and an associated
// user-defined mapper for each clause list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars + 1, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
OMPMapClause *Clause = new (Mem)
OMPMapClause(MapModifiers, MapModifiersLoc, UDMQualifierLoc, MapperId,
Type, TypeIsImplicit, TypeLoc, Locs, Sizes);
Clause->setVarRefs(Vars);
Clause->setUDMapperRefs(UDMapperRefs);
Clause->setIteratorModifier(IteratorModifier);
Clause->setClauseInfo(Declarations, ComponentLists);
Clause->setMapType(Type);
Clause->setMapLoc(TypeLoc);
return Clause;
}
OMPMapClause *
OMPMapClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars + 1, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
OMPMapClause *Clause = new (Mem) OMPMapClause(Sizes);
Clause->setIteratorModifier(nullptr);
return Clause;
}
OMPToClause *OMPToClause::Create(
const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
ArrayRef<SourceLocation> MotionModifiersLoc,
NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
Sizes.NumComponentLists = ComponentLists.size();
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
// 2 x NumVars x Expr* - we have an original list expression and an associated
// user-defined mapper for each clause list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
auto *Clause = new (Mem) OMPToClause(MotionModifiers, MotionModifiersLoc,
UDMQualifierLoc, MapperId, Locs, Sizes);
Clause->setVarRefs(Vars);
Clause->setUDMapperRefs(UDMapperRefs);
Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPToClause(Sizes);
}
OMPFromClause *OMPFromClause::Create(
const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
ArrayRef<SourceLocation> MotionModifiersLoc,
NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
Sizes.NumComponentLists = ComponentLists.size();
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
// 2 x NumVars x Expr* - we have an original list expression and an associated
// user-defined mapper for each clause list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
auto *Clause =
new (Mem) OMPFromClause(MotionModifiers, MotionModifiersLoc,
UDMQualifierLoc, MapperId, Locs, Sizes);
Clause->setVarRefs(Vars);
Clause->setUDMapperRefs(UDMapperRefs);
Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
OMPFromClause *
OMPFromClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPFromClause(Sizes);
}
void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
llvm::copy(VL, varlist_end());
}
void OMPUseDevicePtrClause::setInits(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of inits is not the same as the preallocated buffer");
llvm::copy(VL, getPrivateCopies().end());
}
OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(
const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
ArrayRef<Expr *> PrivateVars, ArrayRef<Expr *> Inits,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
Sizes.NumComponentLists = ComponentLists.size();
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
// NumVars x Expr* - we have an original list expression for each clause
// list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
3 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause(Locs, Sizes);
Clause->setVarRefs(Vars);
Clause->setPrivateCopies(PrivateVars);
Clause->setInits(Inits);
Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
OMPUseDevicePtrClause *
OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
3 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPUseDevicePtrClause(Sizes);
}
OMPUseDeviceAddrClause *
OMPUseDeviceAddrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs,
ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
Sizes.NumComponentLists = ComponentLists.size();
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
// 3 x NumVars x Expr* - we have an original list expression for each clause
// list entry and an equal number of private copies and inits.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
auto *Clause = new (Mem) OMPUseDeviceAddrClause(Locs, Sizes);
Clause->setVarRefs(Vars);
Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
OMPUseDeviceAddrClause *
OMPUseDeviceAddrClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPUseDeviceAddrClause(Sizes);
}
OMPIsDevicePtrClause *
OMPIsDevicePtrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs,
ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
Sizes.NumComponentLists = ComponentLists.size();
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
// NumVars x Expr* - we have an original list expression for each clause list
// entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause(Locs, Sizes);
Clause->setVarRefs(Vars);
Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
OMPIsDevicePtrClause *
OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPIsDevicePtrClause(Sizes);
}
OMPHasDeviceAddrClause *
OMPHasDeviceAddrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs,
ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
Sizes.NumComponentLists = ComponentLists.size();
Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
// We need to allocate:
// NumVars x Expr* - we have an original list expression for each clause list
// entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
auto *Clause = new (Mem) OMPHasDeviceAddrClause(Locs, Sizes);
Clause->setVarRefs(Vars);
Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
OMPHasDeviceAddrClause *
OMPHasDeviceAddrClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
Sizes.NumVars, Sizes.NumUniqueDeclarations,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPHasDeviceAddrClause(Sizes);
}
OMPNontemporalClause *OMPNontemporalClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> VL) {
// Allocate space for nontemporal variables + private references.
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * VL.size()));
auto *Clause =
new (Mem) OMPNontemporalClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
}
OMPNontemporalClause *OMPNontemporalClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * N));
return new (Mem) OMPNontemporalClause(N);
}
void OMPNontemporalClause::setPrivateRefs(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() && "Number of private references is not "
"the same as the preallocated buffer");
llvm::copy(VL, varlist_end());
}
OMPInclusiveClause *OMPInclusiveClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> VL) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
auto *Clause =
new (Mem) OMPInclusiveClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
}
OMPInclusiveClause *OMPInclusiveClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPInclusiveClause(N);
}
OMPExclusiveClause *OMPExclusiveClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> VL) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
auto *Clause =
new (Mem) OMPExclusiveClause(StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
}
OMPExclusiveClause *OMPExclusiveClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPExclusiveClause(N);
}
void OMPUsesAllocatorsClause::setAllocatorsData(
ArrayRef<OMPUsesAllocatorsClause::Data> Data) {
assert(Data.size() == NumOfAllocators &&
"Size of allocators data is not the same as the preallocated buffer.");
for (unsigned I = 0, E = Data.size(); I < E; ++I) {
const OMPUsesAllocatorsClause::Data &D = Data[I];
getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
static_cast<int>(ExprOffsets::Allocator)] =
D.Allocator;
getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
static_cast<int>(
ExprOffsets::AllocatorTraits)] =
D.AllocatorTraits;
getTrailingObjects<
SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
static_cast<int>(ParenLocsOffsets::LParen)] =
D.LParenLoc;
getTrailingObjects<
SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
static_cast<int>(ParenLocsOffsets::RParen)] =
D.RParenLoc;
}
}
OMPUsesAllocatorsClause::Data
OMPUsesAllocatorsClause::getAllocatorData(unsigned I) const {
OMPUsesAllocatorsClause::Data Data;
Data.Allocator =
getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
static_cast<int>(ExprOffsets::Allocator)];
Data.AllocatorTraits =
getTrailingObjects<Expr *>()[I * static_cast<int>(ExprOffsets::Total) +
static_cast<int>(
ExprOffsets::AllocatorTraits)];
Data.LParenLoc = getTrailingObjects<
SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
static_cast<int>(ParenLocsOffsets::LParen)];
Data.RParenLoc = getTrailingObjects<
SourceLocation>()[I * static_cast<int>(ParenLocsOffsets::Total) +
static_cast<int>(ParenLocsOffsets::RParen)];
return Data;
}
OMPUsesAllocatorsClause *
OMPUsesAllocatorsClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<OMPUsesAllocatorsClause::Data> Data) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *, SourceLocation>(
static_cast<int>(ExprOffsets::Total) * Data.size(),
static_cast<int>(ParenLocsOffsets::Total) * Data.size()));
auto *Clause = new (Mem)
OMPUsesAllocatorsClause(StartLoc, LParenLoc, EndLoc, Data.size());
Clause->setAllocatorsData(Data);
return Clause;
}
OMPUsesAllocatorsClause *
OMPUsesAllocatorsClause::CreateEmpty(const ASTContext &C, unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *, SourceLocation>(
static_cast<int>(ExprOffsets::Total) * N,
static_cast<int>(ParenLocsOffsets::Total) * N));
return new (Mem) OMPUsesAllocatorsClause(N);
}
OMPAffinityClause *
OMPAffinityClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, Expr *Modifier,
ArrayRef<Expr *> Locators) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Locators.size() + 1));
auto *Clause = new (Mem)
OMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc, Locators.size());
Clause->setModifier(Modifier);
Clause->setVarRefs(Locators);
return Clause;
}
OMPAffinityClause *OMPAffinityClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1));
return new (Mem) OMPAffinityClause(N);
}
OMPInitClause *OMPInitClause::Create(const ASTContext &C, Expr *InteropVar,
OMPInteropInfo &InteropInfo,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation VarLoc,
SourceLocation EndLoc) {
void *Mem =
C.Allocate(totalSizeToAlloc<Expr *>(InteropInfo.PreferTypes.size() + 1));
auto *Clause = new (Mem) OMPInitClause(
InteropInfo.IsTarget, InteropInfo.IsTargetSync, StartLoc, LParenLoc,
VarLoc, EndLoc, InteropInfo.PreferTypes.size() + 1);
Clause->setInteropVar(InteropVar);
llvm::copy(InteropInfo.PreferTypes, Clause->getTrailingObjects() + 1);
return Clause;
}
OMPInitClause *OMPInitClause::CreateEmpty(const ASTContext &C, unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPInitClause(N);
}
OMPBindClause *
OMPBindClause::Create(const ASTContext &C, OpenMPBindClauseKind K,
SourceLocation KLoc, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc) {
return new (C) OMPBindClause(K, KLoc, StartLoc, LParenLoc, EndLoc);
}
OMPBindClause *OMPBindClause::CreateEmpty(const ASTContext &C) {
return new (C) OMPBindClause();
}
OMPDoacrossClause *
OMPDoacrossClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
OpenMPDoacrossClauseModifier DepType,
SourceLocation DepLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VL, unsigned NumLoops) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops),
alignof(OMPDoacrossClause));
OMPDoacrossClause *Clause = new (Mem)
OMPDoacrossClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
Clause->setDependenceType(DepType);
Clause->setDependenceLoc(DepLoc);
Clause->setColonLoc(ColonLoc);
Clause->setVarRefs(VL);
for (unsigned I = 0; I < NumLoops; ++I)
Clause->setLoopData(I, nullptr);
return Clause;
}
OMPDoacrossClause *OMPDoacrossClause::CreateEmpty(const ASTContext &C,
unsigned N,
unsigned NumLoops) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops),
alignof(OMPDoacrossClause));
return new (Mem) OMPDoacrossClause(N, NumLoops);
}
void OMPDoacrossClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
assert(NumLoop < NumLoops && "Loop index must be less number of loops.");
auto *It = std::next(getVarRefs().end(), NumLoop);
*It = Cnt;
}
Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) {
assert(NumLoop < NumLoops && "Loop index must be less number of loops.");
auto *It = std::next(getVarRefs().end(), NumLoop);
return *It;
}
const Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) const {
assert(NumLoop < NumLoops && "Loop index must be less number of loops.");
const auto *It = std::next(getVarRefs().end(), NumLoop);
return *It;
}
OMPAbsentClause *OMPAbsentClause::Create(const ASTContext &C,
ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc,
SourceLocation LLoc,
SourceLocation RLoc) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(DKVec.size()),
alignof(OMPAbsentClause));
auto *AC = new (Mem) OMPAbsentClause(Loc, LLoc, RLoc, DKVec.size());
AC->setDirectiveKinds(DKVec);
return AC;
}
OMPAbsentClause *OMPAbsentClause::CreateEmpty(const ASTContext &C, unsigned K) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(K),
alignof(OMPAbsentClause));
return new (Mem) OMPAbsentClause(K);
}
OMPContainsClause *OMPContainsClause::Create(
const ASTContext &C, ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(DKVec.size()),
alignof(OMPContainsClause));
auto *CC = new (Mem) OMPContainsClause(Loc, LLoc, RLoc, DKVec.size());
CC->setDirectiveKinds(DKVec);
return CC;
}
OMPContainsClause *OMPContainsClause::CreateEmpty(const ASTContext &C,
unsigned K) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(K),
alignof(OMPContainsClause));
return new (Mem) OMPContainsClause(K);
}
OMPNumTeamsClause *OMPNumTeamsClause::Create(
const ASTContext &C, OpenMPDirectiveKind CaptureRegion,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL, Stmt *PreInit) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
OMPNumTeamsClause *Clause =
new (Mem) OMPNumTeamsClause(C, StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setPreInitStmt(PreInit, CaptureRegion);
return Clause;
}
OMPNumTeamsClause *OMPNumTeamsClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPNumTeamsClause(N);
}
OMPThreadLimitClause *OMPThreadLimitClause::Create(
const ASTContext &C, OpenMPDirectiveKind CaptureRegion,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL, Stmt *PreInit) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
OMPThreadLimitClause *Clause =
new (Mem) OMPThreadLimitClause(C, StartLoc, LParenLoc, EndLoc, VL.size());
Clause->setVarRefs(VL);
Clause->setPreInitStmt(PreInit, CaptureRegion);
return Clause;
}
OMPThreadLimitClause *OMPThreadLimitClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
return new (Mem) OMPThreadLimitClause(N);
}
//===----------------------------------------------------------------------===//
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << "if(";
if (Node->getNameModifier() != OMPD_unknown)
OS << getOpenMPDirectiveName(Node->getNameModifier(), Version) << ": ";
Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) {
OS << "final(";
Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
OS << "num_threads(";
OpenMPNumThreadsClauseModifier Modifier = Node->getModifier();
if (Modifier != OMPC_NUMTHREADS_unknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier)
<< ": ";
}
Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPAlignClause(OMPAlignClause *Node) {
OS << "align(";
Node->getAlignment()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
OS << "safelen(";
Node->getSafelen()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) {
OS << "simdlen(";
Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPSizesClause(OMPSizesClause *Node) {
OS << "sizes(";
bool First = true;
for (auto *Size : Node->getSizesRefs()) {
if (!First)
OS << ", ";
Size->printPretty(OS, nullptr, Policy, 0);
First = false;
}
OS << ")";
}
void OMPClausePrinter::VisitOMPPermutationClause(OMPPermutationClause *Node) {
OS << "permutation(";
llvm::interleaveComma(Node->getArgsRefs(), OS, [&](const Expr *E) {
E->printPretty(OS, nullptr, Policy, 0);
});
OS << ")";
}
void OMPClausePrinter::VisitOMPFullClause(OMPFullClause *Node) { OS << "full"; }
void OMPClausePrinter::VisitOMPPartialClause(OMPPartialClause *Node) {
OS << "partial";
if (Expr *Factor = Node->getFactor()) {
OS << '(';
Factor->printPretty(OS, nullptr, Policy, 0);
OS << ')';
}
}
void OMPClausePrinter::VisitOMPAllocatorClause(OMPAllocatorClause *Node) {
OS << "allocator(";
Node->getAllocator()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
OS << "collapse(";
Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPDetachClause(OMPDetachClause *Node) {
OS << "detach(";
Node->getEventHandler()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
OS << "default("
<< getOpenMPSimpleClauseTypeName(OMPC_default,
unsigned(Node->getDefaultKind()))
<< ")";
}
void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
OS << "proc_bind("
<< getOpenMPSimpleClauseTypeName(OMPC_proc_bind,
unsigned(Node->getProcBindKind()))
<< ")";
}
void OMPClausePrinter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {
OS << "unified_address";
}
void OMPClausePrinter::VisitOMPUnifiedSharedMemoryClause(
OMPUnifiedSharedMemoryClause *) {
OS << "unified_shared_memory";
}
void OMPClausePrinter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {
OS << "reverse_offload";
}
void OMPClausePrinter::VisitOMPDynamicAllocatorsClause(
OMPDynamicAllocatorsClause *) {
OS << "dynamic_allocators";
}
void OMPClausePrinter::VisitOMPAtomicDefaultMemOrderClause(
OMPAtomicDefaultMemOrderClause *Node) {
OS << "atomic_default_mem_order("
<< getOpenMPSimpleClauseTypeName(OMPC_atomic_default_mem_order,
Node->getAtomicDefaultMemOrderKind())
<< ")";
}
void OMPClausePrinter::VisitOMPSelfMapsClause(OMPSelfMapsClause *) {
OS << "self_maps";
}
void OMPClausePrinter::VisitOMPAtClause(OMPAtClause *Node) {
OS << "at(" << getOpenMPSimpleClauseTypeName(OMPC_at, Node->getAtKind())
<< ")";
}
void OMPClausePrinter::VisitOMPSeverityClause(OMPSeverityClause *Node) {
OS << "severity("
<< getOpenMPSimpleClauseTypeName(OMPC_severity, Node->getSeverityKind())
<< ")";
}
void OMPClausePrinter::VisitOMPMessageClause(OMPMessageClause *Node) {
OS << "message(\""
<< cast<StringLiteral>(Node->getMessageString())->getString() << "\")";
}
void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
OS << "schedule(";
if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
Node->getFirstScheduleModifier());
if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
OS << ", ";
OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
Node->getSecondScheduleModifier());
}
OS << ": ";
}
OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
if (auto *E = Node->getChunkSize()) {
OS << ", ";
E->printPretty(OS, nullptr, Policy);
}
OS << ")";
}
void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) {
OS << "ordered";
if (auto *Num = Node->getNumForLoops()) {
OS << "(";
Num->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
}
void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) {
OS << "nowait";
}
void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) {
OS << "untied";
}
void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) {
OS << "nogroup";
}
void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) {
OS << "mergeable";
}
void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; }
void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; }
void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *Node) {
OS << "update";
if (Node->isExtended()) {
OS << "(";
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
Node->getDependencyKind());
OS << ")";
}
}
void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) {
OS << "capture";
}
void OMPClausePrinter::VisitOMPCompareClause(OMPCompareClause *) {
OS << "compare";
}
void OMPClausePrinter::VisitOMPFailClause(OMPFailClause *Node) {
OS << "fail";
if (Node) {
OS << "(";
OS << getOpenMPSimpleClauseTypeName(
Node->getClauseKind(), static_cast<int>(Node->getFailParameter()));
OS << ")";
}
}
void OMPClausePrinter::VisitOMPAbsentClause(OMPAbsentClause *Node) {
OS << "absent(";
bool First = true;
for (auto &D : Node->getDirectiveKinds()) {
if (!First)
OS << ", ";
OS << getOpenMPDirectiveName(D, Version);
First = false;
}
OS << ")";
}
void OMPClausePrinter::VisitOMPHoldsClause(OMPHoldsClause *Node) {
OS << "holds(";
Node->getExpr()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPContainsClause(OMPContainsClause *Node) {
OS << "contains(";
bool First = true;
for (auto &D : Node->getDirectiveKinds()) {
if (!First)
OS << ", ";
OS << getOpenMPDirectiveName(D, Version);
First = false;
}
OS << ")";
}
void OMPClausePrinter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
OS << "no_openmp";
}
void OMPClausePrinter::VisitOMPNoOpenMPRoutinesClause(
OMPNoOpenMPRoutinesClause *) {
OS << "no_openmp_routines";
}
void OMPClausePrinter::VisitOMPNoOpenMPConstructsClause(
OMPNoOpenMPConstructsClause *) {
OS << "no_openmp_constructs";
}
void OMPClausePrinter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {
OS << "no_parallelism";
}
void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
void OMPClausePrinter::VisitOMPAcqRelClause(OMPAcqRelClause *) {
OS << "acq_rel";
}
void OMPClausePrinter::VisitOMPAcquireClause(OMPAcquireClause *) {
OS << "acquire";
}
void OMPClausePrinter::VisitOMPReleaseClause(OMPReleaseClause *) {
OS << "release";
}
void OMPClausePrinter::VisitOMPRelaxedClause(OMPRelaxedClause *) {
OS << "relaxed";
}
void OMPClausePrinter::VisitOMPWeakClause(OMPWeakClause *) { OS << "weak"; }
void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
OS << "threads";
}
void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
OS << "device(";
OpenMPDeviceClauseModifier Modifier = Node->getModifier();
if (Modifier != OMPC_DEVICE_unknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier)
<< ": ";
}
Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
if (!Node->varlist_empty()) {
OS << "num_teams";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) {
if (!Node->varlist_empty()) {
OS << "thread_limit";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) {
OS << "priority(";
Node->getPriority()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) {
OS << "grainsize(";
OpenMPGrainsizeClauseModifier Modifier = Node->getModifier();
if (Modifier != OMPC_GRAINSIZE_unknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier)
<< ": ";
}
Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) {
OS << "num_tasks(";
OpenMPNumTasksClauseModifier Modifier = Node->getModifier();
if (Modifier != OMPC_NUMTASKS_unknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier)
<< ": ";
}
Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
OS << "hint(";
Node->getHint()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPInitClause(OMPInitClause *Node) {
OS << "init(";
bool First = true;
for (const Expr *E : Node->prefs()) {
if (First)
OS << "prefer_type(";
else
OS << ",";
E->printPretty(OS, nullptr, Policy);
First = false;
}
if (!First)
OS << "), ";
if (Node->getIsTarget())
OS << "target";
if (Node->getIsTargetSync()) {
if (Node->getIsTarget())
OS << ", ";
OS << "targetsync";
}
OS << " : ";
Node->getInteropVar()->printPretty(OS, nullptr, Policy);
OS << ")";
}
void OMPClausePrinter::VisitOMPUseClause(OMPUseClause *Node) {
OS << "use(";
Node->getInteropVar()->printPretty(OS, nullptr, Policy);
OS << ")";
}
void OMPClausePrinter::VisitOMPDestroyClause(OMPDestroyClause *Node) {
OS << "destroy";
if (Expr *E = Node->getInteropVar()) {
OS << "(";
E->printPretty(OS, nullptr, Policy);
OS << ")";
}
}
void OMPClausePrinter::VisitOMPNovariantsClause(OMPNovariantsClause *Node) {
OS << "novariants";
if (Expr *E = Node->getCondition()) {
OS << "(";
E->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
}
void OMPClausePrinter::VisitOMPNocontextClause(OMPNocontextClause *Node) {
OS << "nocontext";
if (Expr *E = Node->getCondition()) {
OS << "(";
E->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
}
template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),
E = Node->varlist_end();
I != E; ++I) {
assert(*I && "Expected non-null Stmt");
OS << (I == Node->varlist_begin() ? StartSym : ',');
if (auto *DRE = dyn_cast<DeclRefExpr>(*I)) {
if (isa<OMPCapturedExprDecl>(DRE->getDecl()))
DRE->printPretty(OS, nullptr, Policy, 0);
else
DRE->getDecl()->printQualifiedName(OS);
} else
(*I)->printPretty(OS, nullptr, Policy, 0);
}
}
void OMPClausePrinter::VisitOMPAllocateClause(OMPAllocateClause *Node) {
if (Node->varlist_empty())
return;
Expr *FirstModifier = nullptr;
Expr *SecondModifier = nullptr;
auto FirstAllocMod = Node->getFirstAllocateModifier();
auto SecondAllocMod = Node->getSecondAllocateModifier();
bool FirstUnknown = FirstAllocMod == OMPC_ALLOCATE_unknown;
bool SecondUnknown = SecondAllocMod == OMPC_ALLOCATE_unknown;
if (FirstAllocMod == OMPC_ALLOCATE_allocator ||
(FirstAllocMod == OMPC_ALLOCATE_unknown && Node->getAllocator())) {
FirstModifier = Node->getAllocator();
SecondModifier = Node->getAlignment();
} else {
FirstModifier = Node->getAlignment();
SecondModifier = Node->getAllocator();
}
OS << "allocate";
// If we have any explicit modifiers.
if (FirstModifier) {
OS << "(";
if (!FirstUnknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), FirstAllocMod);
OS << "(";
}
FirstModifier->printPretty(OS, nullptr, Policy, 0);
if (!FirstUnknown)
OS << ")";
if (SecondModifier) {
OS << ", ";
if (!SecondUnknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
SecondAllocMod);
OS << "(";
}
SecondModifier->printPretty(OS, nullptr, Policy, 0);
if (!SecondUnknown)
OS << ")";
}
OS << ":";
VisitOMPClauseList(Node, ' ');
} else {
// No modifiers. Just print the variable list.
VisitOMPClauseList(Node, '(');
}
OS << ")";
}
void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) {
if (!Node->varlist_empty()) {
OS << "private";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) {
if (!Node->varlist_empty()) {
OS << "firstprivate";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) {
if (!Node->varlist_empty()) {
OS << "lastprivate";
OpenMPLastprivateModifier LPKind = Node->getKind();
if (LPKind != OMPC_LASTPRIVATE_unknown) {
OS << "("
<< getOpenMPSimpleClauseTypeName(OMPC_lastprivate, Node->getKind())
<< ":";
}
VisitOMPClauseList(Node, LPKind == OMPC_LASTPRIVATE_unknown ? '(' : ' ');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
if (!Node->varlist_empty()) {
OS << "shared";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "reduction(";
if (Node->getModifierLoc().isValid())
OS << getOpenMPSimpleClauseTypeName(OMPC_reduction, Node->getModifier())
<< ", ";
NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
VisitOMPClauseList(Node, ' ');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPTaskReductionClause(
OMPTaskReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "task_reduction(";
NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
VisitOMPClauseList(Node, ' ');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
if (!Node->varlist_empty()) {
OS << "in_reduction(";
NestedNameSpecifier Qualifier =
Node->getQualifierLoc().getNestedNameSpecifier();
OverloadedOperatorKind OOK =
Node->getNameInfo().getName().getCXXOverloadedOperator();
if (!Qualifier && OOK != OO_None) {
// Print reduction identifier in C format
OS << getOperatorSpelling(OOK);
} else {
// Use C++ format
Qualifier.print(OS, Policy);
OS << Node->getNameInfo();
}
OS << ":";
VisitOMPClauseList(Node, ' ');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
if (!Node->varlist_empty()) {
OS << "linear";
VisitOMPClauseList(Node, '(');
if (Node->getModifierLoc().isValid() || Node->getStep() != nullptr) {
OS << ": ";
}
if (Node->getModifierLoc().isValid()) {
OS << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier());
}
if (Node->getStep() != nullptr) {
if (Node->getModifierLoc().isValid()) {
OS << ", ";
}
OS << "step(";
Node->getStep()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
OS << ")";
}
}
void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) {
if (!Node->varlist_empty()) {
OS << "aligned";
VisitOMPClauseList(Node, '(');
if (Node->getAlignment() != nullptr) {
OS << ": ";
Node->getAlignment()->printPretty(OS, nullptr, Policy, 0);
}
OS << ")";
}
}
void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
if (!Node->varlist_empty()) {
OS << "copyin";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {
if (!Node->varlist_empty()) {
OS << "copyprivate";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
if (!Node->varlist_empty()) {
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPDepobjClause(OMPDepobjClause *Node) {
OS << "(";
Node->getDepobj()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
OS << "depend(";
if (Expr *DepModifier = Node->getModifier()) {
DepModifier->printPretty(OS, nullptr, Policy);
OS << ", ";
}
OpenMPDependClauseKind DepKind = Node->getDependencyKind();
OpenMPDependClauseKind PrintKind = DepKind;
bool IsOmpAllMemory = false;
if (PrintKind == OMPC_DEPEND_outallmemory) {
PrintKind = OMPC_DEPEND_out;
IsOmpAllMemory = true;
} else if (PrintKind == OMPC_DEPEND_inoutallmemory) {
PrintKind = OMPC_DEPEND_inout;
IsOmpAllMemory = true;
}
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), PrintKind);
if (!Node->varlist_empty() || IsOmpAllMemory)
OS << " :";
VisitOMPClauseList(Node, ' ');
if (IsOmpAllMemory) {
OS << (Node->varlist_empty() ? " " : ",");
OS << "omp_all_memory";
}
OS << ")";
}
template <typename T>
static void PrintMapper(raw_ostream &OS, T *Node,
const PrintingPolicy &Policy) {
OS << '(';
NestedNameSpecifier MapperNNS =
Node->getMapperQualifierLoc().getNestedNameSpecifier();
MapperNNS.print(OS, Policy);
OS << Node->getMapperIdInfo() << ')';
}
template <typename T>
static void PrintIterator(raw_ostream &OS, T *Node,
const PrintingPolicy &Policy) {
if (Expr *IteratorModifier = Node->getIteratorModifier())
IteratorModifier->printPretty(OS, nullptr, Policy);
}
void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
if (!Node->varlist_empty()) {
OS << "map(";
if (Node->getMapType() != OMPC_MAP_unknown) {
for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) {
if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) {
if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) {
PrintIterator(OS, Node, Policy);
} else {
OS << getOpenMPSimpleClauseTypeName(OMPC_map,
Node->getMapTypeModifier(I));
if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_mapper)
PrintMapper(OS, Node, Policy);
}
OS << ',';
}
}
OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType());
OS << ':';
}
VisitOMPClauseList(Node, ' ');
OS << ")";
}
}
template <typename T> void OMPClausePrinter::VisitOMPMotionClause(T *Node) {
if (Node->varlist_empty())
return;
OS << getOpenMPClauseName(Node->getClauseKind());
unsigned ModifierCount = 0;
for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {
if (Node->getMotionModifier(I) != OMPC_MOTION_MODIFIER_unknown)
++ModifierCount;
}
if (ModifierCount) {
OS << '(';
for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {
if (Node->getMotionModifier(I) != OMPC_MOTION_MODIFIER_unknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
Node->getMotionModifier(I));
if (Node->getMotionModifier(I) == OMPC_MOTION_MODIFIER_mapper)
PrintMapper(OS, Node, Policy);
if (I < ModifierCount - 1)
OS << ", ";
}
}
OS << ':';
VisitOMPClauseList(Node, ' ');
} else {
VisitOMPClauseList(Node, '(');
}
OS << ")";
}
void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) {
VisitOMPMotionClause(Node);
}
void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) {
VisitOMPMotionClause(Node);
}
void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
OMPC_dist_schedule, Node->getDistScheduleKind());
if (auto *E = Node->getChunkSize()) {
OS << ", ";
E->printPretty(OS, nullptr, Policy);
}
OS << ")";
}
void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) {
OS << "defaultmap(";
OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
Node->getDefaultmapModifier());
if (Node->getDefaultmapKind() != OMPC_DEFAULTMAP_unknown) {
OS << ": ";
OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
Node->getDefaultmapKind());
}
OS << ")";
}
void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) {
if (!Node->varlist_empty()) {
OS << "use_device_ptr";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPUseDeviceAddrClause(
OMPUseDeviceAddrClause *Node) {
if (!Node->varlist_empty()) {
OS << "use_device_addr";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) {
if (!Node->varlist_empty()) {
OS << "is_device_ptr";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *Node) {
if (!Node->varlist_empty()) {
OS << "has_device_addr";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPNontemporalClause(OMPNontemporalClause *Node) {
if (!Node->varlist_empty()) {
OS << "nontemporal";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPOrderClause(OMPOrderClause *Node) {
OS << "order(";
if (Node->getModifier() != OMPC_ORDER_MODIFIER_unknown) {
OS << getOpenMPSimpleClauseTypeName(OMPC_order, Node->getModifier());
OS << ": ";
}
OS << getOpenMPSimpleClauseTypeName(OMPC_order, Node->getKind()) << ")";
}
void OMPClausePrinter::VisitOMPInclusiveClause(OMPInclusiveClause *Node) {
if (!Node->varlist_empty()) {
OS << "inclusive";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPExclusiveClause(OMPExclusiveClause *Node) {
if (!Node->varlist_empty()) {
OS << "exclusive";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}
void OMPClausePrinter::VisitOMPUsesAllocatorsClause(
OMPUsesAllocatorsClause *Node) {
if (Node->getNumberOfAllocators() == 0)
return;
OS << "uses_allocators(";
for (unsigned I = 0, E = Node->getNumberOfAllocators(); I < E; ++I) {
OMPUsesAllocatorsClause::Data Data = Node->getAllocatorData(I);
Data.Allocator->printPretty(OS, nullptr, Policy);
if (Data.AllocatorTraits) {
OS << "(";
Data.AllocatorTraits->printPretty(OS, nullptr, Policy);
OS << ")";
}
if (I < E - 1)
OS << ",";
}
OS << ")";
}
void OMPClausePrinter::VisitOMPAffinityClause(OMPAffinityClause *Node) {
if (Node->varlist_empty())
return;
OS << "affinity";
char StartSym = '(';
if (Expr *Modifier = Node->getModifier()) {
OS << "(";
Modifier->printPretty(OS, nullptr, Policy);
OS << " :";
StartSym = ' ';
}
VisitOMPClauseList(Node, StartSym);
OS << ")";
}
void OMPClausePrinter::VisitOMPFilterClause(OMPFilterClause *Node) {
OS << "filter(";
Node->getThreadID()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPBindClause(OMPBindClause *Node) {
OS << "bind("
<< getOpenMPSimpleClauseTypeName(OMPC_bind, unsigned(Node->getBindKind()))
<< ")";
}
void OMPClausePrinter::VisitOMPXDynCGroupMemClause(
OMPXDynCGroupMemClause *Node) {
OS << "ompx_dyn_cgroup_mem(";
Node->getSize()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPDoacrossClause(OMPDoacrossClause *Node) {
OS << "doacross(";
OpenMPDoacrossClauseModifier DepType = Node->getDependenceType();
switch (DepType) {
case OMPC_DOACROSS_source:
OS << "source:";
break;
case OMPC_DOACROSS_sink:
OS << "sink:";
break;
case OMPC_DOACROSS_source_omp_cur_iteration:
OS << "source: omp_cur_iteration";
break;
case OMPC_DOACROSS_sink_omp_cur_iteration:
OS << "sink: omp_cur_iteration - 1";
break;
default:
llvm_unreachable("unknown docaross modifier");
}
VisitOMPClauseList(Node, ' ');
OS << ")";
}
void OMPClausePrinter::VisitOMPXAttributeClause(OMPXAttributeClause *Node) {
OS << "ompx_attribute(";
bool IsFirst = true;
for (auto &Attr : Node->getAttrs()) {
if (!IsFirst)
OS << ", ";
Attr->printPretty(OS, Policy);
IsFirst = false;
}
OS << ")";
}
void OMPClausePrinter::VisitOMPXBareClause(OMPXBareClause *Node) {
OS << "ompx_bare";
}
void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
VariantMatchInfo &VMI) const {
for (const OMPTraitSet &Set : Sets) {
for (const OMPTraitSelector &Selector : Set.Selectors) {
// User conditions are special as we evaluate the condition here.
if (Selector.Kind == TraitSelector::user_condition) {
assert(Selector.ScoreOrCondition &&
"Ill-formed user condition, expected condition expression!");
assert(Selector.Properties.size() == 1 &&
Selector.Properties.front().Kind ==
TraitProperty::user_condition_unknown &&
"Ill-formed user condition, expected unknown trait property!");
if (std::optional<APSInt> CondVal =
Selector.ScoreOrCondition->getIntegerConstantExpr(ASTCtx))
VMI.addTrait(CondVal->isZero() ? TraitProperty::user_condition_false
: TraitProperty::user_condition_true,
"<condition>");
else
VMI.addTrait(TraitProperty::user_condition_false, "<condition>");
continue;
}
std::optional<llvm::APSInt> Score;
llvm::APInt *ScorePtr = nullptr;
if (Selector.ScoreOrCondition) {
if ((Score = Selector.ScoreOrCondition->getIntegerConstantExpr(ASTCtx)))
ScorePtr = &*Score;
else
VMI.addTrait(TraitProperty::user_condition_false,
"<non-constant-score>");
}
for (const OMPTraitProperty &Property : Selector.Properties)
VMI.addTrait(Set.Kind, Property.Kind, Property.RawString, ScorePtr);
if (Set.Kind != TraitSet::construct)
continue;
// TODO: This might not hold once we implement SIMD properly.
assert(Selector.Properties.size() == 1 &&
Selector.Properties.front().Kind ==
getOpenMPContextTraitPropertyForSelector(
Selector.Kind) &&
"Ill-formed construct selector!");
}
}
}
void OMPTraitInfo::print(llvm::raw_ostream &OS,
const PrintingPolicy &Policy) const {
bool FirstSet = true;
for (const OMPTraitSet &Set : Sets) {
if (!FirstSet)
OS << ", ";
FirstSet = false;
OS << getOpenMPContextTraitSetName(Set.Kind) << "={";
bool FirstSelector = true;
for (const OMPTraitSelector &Selector : Set.Selectors) {
if (!FirstSelector)
OS << ", ";
FirstSelector = false;
OS << getOpenMPContextTraitSelectorName(Selector.Kind);
bool AllowsTraitScore = false;
bool RequiresProperty = false;
isValidTraitSelectorForTraitSet(
Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty);
if (!RequiresProperty)
continue;
OS << "(";
if (Selector.Kind == TraitSelector::user_condition) {
if (Selector.ScoreOrCondition)
Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy);
else
OS << "...";
} else {
if (Selector.ScoreOrCondition) {
OS << "score(";
Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy);
OS << "): ";
}
bool FirstProperty = true;
for (const OMPTraitProperty &Property : Selector.Properties) {
if (!FirstProperty)
OS << ", ";
FirstProperty = false;
OS << getOpenMPContextTraitPropertyName(Property.Kind,
Property.RawString);
}
}
OS << ")";
}
OS << "}";
}
}
std::string OMPTraitInfo::getMangledName() const {
std::string MangledName;
llvm::raw_string_ostream OS(MangledName);
for (const OMPTraitSet &Set : Sets) {
OS << '$' << 'S' << unsigned(Set.Kind);
for (const OMPTraitSelector &Selector : Set.Selectors) {
bool AllowsTraitScore = false;
bool RequiresProperty = false;
isValidTraitSelectorForTraitSet(
Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty);
OS << '$' << 's' << unsigned(Selector.Kind);
if (!RequiresProperty ||
Selector.Kind == TraitSelector::user_condition)
continue;
for (const OMPTraitProperty &Property : Selector.Properties)
OS << '$' << 'P'
<< getOpenMPContextTraitPropertyName(Property.Kind,
Property.RawString);
}
}
return MangledName;
}
OMPTraitInfo::OMPTraitInfo(StringRef MangledName) {
unsigned long U;
do {
if (!MangledName.consume_front("$S"))
break;
if (MangledName.consumeInteger(10, U))
break;
Sets.push_back(OMPTraitSet());
OMPTraitSet &Set = Sets.back();
Set.Kind = TraitSet(U);
do {
if (!MangledName.consume_front("$s"))
break;
if (MangledName.consumeInteger(10, U))
break;
Set.Selectors.push_back(OMPTraitSelector());
OMPTraitSelector &Selector = Set.Selectors.back();
Selector.Kind = TraitSelector(U);
do {
if (!MangledName.consume_front("$P"))
break;
Selector.Properties.push_back(OMPTraitProperty());
OMPTraitProperty &Property = Selector.Properties.back();
std::pair<StringRef, StringRef> PropRestPair = MangledName.split('$');
Property.RawString = PropRestPair.first;
Property.Kind = getOpenMPContextTraitPropertyKind(
Set.Kind, Selector.Kind, PropRestPair.first);
MangledName = MangledName.drop_front(PropRestPair.first.size());
} while (true);
} while (true);
} while (true);
}
llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
const OMPTraitInfo &TI) {
LangOptions LO;
PrintingPolicy Policy(LO);
TI.print(OS, Policy);
return OS;
}
llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
const OMPTraitInfo *TI) {
return TI ? OS << *TI : OS;
}
TargetOMPContext::TargetOMPContext(
ASTContext &ASTCtx, std::function<void(StringRef)> &&DiagUnknownTrait,
const FunctionDecl *CurrentFunctionDecl,
ArrayRef<llvm::omp::TraitProperty> ConstructTraits, int DeviceNum)
: OMPContext(ASTCtx.getLangOpts().OpenMPIsTargetDevice,
ASTCtx.getTargetInfo().getTriple(),
ASTCtx.getLangOpts().OMPTargetTriples.empty()
? llvm::Triple()
: ASTCtx.getLangOpts().OMPTargetTriples[0],
DeviceNum),
FeatureValidityCheck([&](StringRef FeatureName) {
return ASTCtx.getTargetInfo().isValidFeatureName(FeatureName);
}),
DiagUnknownTrait(std::move(DiagUnknownTrait)) {
ASTCtx.getFunctionFeatureMap(FeatureMap, CurrentFunctionDecl);
for (llvm::omp::TraitProperty Property : ConstructTraits)
addTrait(Property);
}
bool TargetOMPContext::matchesISATrait(StringRef RawString) const {
auto It = FeatureMap.find(RawString);
if (It != FeatureMap.end())
return It->second;
if (!FeatureValidityCheck(RawString))
DiagUnknownTrait(RawString);
return false;
}