Skip to content

Commit 2193c16

Browse files
[MLIR][Flang][OpenMP] Implement lowering simd aligned to MLIR
Co-authored-by: Dominik Adamski <[email protected]>
1 parent 4748b49 commit 2193c16

File tree

6 files changed

+177
-5
lines changed

6 files changed

+177
-5
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "flang/Lower/PFTBuilder.h"
1717
#include "flang/Parser/tools.h"
1818
#include "flang/Semantics/tools.h"
19+
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
1920

2021
namespace Fortran {
2122
namespace lower {
@@ -999,6 +1000,72 @@ bool ClauseProcessor::processUseDevicePtr(
9991000
});
10001001
}
10011002

1003+
static llvm::StringMap<bool> getTargetFeatures(mlir::ModuleOp module) {
1004+
llvm::StringMap<bool> featuresMap;
1005+
llvm::SmallVector<llvm::StringRef> targetFeaturesVec;
1006+
if (mlir::LLVM::TargetFeaturesAttr features =
1007+
fir::getTargetFeatures(module)) {
1008+
llvm::StringRef targetFeaturesStr(features.getFeaturesString());
1009+
targetFeaturesStr.split(targetFeaturesVec, ",");
1010+
for (auto &feature : targetFeaturesVec) {
1011+
if (feature.empty())
1012+
continue;
1013+
llvm::StringRef featureKeyString = feature.substr(1);
1014+
featuresMap[featureKeyString] = (feature[0] == '+');
1015+
}
1016+
}
1017+
return featuresMap;
1018+
}
1019+
1020+
static void
1021+
addAlignedClause(lower::AbstractConverter &converter,
1022+
const omp::clause::Aligned &clause,
1023+
llvm::SmallVectorImpl<mlir::Value> &alignedVars,
1024+
llvm::SmallVectorImpl<mlir::Attribute> &alignmentAttrs) {
1025+
using Aligned = omp::clause::Aligned;
1026+
lower::StatementContext stmtCtx;
1027+
mlir::IntegerAttr alignmentValueAttr;
1028+
int64_t alignment = 0;
1029+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1030+
1031+
if (auto &alignmentValueParserExpr =
1032+
std::get<std::optional<Aligned::Alignment>>(clause.t)) {
1033+
mlir::Value operand = fir::getBase(
1034+
converter.genExprValue(*alignmentValueParserExpr, stmtCtx));
1035+
if (mlir::Operation *definingOp = operand.getDefiningOp())
1036+
if (auto cst = mlir::dyn_cast<mlir::arith::ConstantOp>(definingOp))
1037+
if (auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(cst.getValue()))
1038+
alignment = intAttr.getInt();
1039+
} else {
1040+
llvm::StringMap<bool> featuresMap = getTargetFeatures(builder.getModule());
1041+
llvm::Triple triple = fir::getTargetTriple(builder.getModule());
1042+
alignment =
1043+
llvm::OpenMPIRBuilder::getOpenMPDefaultSimdAlign(triple, featuresMap);
1044+
}
1045+
1046+
// The default alignment for some targets is equal to 0.
1047+
// Do not generate alignment assumption if alignment is less than or equal to
1048+
// 0.
1049+
if (alignment > 0) {
1050+
auto &objects = std::get<omp::ObjectList>(clause.t);
1051+
if (!objects.empty())
1052+
genObjectList(objects, converter, alignedVars);
1053+
alignmentValueAttr = builder.getI64IntegerAttr(alignment);
1054+
// All the list items in a aligned clause will have same alignment
1055+
for (unsigned i = 0; i < (unsigned)objects.size(); i++)
1056+
alignmentAttrs.push_back(alignmentValueAttr);
1057+
}
1058+
}
1059+
1060+
bool ClauseProcessor::processAligned(
1061+
mlir::omp::AlignedClauseOps &result) const {
1062+
return findRepeatableClause<omp::clause::Aligned>(
1063+
[&](const omp::clause::Aligned &clause, const parser::CharBlock &) {
1064+
addAlignedClause(converter, clause, result.alignedVars,
1065+
result.alignmentAttrs);
1066+
});
1067+
}
1068+
10021069
} // namespace omp
10031070
} // namespace lower
10041071
} // namespace Fortran

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class ClauseProcessor {
138138
template <typename T>
139139
bool processMotionClauses(lower::StatementContext &stmtCtx,
140140
mlir::omp::MapClauseOps &result);
141-
141+
bool processAligned(mlir::omp::AlignedClauseOps &result) const;
142142
// Call this method for these clauses that should be supported but are not
143143
// implemented yet. It triggers a compilation error if any of the given
144144
// clauses is found.

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,11 +1062,11 @@ static void genSimdClauses(lower::AbstractConverter &converter,
10621062
cp.processReduction(loc, clauseOps);
10631063
cp.processSafelen(clauseOps);
10641064
cp.processSimdlen(clauseOps);
1065-
// TODO Support delayed privatization.
1065+
cp.processAligned(clauseOps);
10661066

1067-
cp.processTODO<clause::Aligned, clause::Allocate, clause::Linear,
1068-
clause::Nontemporal, clause::Order>(
1069-
loc, llvm::omp::Directive::OMPD_simd);
1067+
// TODO Support delayed privatization.
1068+
cp.processTODO<clause::Allocate, clause::Linear, clause::Nontemporal,
1069+
clause::Order>(loc, llvm::omp::Directive::OMPD_simd);
10701070
}
10711071

10721072
static void genSingleClauses(lower::AbstractConverter &converter,

flang/test/Lower/OpenMP/simd.f90

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,44 @@ subroutine simd_with_collapse_clause(n)
182182
end do
183183
!$OMP END SIMD
184184
end subroutine
185+
186+
187+
!CHECK: func.func @_QPsimdloop_aligned_cptr(%[[ARG_A:.*]]: !fir.ref
188+
!CHECK-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr
189+
!CHECK-SAME: {__address:i64}>> {fir.bindc_name = "a"}) {
190+
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %0
191+
!CHECK-SAME: {uniq_name = "_QFsimdloop_aligned_cptrEa"} :
192+
!CHECK-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) ->
193+
!CHECK-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>,
194+
!CHECK-SAME: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
195+
subroutine simdloop_aligned_cptr( A)
196+
use iso_c_binding
197+
integer :: i
198+
type (c_ptr) :: A
199+
!CHECK: omp.simd aligned(%[[A_DECL]]#1 : !fir.ref
200+
!CHECK-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
201+
!CHECK-SAME: -> 256 : i64)
202+
!$OMP SIMD ALIGNED(A:256)
203+
do i = 1, 10
204+
call c_test_call(A)
205+
end do
206+
!$OMP END SIMD
207+
end subroutine
208+
209+
!CHECK-LABEL: func @_QPsimdloop_aligned_allocatable
210+
subroutine simdloop_aligned_allocatable()
211+
integer :: i
212+
integer, allocatable :: A(:)
213+
allocate(A(10))
214+
!CHECK: %[[A_PTR:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "a",
215+
!CHECK-SAME: uniq_name = "_QFsimdloop_aligned_allocatableEa"}
216+
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_PTR]] {fortran_attrs = #fir.var_attrs<allocatable>,
217+
!CHECK-SAME: uniq_name = "_QFsimdloop_aligned_allocatableEa"} :
218+
!CHECK-SAME: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) ->
219+
!CHECK-SAME: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
220+
!CHECK: omp.simd aligned(%[[A_DECL]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> -> 256 : i64)
221+
!$OMP SIMD ALIGNED(A:256)
222+
do i = 1, 10
223+
A(i) = i
224+
end do
225+
end subroutine
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
! Tests for 2.9.3.1 Simd and target dependent defult alignment for AArch64
2+
! The default alignment for AARch is 0 so we do not emit aligned clause
3+
! REQUIRES: aarch64-registered-target
4+
! RUN: %flang_fc1 -triple aarch64-unknown-linux-gnu -emit-hlfir -fopenmp %s -o - | FileCheck %s
5+
subroutine simdloop_aligned_cptr(A)
6+
use iso_c_binding
7+
integer :: i
8+
type (c_ptr) :: A
9+
!CHECK: omp.simd
10+
!CHECK-NOT: aligned(
11+
!$OMP SIMD ALIGNED(A)
12+
do i = 1, 10
13+
call c_test_call(A)
14+
end do
15+
!$OMP END SIMD
16+
end subroutine
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
! Tests for 2.9.3.1 Simd and target dependent defult alignment for x86
2+
! REQUIRES: x86-registered-target
3+
! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-hlfir -fopenmp -target-cpu x86-64 %s -o - | FileCheck --check-prefixes=DEFAULT %s
4+
! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-hlfir -fopenmp -target-cpu x86-64 -target-feature +avx %s -o - | FileCheck --check-prefixes=AVX %s
5+
! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-hlfir -fopenmp -target-cpu x86-64 -target-feature +avx512f %s -o - | FileCheck --check-prefixes=AVX512F %s
6+
!DEFAULT: func.func @_QPsimdloop_aligned_cptr(%[[ARG_A:.*]]: !fir.ref
7+
!DEFAULT-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr
8+
!DEFAULT-SAME: {__address:i64}>> {fir.bindc_name = "a"}) {
9+
!DEFAULT: %[[A_DECL:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %0
10+
!DEFAULT-SAME: {uniq_name = "_QFsimdloop_aligned_cptrEa"} :
11+
!DEFAULT-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) ->
12+
!DEFAULT-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>,
13+
!DEFAULT-SAME: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
14+
!AVX: func.func @_QPsimdloop_aligned_cptr(%[[ARG_A:.*]]: !fir.ref
15+
!AVX-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr
16+
!AVX-SAME: {__address:i64}>> {fir.bindc_name = "a"}) {
17+
!AVX: %[[A_DECL:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %0
18+
!AVX-SAME: {uniq_name = "_QFsimdloop_aligned_cptrEa"} :
19+
!AVX-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) ->
20+
!AVX-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>,
21+
!AVX-SAME: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
22+
!AVX512F: func.func @_QPsimdloop_aligned_cptr(%[[ARG_A:.*]]: !fir.ref
23+
!AVX512F-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr
24+
!AVX512F-SAME: {__address:i64}>> {fir.bindc_name = "a"}) {
25+
!AVX512F: %[[A_DECL:.*]]:2 = hlfir.declare %[[ARG_A]] dummy_scope %0
26+
!AVX512F-SAME: {uniq_name = "_QFsimdloop_aligned_cptrEa"} :
27+
!AVX512F-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.dscope) ->
28+
!AVX512F-SAME: (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>,
29+
!AVX512F-SAME: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
30+
subroutine simdloop_aligned_cptr(A)
31+
use iso_c_binding
32+
integer :: i
33+
type (c_ptr) :: A
34+
!DEFAULT: omp.simd aligned(%[[A_DECL]]#1 : !fir.ref
35+
!DEFAULT-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
36+
!DEFAULT-SAME: -> 128 : i64)
37+
!AVX: omp.simd aligned(%[[A_DECL]]#1 : !fir.ref
38+
!AVX-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
39+
!AVX-SAME: -> 256 : i64)
40+
!AVX512F: omp.simd aligned(%[[A_DECL]]#1 : !fir.ref
41+
!AVX512F-SAME: <!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
42+
!AVX512F-SAME: -> 512 : i64)
43+
!$OMP SIMD ALIGNED(A)
44+
do i = 1, 10
45+
call c_test_call(A)
46+
end do
47+
!$OMP END SIMD
48+
end subroutine

0 commit comments

Comments
 (0)