[flang-commits] [flang] 0ac2b88 - [flang][OpenMP] Lower align modifiers on allocate clauses (#211624)
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 4 04:02:13 PDT 2026
Author: Sairudra More
Date: 2026-08-04T16:32:03+05:30
New Revision: 0ac2b88c53c08f405866ed0ca78be7e423ed0109
URL: https://github.com/llvm/llvm-project/commit/0ac2b88c53c08f405866ed0ca78be7e423ed0109
DIFF: https://github.com/llvm/llvm-project/commit/0ac2b88c53c08f405866ed0ca78be7e423ed0109.diff
LOG: [flang][OpenMP] Lower align modifiers on allocate clauses (#211624)
Closes #211620.
Stacked on #211621.
This adds `align` modifier lowering to the host `omp.parallel` path
introduced by the parent change. It carries and verifies per-item
alignment metadata and uses aligned runtime allocation when alignment is
specified, while retaining the unaligned path otherwise.
Other clause-bearing constructs and unsupported data types remain out of
scope.
Assisted-by: Copilot
Added:
Modified:
flang/lib/Lower/OpenMP/ClauseProcessor.cpp
flang/lib/Lower/OpenMP/ClauseProcessor.h
flang/lib/Lower/OpenMP/OpenMP.cpp
flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
flang/lib/Semantics/check-omp-structure.cpp
flang/test/Lower/OpenMP/Todo/allocate-clause-unsupported.f90
flang/test/Lower/OpenMP/allocate-clause-allocator.f90
flang/test/Semantics/OpenMP/allocate-clause01.f90
flang/test/Transforms/OpenMP/lower-workdistribute-fission-target.mlir
mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
mlir/test/Dialect/OpenMP/host-op-filtering.mlir
mlir/test/Dialect/OpenMP/invalid.mlir
mlir/test/Dialect/OpenMP/ops.mlir
mlir/test/Target/LLVMIR/openmp-allocate-clause.mlir
Removed:
flang/test/Lower/OpenMP/Todo/allocate-clause-align.f90
################################################################################
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index f912c2af15d67..2f45b70db8fe6 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -94,11 +94,11 @@ getSimdModifier(const omp::clause::Schedule &clause) {
return mlir::omp::ScheduleModifier::none;
}
-static void
-genAllocateClause(lower::AbstractConverter &converter,
- const omp::clause::Allocate &clause,
- llvm::SmallVectorImpl<mlir::Value> &allocatorOperands,
- llvm::SmallVectorImpl<mlir::Value> &allocateOperands) {
+static void genAllocateClause(
+ lower::AbstractConverter &converter, const omp::clause::Allocate &clause,
+ llvm::SmallVectorImpl<mlir::Value> &allocatorOperands,
+ llvm::SmallVectorImpl<mlir::Value> &allocateOperands,
+ llvm::SmallVectorImpl<int64_t> &alignments, bool supportAlignment) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
mlir::Location currentLocation = converter.getCurrentLocation();
lower::StatementContext stmtCtx;
@@ -106,10 +106,18 @@ genAllocateClause(lower::AbstractConverter &converter,
auto &objects = std::get<omp::ObjectList>(clause.t);
using Allocate = omp::clause::Allocate;
- // ALIGN in this context is unimplemented
- if (std::get<std::optional<Allocate::AlignModifier>>(clause.t))
+ auto &align = std::get<std::optional<Allocate::AlignModifier>>(clause.t);
+ if (align && !supportAlignment)
TODO(currentLocation, "OmpAllocateClause ALIGN modifier");
+ if (align) {
+ if (alignments.empty())
+ alignments.resize(allocateOperands.size(), 0);
+ alignments.append(objects.size(), evaluate::ToInt64(align->v).value());
+ } else if (!alignments.empty()) {
+ alignments.append(objects.size(), 0);
+ }
+
// Use a null handle to select the binding task's default allocator.
using ComplexModifier = Allocate::AllocatorComplexModifier;
if (auto &mod = std::get<std::optional<ComplexModifier>>(clause.t)) {
@@ -1136,12 +1144,13 @@ bool ClauseProcessor::processAligned(
});
}
-bool ClauseProcessor::processAllocate(
- mlir::omp::AllocateClauseOps &result) const {
+bool ClauseProcessor::processAllocate(mlir::omp::AllocateClauseOps &result,
+ bool supportAlignment) const {
return findRepeatableClause<omp::clause::Allocate>(
[&](const omp::clause::Allocate &clause, const parser::CharBlock &) {
genAllocateClause(converter, clause, result.allocatorVars,
- result.allocateVars);
+ result.allocateVars, result.allocateAlignments,
+ supportAlignment);
});
}
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index cb42b6524e2e7..2a78cd52ee633 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -129,7 +129,8 @@ class ClauseProcessor {
// 'Repeatable' clauses: They can appear multiple times in the clause list.
bool processAffinity(mlir::omp::AffinityClauseOps &result) const;
bool processAligned(mlir::omp::AlignedClauseOps &result) const;
- bool processAllocate(mlir::omp::AllocateClauseOps &result) const;
+ bool processAllocate(mlir::omp::AllocateClauseOps &result,
+ bool supportAlignment = false) const;
bool processCopyin() const;
bool processCopyprivate(mlir::Location currentLocation,
mlir::omp::CopyprivateClauseOps &result) const;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 1ac2d254d14e9..3876799b3a081 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2544,7 +2544,7 @@ static void genParallelClauses(
mlir::Location loc, mlir::omp::ParallelOperands &clauseOps,
llvm::SmallVectorImpl<Object> &reductionObjects) {
ClauseProcessor cp(converter, semaCtx, clauses);
- cp.processAllocate(clauseOps);
+ cp.processAllocate(clauseOps, /*supportAlignment=*/true);
cp.processIf(llvm::omp::Directive::OMPD_parallel, clauseOps);
HostEvalInfo *hostEvalInfo = getHostEvalInfoStackTop(converter);
diff --git a/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp b/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
index 5c42632d0c5fb..68e997e3abde4 100644
--- a/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
+++ b/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
@@ -757,10 +757,11 @@ FailureOr<omp::TargetOp> splitTargetData(omp::TargetOp targetOp,
// Create the inner target op
auto newTargetOp = omp::TargetOp::create(
rewriter, targetOp.getLoc(), targetOp.getAllocateVars(),
- targetOp.getAllocatorVars(), targetOp.getAllocatePrivateIndicesAttr(),
- targetOp.getDependKindsAttr(), targetOp.getDependVars(),
- targetOp.getDependIteratedKindsAttr(), targetOp.getDependIterated(),
- targetOp.getDevice(), targetOp.getDynGroupprivateAccessGroupAttr(),
+ targetOp.getAllocatorVars(), targetOp.getAllocateAlignmentsAttr(),
+ targetOp.getAllocatePrivateIndicesAttr(), targetOp.getDependKindsAttr(),
+ targetOp.getDependVars(), targetOp.getDependIteratedKindsAttr(),
+ targetOp.getDependIterated(), targetOp.getDevice(),
+ targetOp.getDynGroupprivateAccessGroupAttr(),
targetOp.getDynGroupprivateFallbackAttr(),
targetOp.getDynGroupprivateSize(), targetOp.getHasDeviceAddrVars(),
targetOp.getHostEvalVars(), targetOp.getIfExpr(),
@@ -1482,10 +1483,11 @@ genPreTargetOp(omp::TargetOp targetOp, SmallVector<Value> &preMapOperands,
// update the hostEvalVars of preTargetOp
omp::TargetOp preTargetOp = omp::TargetOp::create(
rewriter, targetOp.getLoc(), targetOp.getAllocateVars(),
- targetOp.getAllocatorVars(), targetOp.getAllocatePrivateIndicesAttr(),
- targetOp.getDependKindsAttr(), targetOp.getDependVars(),
- targetOp.getDependIteratedKindsAttr(), targetOp.getDependIterated(),
- targetOp.getDevice(), targetOp.getDynGroupprivateAccessGroupAttr(),
+ targetOp.getAllocatorVars(), targetOp.getAllocateAlignmentsAttr(),
+ targetOp.getAllocatePrivateIndicesAttr(), targetOp.getDependKindsAttr(),
+ targetOp.getDependVars(), targetOp.getDependIteratedKindsAttr(),
+ targetOp.getDependIterated(), targetOp.getDevice(),
+ targetOp.getDynGroupprivateAccessGroupAttr(),
targetOp.getDynGroupprivateFallbackAttr(),
targetOp.getDynGroupprivateSize(), targetOp.getHasDeviceAddrVars(),
preHostEvalVars, targetOp.getIfExpr(), targetOp.getInReductionVars(),
@@ -1576,10 +1578,11 @@ genIsolatedTargetOp(omp::TargetOp targetOp, SmallVector<Value> &postMapOperands,
// Create the isolated target op
omp::TargetOp isolatedTargetOp = omp::TargetOp::create(
rewriter, targetOp.getLoc(), targetOp.getAllocateVars(),
- targetOp.getAllocatorVars(), targetOp.getAllocatePrivateIndicesAttr(),
- targetOp.getDependKindsAttr(), targetOp.getDependVars(),
- targetOp.getDependIteratedKindsAttr(), targetOp.getDependIterated(),
- targetOp.getDevice(), targetOp.getDynGroupprivateAccessGroupAttr(),
+ targetOp.getAllocatorVars(), targetOp.getAllocateAlignmentsAttr(),
+ targetOp.getAllocatePrivateIndicesAttr(), targetOp.getDependKindsAttr(),
+ targetOp.getDependVars(), targetOp.getDependIteratedKindsAttr(),
+ targetOp.getDependIterated(), targetOp.getDevice(),
+ targetOp.getDynGroupprivateAccessGroupAttr(),
targetOp.getDynGroupprivateFallbackAttr(),
targetOp.getDynGroupprivateSize(), targetOp.getHasDeviceAddrVars(),
isolatedHostEvalVars, targetOp.getIfExpr(), targetOp.getInReductionVars(),
@@ -1662,10 +1665,11 @@ static omp::TargetOp genPostTargetOp(omp::TargetOp targetOp,
// Create the post target op
omp::TargetOp postTargetOp = omp::TargetOp::create(
rewriter, targetOp.getLoc(), targetOp.getAllocateVars(),
- targetOp.getAllocatorVars(), targetOp.getAllocatePrivateIndicesAttr(),
- targetOp.getDependKindsAttr(), targetOp.getDependVars(),
- targetOp.getDependIteratedKindsAttr(), targetOp.getDependIterated(),
- targetOp.getDevice(), targetOp.getDynGroupprivateAccessGroupAttr(),
+ targetOp.getAllocatorVars(), targetOp.getAllocateAlignmentsAttr(),
+ targetOp.getAllocatePrivateIndicesAttr(), targetOp.getDependKindsAttr(),
+ targetOp.getDependVars(), targetOp.getDependIteratedKindsAttr(),
+ targetOp.getDependIterated(), targetOp.getDevice(),
+ targetOp.getDynGroupprivateAccessGroupAttr(),
targetOp.getDynGroupprivateFallbackAttr(),
targetOp.getDynGroupprivateSize(), targetOp.getHasDeviceAddrVars(),
postHostEvalVars, targetOp.getIfExpr(), targetOp.getInReductionVars(),
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 8e845fbf5993b..7bd5f1720fb3c 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2488,6 +2488,9 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
if (const auto &v{GetIntValue(align->v)}; !v || *v <= 0) {
context_.Say(OmpGetModifierSource(modifiers, align),
"The alignment value should be a constant positive integer"_err_en_US);
+ } else if (!llvm::isPowerOf2_64(*v)) {
+ context_.Say(OmpGetModifierSource(modifiers, align),
+ "The alignment value should be a power of 2"_err_en_US);
}
}
}
diff --git a/flang/test/Lower/OpenMP/Todo/allocate-clause-align.f90 b/flang/test/Lower/OpenMP/Todo/allocate-clause-align.f90
deleted file mode 100644
index b272d2e76d70c..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/allocate-clause-align.f90
+++ /dev/null
@@ -1,13 +0,0 @@
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: OmpAllocateClause ALIGN modifier
-program p
- integer :: x
- integer :: a
- integer :: i
- !$omp parallel private(x) allocate(align(4): x)
- do i=1,10
- a = a + i
- end do
- !$omp end parallel
-end program p
diff --git a/flang/test/Lower/OpenMP/Todo/allocate-clause-unsupported.f90 b/flang/test/Lower/OpenMP/Todo/allocate-clause-unsupported.f90
index 82b82fa6c33f1..72e83c6967642 100644
--- a/flang/test/Lower/OpenMP/Todo/allocate-clause-unsupported.f90
+++ b/flang/test/Lower/OpenMP/Todo/allocate-clause-unsupported.f90
@@ -5,6 +5,7 @@
! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=51 -o - %t/pointer.f90 2>&1 | FileCheck %s --check-prefix=POINTER
! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=51 -o - %t/allocatable.f90 2>&1 | FileCheck %s --check-prefix=ALLOCATABLE
! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=51 -o - %t/assumed-length.f90 2>&1 | FileCheck %s --check-prefix=ASSUMED-LENGTH
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=51 -o - %t/non-parallel.f90 2>&1 | FileCheck %s --check-prefix=NON-PARALLEL
! DUPLICATE: not yet implemented: ALLOCATE clause item appears more than once
! ARRAY: not yet implemented: ALLOCATE clause currently supports only fixed-size intrinsic scalar PRIVATE or FIRSTPRIVATE items
@@ -12,6 +13,7 @@
! POINTER: not yet implemented: ALLOCATE clause currently supports only fixed-size intrinsic scalar PRIVATE or FIRSTPRIVATE items
! ALLOCATABLE: not yet implemented: ALLOCATE clause currently supports only fixed-size intrinsic scalar PRIVATE or FIRSTPRIVATE items
! ASSUMED-LENGTH: not yet implemented: ALLOCATE clause currently supports only fixed-size intrinsic scalar PRIVATE or FIRSTPRIVATE items
+! NON-PARALLEL: not yet implemented: OmpAllocateClause ALIGN modifier
!--- duplicate.f90
subroutine duplicate(x)
@@ -29,6 +31,14 @@ subroutine pointer(x)
!$omp end parallel
end subroutine
+!--- non-parallel.f90
+subroutine non_parallel(x)
+ integer :: x
+ !$omp task private(x) allocate(align(64): x)
+ x = 1
+ !$omp end task
+end subroutine
+
!--- allocatable.f90
subroutine allocatable(x)
integer, allocatable :: x
@@ -48,7 +58,7 @@ subroutine assumed_length(x)
!--- array.f90
subroutine array(x)
integer :: x(4)
- !$omp parallel private(x) allocate(x)
+ !$omp parallel private(x) allocate(align(64): x)
x = 1
!$omp end parallel
end subroutine
diff --git a/flang/test/Lower/OpenMP/allocate-clause-allocator.f90 b/flang/test/Lower/OpenMP/allocate-clause-allocator.f90
index 79f8554dbdbda..09ac3993f5cec 100644
--- a/flang/test/Lower/OpenMP/allocate-clause-allocator.f90
+++ b/flang/test/Lower/OpenMP/allocate-clause-allocator.f90
@@ -135,3 +135,22 @@ subroutine allocator_common_block(y)
! HLFIR-SAME: private({{.*}} -> %{{.*}}, {{.*}} -> %{{.*}}, {{.*}} %[[Y]]#0 -> %{{.*}} :
! HLFIR-SAME: !fir.ref<i32>, !fir.ref<i32>, !fir.ref<i32>) {
! HLFIR: } {allocate_private_indices = array<i64: 2>}
+
+subroutine allocator_alignment(x, y, z, w)
+ use omp_lib
+ integer :: x, y, z, w
+ !$omp parallel private(x, y, z) firstprivate(w) &
+ !$omp& allocate(x) &
+ !$omp& allocate(align(64): y, z) &
+ !$omp& allocate(allocator(omp_default_mem_alloc), align(128): w)
+ x = 1
+ y = 2
+ z = 3
+ w = w + 1
+ !$omp end parallel
+end subroutine
+
+! HLFIR-LABEL: func.func @_QPallocator_alignment
+! HLFIR: omp.parallel allocate(
+! HLFIR-SAME: private(
+! HLFIR: } {allocate_alignments = array<i64: 0, 64, 64, 128>, allocate_private_indices = array<i64: 0, 1, 2, 3>}
diff --git a/flang/test/Semantics/OpenMP/allocate-clause01.f90 b/flang/test/Semantics/OpenMP/allocate-clause01.f90
index b84b13df5aab0..d5e22871943fb 100644
--- a/flang/test/Semantics/OpenMP/allocate-clause01.f90
+++ b/flang/test/Semantics/OpenMP/allocate-clause01.f90
@@ -34,3 +34,28 @@ subroutine parallel_allocate(x, y)
x = y
!$omp end parallel
end subroutine
+
+subroutine parallel_allocate_align(x, alignment)
+ integer, parameter :: cache_line = 64
+ integer :: x, alignment
+
+ !$omp parallel private(x) allocate(align(cache_line): x)
+ x = 1
+ !$omp end parallel
+
+ !ERROR: The alignment value should be a constant positive integer
+ !$omp parallel private(x) allocate(align(0): x)
+ !$omp end parallel
+
+ !ERROR: The alignment value should be a constant positive integer
+ !$omp parallel private(x) allocate(align(-4): x)
+ !$omp end parallel
+
+ !ERROR: The alignment value should be a constant positive integer
+ !$omp parallel private(x) allocate(align(alignment): x)
+ !$omp end parallel
+
+ !ERROR: The alignment value should be a power of 2
+ !$omp parallel private(x) allocate(align(24): x)
+ !$omp end parallel
+end subroutine
diff --git a/flang/test/Transforms/OpenMP/lower-workdistribute-fission-target.mlir b/flang/test/Transforms/OpenMP/lower-workdistribute-fission-target.mlir
index 4efc02e07c6d0..7354c89dfa321 100644
--- a/flang/test/Transforms/OpenMP/lower-workdistribute-fission-target.mlir
+++ b/flang/test/Transforms/OpenMP/lower-workdistribute-fission-target.mlir
@@ -62,7 +62,7 @@
// CHECK: omp.terminator
// CHECK: } {omp.combined}
// CHECK: omp.terminator
-// CHECK: } {allocate_private_indices = array<i64: 0>, omp.combined}
+// CHECK: } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>, omp.combined}
// CHECK: %[[VAL_45:.*]] = llvm.mlir.constant(0 : i32) : i32
// CHECK: %[[VAL_46:.*]] = fir.load %[[VAL_11]] : !fir.ref<index>
// CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_14]] : !fir.ref<index>
@@ -96,6 +96,7 @@ func.func @x(%lb : index, %ub : index, %step : index, %addr : !fir.ref<index>) {
"omp.target"(%addr, %allocator, %lb_map, %ub_map, %step_map, %addr_map, %addr) <{
allocate_private_indices = array<i64: 0>,
+ allocate_alignments = array<i64: 64>,
kernel_type = #omp<kernel_type(generic)>,
operandSegmentSizes = array<i32: 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0>,
private_syms = [@addr_private]
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index b6637d6df90e5..22296338b7915 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -114,6 +114,7 @@ class OpenMP_AllocateClauseSkip<
let arguments = (ins
Variadic<AnyType>:$allocate_vars,
Variadic<AnyType>:$allocator_vars,
+ OptionalAttr<DenseI64ArrayAttr>:$allocate_alignments,
OptionalAttr<DenseI64ArrayAttr>:$allocate_private_indices
);
@@ -131,8 +132,11 @@ class OpenMP_AllocateClauseSkip<
let description = [{
The `allocate_vars` and `allocator_vars` parameters are parallel lists that
pair each allocated private value with the allocator used to obtain its
- storage. When present, `allocate_private_indices` maps each allocate variable
- to the corresponding position in the operation's private variables.
+ storage. When present, `allocate_alignments` has one entry per allocate
+ variable; zero means omitted alignment, and nonzero entries must be powers
+ of two.
+ `allocate_private_indices` maps each allocate variable to the corresponding
+ position in the operation's private variables.
}];
}
diff --git a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp
index bdc428fc289f4..37a2b5046096a 100644
--- a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp
+++ b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp
@@ -503,6 +503,7 @@ struct ParallelOpLowering : public OpRewritePattern<scf::ParallelOp> {
rewriter, loc,
/* allocate_vars = */ llvm::SmallVector<Value>{},
/* allocator_vars = */ llvm::SmallVector<Value>{},
+ /* allocate_alignments = */ nullptr,
/* allocate_private_indices = */ nullptr,
/* if_expr = */ Value{},
/* num_threads_vars = */ numThreadsVars,
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 190014f2bab89..d941b62d13414 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -622,6 +622,7 @@ static void printAlignedClause(OpAsmPrinter &p, Operation *op,
static LogicalResult verifyAllocateClause(
Operation *op, ValueRange allocateVars, ValueRange allocatorVars,
+ DenseI64ArrayAttr allocateAlignments,
DenseI64ArrayAttr allocatePrivateIndices, ValueRange privateVars = {},
ArrayAttr privateSyms = nullptr, bool requirePrivateIndices = false) {
if (allocateVars.size() != allocatorVars.size())
@@ -629,12 +630,29 @@ static LogicalResult verifyAllocateClause(
"expected equal sizes for allocate and allocator variables");
if (allocateVars.empty()) {
+ if (allocateAlignments)
+ return op->emitError(
+ "unexpected allocate alignments without allocate variables");
if (allocatePrivateIndices)
return op->emitError(
"unexpected allocate private indices without allocate variables");
return success();
}
+ if (allocateAlignments) {
+ ArrayRef<int64_t> alignments = allocateAlignments.asArrayRef();
+ if (alignments.size() != allocateVars.size())
+ return op->emitError(
+ "expected as many allocate alignments as allocate variables");
+ for (int64_t alignment : alignments) {
+ if (alignment < 0)
+ return op->emitError("expected non-negative allocate alignments");
+ if (alignment != 0 && (alignment & (alignment - 1)) != 0)
+ return op->emitError(
+ "expected positive allocate alignments to be powers of two");
+ }
+ }
+
if (!allocatePrivateIndices) {
if (requirePrivateIndices)
return op->emitError(
@@ -2718,6 +2736,7 @@ void TargetOp::build(OpBuilder &builder, OperationState &state,
MLIRContext *ctx = builder.getContext();
TargetOp::build(
builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
makeArrayAttr(ctx, clauses.dependKinds), clauses.dependVars,
makeArrayAttr(ctx, clauses.dependIteratedKinds), clauses.dependIterated,
@@ -2783,10 +2802,10 @@ static bool targetInReductionCapturedBy(Value inReductionVar, Value mapVarPtr) {
}
LogicalResult TargetOp::verify() {
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
if (getKernelType() == TargetExecMode::bare && !isCombined())
@@ -2935,6 +2954,7 @@ void ParallelOp::build(OpBuilder &builder, OperationState &state,
ArrayRef<NamedAttribute> attributes) {
ParallelOp::build(builder, state, /*allocate_vars=*/ValueRange(),
/*allocator_vars=*/ValueRange(),
+ /*allocate_alignments=*/nullptr,
/*allocate_private_indices=*/nullptr, /*if_expr=*/nullptr,
/*num_threads_vars=*/ValueRange(),
/*private_vars=*/ValueRange(),
@@ -2949,6 +2969,7 @@ void ParallelOp::build(OpBuilder &builder, OperationState &state,
const ParallelOperands &clauses) {
MLIRContext *ctx = builder.getContext();
ParallelOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
clauses.ifExpr, clauses.numThreadsVars, clauses.privateVars,
makeArrayAttr(ctx, clauses.privateSyms),
@@ -3006,8 +3027,9 @@ LogicalResult ParallelOp::verify() {
return failure();
if (failed(verifyAllocateClause(
getOperation(), getAllocateVars(), getAllocatorVars(),
- getAllocatePrivateIndicesAttr(), getPrivateVars(),
- getPrivateSymsAttr(), /*requirePrivateIndices=*/true)))
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr(),
+ /*requirePrivateIndices=*/true)))
return failure();
return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
@@ -3061,6 +3083,7 @@ void TeamsOp::build(OpBuilder &builder, OperationState &state,
// TODO Store clauses in op: privateVars, privateSyms, privateNeedsBarrier
TeamsOp::build(
builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
clauses.dynGroupprivateAccessGroup, clauses.dynGroupprivateFallback,
clauses.dynGroupprivateSize, clauses.ifExpr, clauses.numTeamsLower,
@@ -3111,10 +3134,10 @@ LogicalResult TeamsOp::verify() {
(getNumTeamsLower() || !getNumTeamsUpperVars().empty()))
return emitOpError() << "'num_teams' not allowed in SPMD-no-loop kernels";
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
if (failed(verifyDynGroupprivateClause(
@@ -3150,6 +3173,7 @@ void SectionsOp::build(OpBuilder &builder, OperationState &state,
MLIRContext *ctx = builder.getContext();
// TODO Store clauses in op: privateVars, privateSyms, privateNeedsBarrier
SectionsOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
clauses.nowait, /*private_vars=*/{},
/*private_syms=*/nullptr, /*private_needs_barrier=*/nullptr,
@@ -3162,10 +3186,10 @@ LogicalResult SectionsOp::verify() {
if (isCombined())
return emitOpError() << "cannot be a non-innermost combined construct leaf";
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
@@ -3191,6 +3215,7 @@ void ScopeOp::build(OpBuilder &builder, OperationState &state,
const ScopeOperands &clauses) {
MLIRContext *ctx = builder.getContext();
ScopeOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
clauses.nowait, clauses.privateVars,
makeArrayAttr(ctx, clauses.privateSyms),
@@ -3201,10 +3226,10 @@ void ScopeOp::build(OpBuilder &builder, OperationState &state,
}
LogicalResult ScopeOp::verify() {
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
if (failed(verifyPrivateVarList(*this)))
@@ -3223,6 +3248,7 @@ void SingleOp::build(OpBuilder &builder, OperationState &state,
MLIRContext *ctx = builder.getContext();
// TODO Store clauses in op: privateVars, privateSyms, privateNeedsBarrier
SingleOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
clauses.copyprivateVars,
makeArrayAttr(ctx, clauses.copyprivateSyms), clauses.nowait,
@@ -3231,10 +3257,10 @@ void SingleOp::build(OpBuilder &builder, OperationState &state,
}
LogicalResult SingleOp::verify() {
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
return verifyCopyprivateVarList(*this, getCopyprivateVars(),
@@ -3427,6 +3453,7 @@ LogicalResult LoopOp::verifyRegions() {
void WsloopOp::build(OpBuilder &builder, OperationState &state,
ArrayRef<NamedAttribute> attributes) {
build(builder, state, /*allocate_vars=*/{}, /*allocator_vars=*/{},
+ /*allocate_alignments=*/nullptr,
/*allocate_private_indices=*/nullptr,
/*linear_vars=*/ValueRange(), /*linear_step_vars=*/ValueRange(),
/*linear_var_types*/ nullptr, /*linear_modifiers=*/nullptr,
@@ -3446,6 +3473,7 @@ void WsloopOp::build(OpBuilder &builder, OperationState &state,
MLIRContext *ctx = builder.getContext();
WsloopOp::build(
builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
clauses.linearVars, clauses.linearStepVars, clauses.linearVarTypes,
clauses.linearModifiers, clauses.nowait, clauses.order, clauses.orderMod,
@@ -3458,10 +3486,10 @@ void WsloopOp::build(OpBuilder &builder, OperationState &state,
}
LogicalResult WsloopOp::verify() {
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
if (failed(
@@ -3600,14 +3628,15 @@ LogicalResult SimdOp::verifyRegions() {
void DistributeOp::build(OpBuilder &builder, OperationState &state,
const DistributeOperands &clauses) {
- DistributeOp::build(builder, state, clauses.allocateVars,
- clauses.allocatorVars,
- makeDenseI64ArrayAttr(builder.getContext(),
- clauses.allocatePrivateIndices),
- clauses.distScheduleStatic, clauses.distScheduleChunkSize,
- clauses.order, clauses.orderMod, clauses.privateVars,
- makeArrayAttr(builder.getContext(), clauses.privateSyms),
- clauses.privateNeedsBarrier);
+ DistributeOp::build(
+ builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(builder.getContext(), clauses.allocateAlignments),
+ makeDenseI64ArrayAttr(builder.getContext(),
+ clauses.allocatePrivateIndices),
+ clauses.distScheduleStatic, clauses.distScheduleChunkSize, clauses.order,
+ clauses.orderMod, clauses.privateVars,
+ makeArrayAttr(builder.getContext(), clauses.privateSyms),
+ clauses.privateNeedsBarrier);
}
LogicalResult DistributeOp::verify() {
@@ -3615,10 +3644,10 @@ LogicalResult DistributeOp::verify() {
return emitOpError() << "chunk size set without "
"dist_schedule_static being present";
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
if (failed(verifyPrivateVarList(*this)))
@@ -3770,6 +3799,7 @@ void TaskOp::build(OpBuilder &builder, OperationState &state,
TaskOp::build(
builder, state, clauses.iterated, clauses.affinityVars,
clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
makeArrayAttr(ctx, clauses.dependKinds), clauses.dependVars,
makeArrayAttr(ctx, clauses.dependIteratedKinds), clauses.dependIterated,
@@ -3782,10 +3812,10 @@ void TaskOp::build(OpBuilder &builder, OperationState &state,
}
LogicalResult TaskOp::verify() {
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
LogicalResult verifyDependVars =
@@ -3810,6 +3840,7 @@ void TaskgroupOp::build(OpBuilder &builder, OperationState &state,
MLIRContext *ctx = builder.getContext();
TaskgroupOp::build(builder, state, clauses.allocateVars,
clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
clauses.taskReductionVars,
makeDenseBoolArrayAttr(ctx, clauses.taskReductionByref),
@@ -3817,9 +3848,9 @@ void TaskgroupOp::build(OpBuilder &builder, OperationState &state,
}
LogicalResult TaskgroupOp::verify() {
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr())))
return failure();
return verifyReductionVarList(*this, getTaskReductionSyms(),
@@ -3836,6 +3867,7 @@ void TaskloopContextOp::build(OpBuilder &builder, OperationState &state,
MLIRContext *ctx = builder.getContext();
TaskloopContextOp::build(
builder, state, clauses.allocateVars, clauses.allocatorVars,
+ makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices), clauses.final,
clauses.grainsizeMod, clauses.grainsize, clauses.ifExpr,
clauses.inReductionVars,
@@ -3860,10 +3892,10 @@ TaskloopWrapperOp TaskloopContextOp::getLoopOp() {
LogicalResult TaskloopContextOp::verify() {
if (failed(verifyPrivateVarList(*this)))
return failure();
- if (failed(verifyAllocateClause(getOperation(), getAllocateVars(),
- getAllocatorVars(),
- getAllocatePrivateIndicesAttr(),
- getPrivateVars(), getPrivateSymsAttr())))
+ if (failed(verifyAllocateClause(
+ getOperation(), getAllocateVars(), getAllocatorVars(),
+ getAllocateAlignmentsAttr(), getAllocatePrivateIndicesAttr(),
+ getPrivateVars(), getPrivateSymsAttr())))
return failure();
if (failed(verifyReductionVarList(*this, getReductionSyms(),
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index a1c0f5dcfbd72..e09bb720ced2d 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -1971,8 +1971,10 @@ allocatePrivateVars(T op, llvm::IRBuilderBase &builder,
SmallVector<int64_t> allocateItemForPrivate(privateVarsInfo.blockArgs.size(),
-1);
ValueRange allocatorVars;
+ DenseI64ArrayAttr allocateAlignments;
if constexpr (std::is_same_v<T, omp::ParallelOp>) {
allocatorVars = op.getAllocatorVars();
+ allocateAlignments = op.getAllocateAlignmentsAttr();
if (auto privateIndices = op.getAllocatePrivateIndicesAttr())
for (auto [allocateIndex, privateIndex] :
llvm::enumerate(privateIndices.asArrayRef()))
@@ -2016,8 +2018,26 @@ allocatePrivateVars(T op, llvm::IRBuilderBase &builder,
return llvm::createStringError(
"failed to find converted OpenMP allocator operand");
llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
- llvmPrivateVar = ompBuilder->createOMPAlloc(
- ompLoc, sizeValue, allocator->second, "omp.private.alloc");
+ int64_t alignment =
+ allocateAlignments ? allocateAlignments[allocateIndex] : 0;
+ if (alignment != 0) {
+ // The allocation must be aligned to at least the maximum of the
+ // requested alignment and the alignment the base language requires
+ // for the type being allocated.
+ uint64_t alignmentValue = std::max<uint64_t>(
+ static_cast<uint64_t>(alignment),
+ dataLayout.getABITypeAlign(llvmAllocType).value());
+ if (!llvm::isUIntN(sizeTy->getBitWidth(), alignmentValue))
+ return llvm::createStringError(
+ "OpenMP allocation alignment cannot be represented by the "
+ "target size type");
+ llvmPrivateVar = ompBuilder->createOMPAlignedAlloc(
+ ompLoc, llvm::ConstantInt::get(sizeTy, alignmentValue), sizeValue,
+ allocator->second, "omp.private.alloc");
+ } else {
+ llvmPrivateVar = ompBuilder->createOMPAlloc(
+ ompLoc, sizeValue, allocator->second, "omp.private.alloc");
+ }
if (!llvmPrivateVar)
return llvm::createStringError(
"failed to create OpenMP private allocation");
diff --git a/mlir/test/Dialect/OpenMP/host-op-filtering.mlir b/mlir/test/Dialect/OpenMP/host-op-filtering.mlir
index e11ef390c2147..d4dde0cdef178 100644
--- a/mlir/test/Dialect/OpenMP/host-op-filtering.mlir
+++ b/mlir/test/Dialect/OpenMP/host-op-filtering.mlir
@@ -353,10 +353,10 @@ module attributes {omp.is_target_device = true} {
// CHECK-NEXT: %[[MAP:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr
%1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr
// CHECK-NEXT: omp.target kernel_type(generic) allocate(%[[ARG0]] : !llvm.ptr -> %[[ARG0]] : !llvm.ptr) thread_limit(%[[ARG1]] : i32) map_entries(%[[MAP]] -> %{{.*}} : !llvm.ptr) private(@privatizer %[[ARG0]] -> %{{.*}} : !llvm.ptr)
- // CHECK: } {allocate_private_indices = array<i64: 0>}
+ // CHECK: } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
omp.target kernel_type(generic) allocate(%arg0 : !llvm.ptr -> %arg0 : !llvm.ptr) depend(taskdependin -> %arg0 : !llvm.ptr) device(%arg1 : i32) if(%arg2) thread_limit(%arg1 : i32) in_reduction(@reduction %arg0 : !llvm.ptr) map_entries(%1 -> %arg3 : !llvm.ptr) private(@privatizer %arg0 -> %arg4 : !llvm.ptr) {
omp.terminator
- } {allocate_private_indices = array<i64: 0>}
+ } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
// CHECK-NOT: omp.target_enter_data
// CHECK-NOT: omp.target_exit_data
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 41f2b705d31fe..56dae56f2fb8c 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3374,6 +3374,58 @@ func.func @omp_parallel_allocate_empty_map() {
// -----
+func.func @omp_parallel_allocate_empty_alignments() {
+ // expected-error @below {{unexpected allocate alignments without allocate variables}}
+ omp.parallel {
+ omp.terminator
+ } {allocate_alignments = array<i64>}
+ return
+}
+
+// -----
+
+omp.private {type = private} @allocate_private : i32
+
+func.func @omp_parallel_allocate_alignment_size(
+ %allocator : i64, %var : !llvm.ptr) {
+ // expected-error @below {{expected as many allocate alignments as allocate variables}}
+ omp.parallel allocate(%allocator : i64 -> %var : !llvm.ptr)
+ private(@allocate_private %var -> %private : !llvm.ptr) {
+ omp.terminator
+ } {allocate_alignments = array<i64: 64, 128>, allocate_private_indices = array<i64: 0>}
+ return
+}
+
+// -----
+
+omp.private {type = private} @allocate_private : i32
+
+func.func @omp_parallel_allocate_negative_alignment(
+ %allocator : i64, %var : !llvm.ptr) {
+ // expected-error @below {{expected non-negative allocate alignments}}
+ omp.parallel allocate(%allocator : i64 -> %var : !llvm.ptr)
+ private(@allocate_private %var -> %private : !llvm.ptr) {
+ omp.terminator
+ } {allocate_alignments = array<i64: -64>, allocate_private_indices = array<i64: 0>}
+ return
+}
+
+// -----
+
+omp.private {type = private} @allocate_private : i32
+
+func.func @omp_parallel_allocate_non_power_of_two_alignment(
+ %allocator : i64, %var : !llvm.ptr) {
+ // expected-error @below {{expected positive allocate alignments to be powers of two}}
+ omp.parallel allocate(%allocator : i64 -> %var : !llvm.ptr)
+ private(@allocate_private %var -> %private : !llvm.ptr) {
+ omp.terminator
+ } {allocate_alignments = array<i64: 24>, allocate_private_indices = array<i64: 0>}
+ return
+}
+
+// -----
+
omp.private {type = private} @allocate_private : i32
func.func @omp_parallel_allocate_missing_map(%allocator : i64, %var : !llvm.ptr) {
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index b2fe5effd2de6..00b975c371d1b 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -195,11 +195,11 @@ func.func @omp_parallel_pretty(%data_var : memref<i32>, %if_cond : i1, %num_thre
// CHECK: omp.parallel allocate(
// CHECK-SAME: private(
- // CHECK: } {allocate_private_indices = array<i64: 0>}
+ // CHECK: } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
omp.parallel allocate(%allocator : si32 -> %data_var : memref<i32>)
private(@parallel_allocate_private %data_var -> %private : memref<i32>) {
omp.terminator
- } {allocate_private_indices = array<i64: 0>}
+ } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
// CHECK: omp.parallel
// CHECK-NEXT: omp.parallel if(%{{.*}})
diff --git a/mlir/test/Target/LLVMIR/openmp-allocate-clause.mlir b/mlir/test/Target/LLVMIR/openmp-allocate-clause.mlir
index dc2515e3f1358..d6e0587ce5095 100644
--- a/mlir/test/Target/LLVMIR/openmp-allocate-clause.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-allocate-clause.mlir
@@ -1,7 +1,10 @@
// RUN: split-file %s %t
// RUN: mlir-translate -mlir-to-llvmir -split-input-file %t/valid.mlir | FileCheck %s
// RUN: mlir-translate -mlir-to-llvmir %t/i386.mlir | FileCheck %s --check-prefix=I386
+// RUN: mlir-translate -mlir-to-llvmir %t/i386-aligned.mlir | FileCheck %s --check-prefix=I386-ALIGNED
+// RUN: mlir-translate -mlir-to-llvmir %t/natural-alignment.mlir | FileCheck %s --check-prefix=NATURAL
// RUN: not mlir-translate -mlir-to-llvmir %t/i386-overflow.mlir 2>&1 | FileCheck %s --check-prefix=I386-OVERFLOW
+// RUN: not mlir-translate -mlir-to-llvmir %t/i386-alignment-overflow.mlir 2>&1 | FileCheck %s --check-prefix=I386-ALIGNMENT-OVERFLOW
// RUN: not mlir-translate -mlir-to-llvmir %t/device.mlir 2>&1 | FileCheck %s --check-prefix=DEVICE
//--- valid.mlir
@@ -15,6 +18,19 @@ omp.private {type = firstprivate} @x.firstprivate : i32 copy {
omp.private {type = private} @y.private : i32
+llvm.func @allocator_unaligned(%x: !llvm.ptr) {
+ %null = llvm.mlir.constant(0 : i64) : i64
+ omp.parallel allocate(%null : i64 -> %x : !llvm.ptr)
+ private(@y.private %x -> %x.private : !llvm.ptr) {
+ omp.terminator
+ } {allocate_private_indices = array<i64: 0>}
+ llvm.return
+}
+
+// CHECK-LABEL: define internal void @allocator_unaligned..omp_par
+// CHECK: %[[UNALIGNED:.*]] = call ptr @__kmpc_alloc({{.*}}, i64 4, ptr null)
+// CHECK: call void @__kmpc_free({{.*}}, ptr %[[UNALIGNED]], ptr null)
+
llvm.func @allocator_dynamic(%x: !llvm.ptr, %y: !llvm.ptr, %allocator: i64) {
omp.parallel allocate(%allocator : i64 -> %x : !llvm.ptr)
private(@x.firstprivate %x -> %x.private,
@@ -25,7 +41,7 @@ llvm.func @allocator_dynamic(%x: !llvm.ptr, %y: !llvm.ptr, %allocator: i64) {
llvm.store %next, %x.private : i32, !llvm.ptr
llvm.store %one, %y.private : i32, !llvm.ptr
omp.terminator
- } {allocate_private_indices = array<i64: 0>}
+ } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
llvm.return
}
@@ -35,7 +51,7 @@ llvm.func @allocator_dynamic(%x: !llvm.ptr, %y: !llvm.ptr, %allocator: i64) {
// CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call
// CHECK-LABEL: define internal void @allocator_dynamic..omp_par
// CHECK: %[[CAPTURED_ALLOCATOR:.*]] = load ptr, ptr %{{.*}}, align 8
-// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_alloc({{.*}}, i64 4, ptr %[[CAPTURED_ALLOCATOR]])
+// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i64 64, i64 4, ptr %[[CAPTURED_ALLOCATOR]])
// CHECK: %[[Y_ALLOCA:.*]] = alloca i32, align 4
// CHECK: %[[ORIGINAL:.*]] = load i32, ptr %{{.*}}, align 4
// CHECK: store i32 %[[ORIGINAL]], ptr %[[ALLOC]], align 4
@@ -67,8 +83,11 @@ llvm.func @allocator_reverse_free(%x: !llvm.ptr, %y: !llvm.ptr,
%allocator.x : i64 -> %x : !llvm.ptr)
private(@x.private %x -> %x.private,
@y.private %y -> %y.private : !llvm.ptr, !llvm.ptr) {
+ %one = llvm.mlir.constant(1 : i32) : i32
+ llvm.store %one, %x.private : i32, !llvm.ptr
+ llvm.store %one, %y.private : i32, !llvm.ptr
omp.terminator
- } {allocate_private_indices = array<i64: 1, 0>}
+ } {allocate_alignments = array<i64: 128, 64>, allocate_private_indices = array<i64: 1, 0>}
llvm.return
}
@@ -78,8 +97,10 @@ llvm.func @allocator_reverse_free(%x: !llvm.ptr, %y: !llvm.ptr,
// CHECK-LABEL: define internal void @allocator_reverse_free..omp_par
// CHECK: %[[CAPTURED_X:.*]] = load ptr, ptr %{{.*}}, align 8
// CHECK: %[[CAPTURED_Y:.*]] = load ptr, ptr %{{.*}}, align 8
-// CHECK: %[[X_ALLOC:.*]] = call ptr @__kmpc_alloc({{.*}}, i64 4, ptr %[[CAPTURED_X]])
-// CHECK: %[[Y_ALLOC:.*]] = call ptr @__kmpc_alloc({{.*}}, i64 4, ptr %[[CAPTURED_Y]])
+// CHECK: %[[X_ALLOC:.*]] = call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i64 64, i64 4, ptr %[[CAPTURED_X]])
+// CHECK: %[[Y_ALLOC:.*]] = call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i64 128, i64 4, ptr %[[CAPTURED_Y]])
+// CHECK: store i32 1, ptr %[[X_ALLOC]], align 4
+// CHECK: store i32 1, ptr %[[Y_ALLOC]], align 4
// CHECK: call void @private_dealloc(ptr %[[X_ALLOC]])
// CHECK: call void @__kmpc_free({{.*}}, ptr %[[Y_ALLOC]], ptr %[[CAPTURED_Y]])
// CHECK: call void @__kmpc_free({{.*}}, ptr %[[X_ALLOC]], ptr %[[CAPTURED_X]])
@@ -95,12 +116,12 @@ llvm.func @allocator_cancel(%x: !llvm.ptr) {
private(@x.private %x -> %x.private : !llvm.ptr) {
omp.cancel cancellation_construct_type(parallel)
omp.terminator
- } {allocate_private_indices = array<i64: 0>}
+ } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
llvm.return
}
// CHECK-LABEL: define internal void @allocator_cancel..omp_par
-// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_alloc({{.*}}, i64 4, ptr null)
+// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i64 64, i64 4, ptr null)
// CHECK: {{.*}}.cncl:
// CHECK: br label %[[FINI:.*]]
// CHECK: .fini:
@@ -119,12 +140,12 @@ llvm.func @allocator_cancellation_point(%x: !llvm.ptr) {
private(@x.private %x -> %x.private : !llvm.ptr) {
omp.cancellation_point cancellation_construct_type(parallel)
omp.terminator
- } {allocate_private_indices = array<i64: 0>}
+ } {allocate_alignments = array<i64: 128>, allocate_private_indices = array<i64: 0>}
llvm.return
}
// CHECK-LABEL: define internal void @allocator_cancellation_point..omp_par
-// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_alloc({{.*}}, i64 4, ptr null)
+// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i64 128, i64 4, ptr null)
// CHECK: {{.*}}.cncl:
// CHECK: br label %[[FINI:.*]]
// CHECK: .fini:
@@ -158,6 +179,66 @@ module attributes {
// I386: ret void
// I386-LABEL: declare noalias ptr @__kmpc_alloc(i32, i32, ptr)
+//--- i386-aligned.mlir
+
+module attributes {
+ llvm.data_layout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-S128",
+ llvm.target_triple = "i386-unknown-linux-gnu"
+} {
+ omp.private {type = private} @x.private : i32
+
+ llvm.func @allocator_i386_aligned(%x: !llvm.ptr) {
+ %null = llvm.mlir.constant(0 : i64) : i64
+ omp.parallel allocate(%null : i64 -> %x : !llvm.ptr)
+ private(@x.private %x -> %x.private : !llvm.ptr) {
+ %one = llvm.mlir.constant(1 : i32) : i32
+ llvm.store %one, %x.private : i32, !llvm.ptr
+ omp.terminator
+ } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
+ llvm.return
+ }
+}
+
+// I386-ALIGNED: target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-S128"
+// I386-ALIGNED-LABEL: define internal void @allocator_i386_aligned..omp_par
+// I386-ALIGNED: %[[ALLOC:.*]] = call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i32 64, i32 4, ptr null)
+// I386-ALIGNED: store i32 1, ptr %[[ALLOC]], align 4
+// I386-ALIGNED: call void @__kmpc_free(i32 %{{.*}}, ptr %[[ALLOC]], ptr null)
+// I386-ALIGNED: ret void
+// I386-ALIGNED-LABEL: declare noalias ptr @__kmpc_aligned_alloc(i32, i32, i32, ptr)
+
+//--- natural-alignment.mlir
+
+module attributes {
+ llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
+ llvm.target_triple = "x86_64-unknown-linux-gnu"
+} {
+ omp.private {type = private} @i64.private : i64
+
+ llvm.func @allocator_below_natural_alignment(%x: !llvm.ptr) {
+ %null = llvm.mlir.constant(0 : i64) : i64
+ omp.parallel allocate(%null : i64 -> %x : !llvm.ptr)
+ private(@i64.private %x -> %x.private : !llvm.ptr) {
+ omp.terminator
+ } {allocate_alignments = array<i64: 2>, allocate_private_indices = array<i64: 0>}
+ llvm.return
+ }
+
+ llvm.func @allocator_above_natural_alignment(%x: !llvm.ptr) {
+ %null = llvm.mlir.constant(0 : i64) : i64
+ omp.parallel allocate(%null : i64 -> %x : !llvm.ptr)
+ private(@i64.private %x -> %x.private : !llvm.ptr) {
+ omp.terminator
+ } {allocate_alignments = array<i64: 32>, allocate_private_indices = array<i64: 0>}
+ llvm.return
+ }
+}
+
+// NATURAL-LABEL: define internal void @allocator_below_natural_alignment..omp_par
+// NATURAL: call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i64 8, i64 8, ptr null)
+// NATURAL-LABEL: define internal void @allocator_above_natural_alignment..omp_par
+// NATURAL: call ptr @__kmpc_aligned_alloc(i32 %{{.*}}, i64 32, i64 8, ptr null)
+
//--- i386-overflow.mlir
module attributes {
@@ -182,6 +263,30 @@ module attributes {
// I386-OVERFLOW: LLVM Translation failed for operation: omp.parallel
// I386-OVERFLOW-NOT: __kmpc_alloc
+//--- i386-alignment-overflow.mlir
+
+module attributes {
+ llvm.data_layout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-S128",
+ llvm.target_triple = "i386-unknown-linux-gnu"
+} {
+ omp.private {type = private} @x.private : i32
+
+ llvm.func @allocator_i386_alignment_overflow(%x: !llvm.ptr) {
+ %null = llvm.mlir.constant(0 : i64) : i64
+ omp.parallel allocate(%null : i64 -> %x : !llvm.ptr)
+ private(@x.private %x -> %x.private : !llvm.ptr) {
+ omp.terminator
+ } {allocate_alignments = array<i64: 4294967296>, allocate_private_indices = array<i64: 0>}
+ llvm.return
+ }
+}
+
+// I386-ALIGNMENT-OVERFLOW-NOT: __kmpc_aligned_alloc
+// I386-ALIGNMENT-OVERFLOW: OpenMP allocation alignment cannot be represented by the target size type
+// I386-ALIGNMENT-OVERFLOW-NOT: __kmpc_aligned_alloc
+// I386-ALIGNMENT-OVERFLOW: LLVM Translation failed for operation: omp.parallel
+// I386-ALIGNMENT-OVERFLOW-NOT: __kmpc_aligned_alloc
+
//--- device.mlir
omp.private {type = private} @device.private : i32
@@ -193,7 +298,7 @@ llvm.func @allocator_device() {
omp.parallel allocate(%allocator : i64 -> %x : !llvm.ptr)
private(@device.private %x -> %private : !llvm.ptr) {
omp.terminator
- } {allocate_private_indices = array<i64: 0>}
+ } {allocate_alignments = array<i64: 64>, allocate_private_indices = array<i64: 0>}
omp.terminator
}
llvm.return
More information about the flang-commits
mailing list