[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