Index: clang/lib/CodeGen/CGDecl.cpp =================================================================== --- clang/lib/CodeGen/CGDecl.cpp +++ clang/lib/CodeGen/CGDecl.cpp @@ -2694,3 +2694,22 @@ DummyGV->eraseFromParent(); } } + +llvm::Optional +CodeGenModule::getOMPAllocateAlignment(const VarDecl *VD) { + if (const auto *AA = VD->getAttr()) { + if (Expr *Alignment = AA->getAlignment()) { + unsigned UserAlign = + Alignment->EvaluateKnownConstInt(getContext()).getExtValue(); + CharUnits NaturalAlign = + getNaturalTypeAlignment(VD->getType().getNonReferenceType()); + + // OpenMP5.1 pg 185 lines 7-10 + // Each item in the align modifier list must be aligned to the maximum + // of the specified alignment and the type's natural alignment. + return CharUnits::fromQuantity( + std::max(UserAlign, NaturalAlign.getQuantity())); + } + } + return llvm::None; +} Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -12185,25 +12185,15 @@ return AllocVal; } -/// Given the allocate directive list item type and align clause value, -/// return appropriate alignment. -static llvm::Value *getAlignmentValue(CodeGenFunction &CGF, QualType ListItemTy, - const Expr *Alignment) { - if (!Alignment) - return nullptr; +/// Return the alignment from an allocate directive if present. +static llvm::Value *getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD) { + llvm::Optional AllocateAlignment = CGM.getOMPAllocateAlignment(VD); - unsigned UserAlign = - Alignment->EvaluateKnownConstInt(CGF.getContext()).getExtValue(); - CharUnits NaturalAlign = CGF.CGM.getNaturalTypeAlignment(ListItemTy); + if (!AllocateAlignment) + return nullptr; - // OpenMP5.1 pg 185 lines 7-10 - // Each item in the align modifier list must be aligned to the maximum - // of the specified alignment and the type's natural alignment. - // - // If no alignment specified then use the natural alignment. - return llvm::ConstantInt::get( - CGF.CGM.SizeTy, - std::max(UserAlign, NaturalAlign.getQuantity())); + return llvm::ConstantInt::get(CGM.SizeTy, + AllocateAlignment.getValue().getQuantity()); } Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, @@ -12244,8 +12234,7 @@ const auto *AA = CVD->getAttr(); const Expr *Allocator = AA->getAllocator(); llvm::Value *AllocVal = getAllocatorVal(CGF, Allocator); - llvm::Value *Alignment = getAlignmentValue( - CGF, VD->getType().getNonReferenceType(), AA->getAlignment()); + llvm::Value *Alignment = getAlignmentValue(CGM, CVD); SmallVector Args; Args.push_back(ThreadID); if (Alignment) Index: clang/lib/CodeGen/CodeGenModule.h =================================================================== --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -1365,6 +1365,9 @@ /// \param D The allocate declaration void EmitOMPAllocateDecl(const OMPAllocateDecl *D); + /// Return the alignment specified in an allocate directive, if present. + llvm::Optional getOMPAllocateAlignment(const VarDecl *VD); + /// Returns whether the given record has hidden LTO visibility and therefore /// may participate in (single-module) CFI and whole-program vtable /// optimization. Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -4737,7 +4737,12 @@ GV->setConstant(true); } - GV->setAlignment(getContext().getDeclAlign(D).getAsAlign()); + CharUnits AlignVal = getContext().getDeclAlign(D); + // Check for alignment specifed in an 'omp allocate' directive. + if (llvm::Optional AlignValFromAllocate = + getOMPAllocateAlignment(D)) + AlignVal = AlignValFromAllocate.getValue(); + GV->setAlignment(AlignVal.getAsAlign()); // On Darwin, unlike other Itanium C++ ABI platforms, the thread-wrapper // function is only defined alongside the variable, not also alongside Index: clang/test/OpenMP/align_clause_global_codegen.cpp =================================================================== --- /dev/null +++ clang/test/OpenMP/align_clause_global_codegen.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -emit-llvm -o - -fopenmp \ +// RUN: -triple i386-unknown-unknown -fopenmp-version=51 %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-32 + +// RUN: %clang_cc1 -emit-llvm -o - -fopenmp \ +// RUN: -triple x86_64-unknown-linux-gnu -fopenmp-version=51 %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-64 + +typedef enum omp_allocator_handle_t { + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + KMP_ALLOCATOR_MAX_HANDLE = __UINTPTR_MAX__ +} omp_allocator_handle_t; + +// +// Should allow larger alignment. +// + +// CHECK: @foo_global1 = global float 0.000000e+00, align 16 +float foo_global1; +#pragma omp allocate(foo_global1) align(16) + +// CHECK: @foo_global2 = global float 0.000000e+00, align 16 +float foo_global2; +#pragma omp allocate(foo_global2) allocator(omp_default_mem_alloc) align(16) + +// CHECK: @foo_global3 = global float 0.000000e+00, align 16 +float foo_global3; +#pragma omp allocate(foo_global3) allocator(omp_large_cap_mem_alloc) align(16) + +// CHECK: @foop_global1 = global ptr null, align 16 +int *foop_global1; +#pragma omp allocate(foop_global1) align(16) + +// +// Should use natural alignment when alignment specified is too small. +// + +// CHECK: @foo_global4 = global float 0.000000e+00, align 4 +float foo_global4; +#pragma omp allocate(foo_global4) align(2) + +// CHECK: @foo_global5 = global float 0.000000e+00, align 4 +float foo_global5; +#pragma omp allocate(foo_global5) allocator(omp_default_mem_alloc) align(2) + +// CHECK: @foo_global6 = global float 0.000000e+00, align 4 +float foo_global6; +#pragma omp allocate(foo_global6) allocator(omp_large_cap_mem_alloc) align(2) + +// CHECK-32: @foop_global2 = global ptr null, align 4 +// CHECK-64: @foop_global2 = global ptr null, align 8 +int *foop_global2; +#pragma omp allocate(foop_global2) align(2)