Skip to content

Commit 2f3a180

Browse files
authored
Merge pull request #424 from SouraVX/parallel-codegen
[flang][OpenMP] Parallel region codegen support
2 parents d2c45b3 + 4f1e425 commit 2f3a180

File tree

3 files changed

+125
-2
lines changed

3 files changed

+125
-2
lines changed

flang/lib/Lower/Bridge.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
12051205
}
12061206

12071207
void genFIR(const Fortran::parser::OpenMPConstruct &omp) {
1208+
auto insertPt = builder->saveInsertionPoint();
12081209
genOpenMPConstruct(*this, getEval(), omp);
1210+
for (auto &e : getEval().getNestedEvaluations())
1211+
genFIR(e);
1212+
builder->restoreInsertionPoint(insertPt);
12091213
}
12101214

12111215
void genFIR(const Fortran::parser::OmpEndLoopDirective &omp) {

flang/lib/Lower/OpenMP.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ genOMP(Fortran::lower::AbstractConverter &absConv,
8787
if (parallelDirective.v == llvm::omp::OMPD_parallel) {
8888
auto &firOpBuilder = absConv.getFirOpBuilder();
8989
auto currentLocation = absConv.getCurrentLocation();
90-
auto insertPt = firOpBuilder.saveInsertionPoint();
9190

9291
// Clauses.
9392
// FIXME: Add support for other clauses.
@@ -117,7 +116,9 @@ genOMP(Fortran::lower::AbstractConverter &absConv,
117116
firOpBuilder.setInsertionPointToStart(&block);
118117
// Ensure the block is well-formed.
119118
firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation);
120-
firOpBuilder.restoreInsertionPoint(insertPt);
119+
120+
// Place the insertion point to the start of the first block.
121+
firOpBuilder.setInsertionPointToStart(&block);
121122
}
122123
}
123124

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
! This test checks lowering of OpenMP parallel Directive with arbitrary code
2+
! inside it.
3+
4+
! RUN: bbc -fopenmp -emit-fir %s -o - | \
5+
! RUN: FileCheck %s --check-prefix=FIRDialect
6+
! RUN: bbc -fopenmp -emit-llvm %s -o - | \
7+
! RUN: FileCheck %s --check-prefix=LLVMIRDialect
8+
! RUN: bbc -fopenmp -emit-fir %s -o - | \
9+
! RUN: tco | FileCheck %s --check-prefix=LLVMIR
10+
11+
program parallel
12+
13+
integer :: a,b,c
14+
integer :: num_threads
15+
16+
a = 1
17+
b = 2
18+
!FIRDialect: %[[VAR_A:.*]] = fir.alloca i32 {name = "a"}
19+
!FIRDialect: %[[VAR_B:.*]] = fir.alloca i32 {name = "b"}
20+
!FIRDialect: %[[VAR_C:.*]] = fir.alloca i32 {name = "c"}
21+
!FIRDialect: %[[VAR_NUM_THREADS:.*]] = fir.alloca i32 {name = "num_threads"}
22+
23+
!LLVMIRDialect: %[[VAR_A:.*]] = llvm.alloca %{{.*}} x !llvm.i32 {in_type = i32, name = "a"}
24+
!LLVMIRDialect: %[[VAR_B:.*]] = llvm.alloca %{{.*}} x !llvm.i32 {in_type = i32, name = "b"}
25+
!LLVMIRDialect: %[[VAR_C:.*]] = llvm.alloca %{{.*}} x !llvm.i32 {in_type = i32, name = "c"}
26+
!LLVMIRDialect: %[[VAR_NUM_THREADS:.*]] = llvm.alloca %{{.*}} x !llvm.i32 {in_type = i32, name = "num_threads"}
27+
28+
!LLVMIR: %[[OMP_GLOBAL_THREAD_NUM:.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{.*}})
29+
!LLVMIR: call void @__kmpc_push_num_threads(%struct.ident_t* @{{.*}}, i32 %[[OMP_GLOBAL_THREAD_NUM]], i32 %{{.*}})
30+
31+
!$OMP PARALLEL NUM_THREADS(num_threads)
32+
!FIRDialect: omp.parallel num_threads(%{{.*}} : i32) {
33+
!FIRDialect-DAG: %[[OMP_VAR_A:.*]] = fir.load %[[VAR_A]]
34+
!FIRDialect-DAG: %[[OMP_VAR_B:.*]] = fir.load %[[VAR_B]]
35+
!FIRDialect: %[[OMP_VAR_C:.*]] = addi %[[OMP_VAR_A]], %[[OMP_VAR_B]]
36+
!FIRDialect: fir.store %[[OMP_VAR_C]] to %[[VAR_C]]
37+
!FIRDialect: %[[CONSTANT:.*]] = constant 4 : i32
38+
!FIRDialect: %[[COND_C:.*]] = fir.load %[[VAR_C]] : !fir.ref<i32>
39+
!FIRDialect: %[[COND_RES:.*]] = cmpi "sgt", %[[COND_C]], %[[CONSTANT]] : i32
40+
!FIRDialect: fir.if %[[COND_RES]] {
41+
!FIRDialect: fir.call @_FortranAioBeginExternalListOutput
42+
!FIRDialect: fir.call @_FortranAioOutputAscii
43+
!FIRDialect: fir.call @_FortranAioEndIoStatement
44+
!FIRDialect: } else {
45+
!FIRDialect-NEXT: }
46+
!FIRDialect: fir.call @_FortranAioBeginExternalListOutput
47+
!FIRDialect: fir.load %[[VAR_C]]
48+
!FIRDialect: fir.call @_FortranAioOutputInteger64
49+
!FIRDialect: fir.call @_FortranAioEndIoStatement
50+
!FIRDialect: omp.terminator
51+
!FIRDialect-NEXT: }
52+
53+
!LLVMIRDialect-LABEL: omp.parallel num_threads(%{{.*}} : !llvm.i32) {
54+
!LLVMIRDialect-DAG: %[[OMP_VAR_A:.*]] = llvm.load %[[VAR_A:.*]]
55+
!LLVMIRDialect-DAG: %[[OMP_VAR_B:.*]] = llvm.load %[[VAR_B:.*]]
56+
!LLVMIRDialect: %[[OMP_VAR_C:.*]] = llvm.add %[[OMP_VAR_B]], %[[OMP_VAR_A]]
57+
!LLVMIRDialect: llvm.store %[[OMP_VAR_C]], %[[VAR_C]]
58+
!LLVMIRDialect: %[[COND_C:.*]] = llvm.load %[[VAR_C]] : !llvm.ptr<i32>
59+
!LLVMIRDialect: %[[COND_RES:.*]] = llvm.icmp "sgt" %[[COND_C]], %{{.*}} : !llvm.i32
60+
!LLVMIRDialect: llvm.cond_br %[[COND_RES]], ^bb1, ^bb2
61+
!LLVMIRDialect: ^bb1: // pred: ^bb0
62+
!LLVMIRDialect: llvm.call @_FortranAioBeginExternalListOutput
63+
!LLVMIRDialect: llvm.call @_FortranAioOutputAscii
64+
!LLVMIRDialect: llvm.call @_FortranAioEndIoStatement
65+
!LLVMIRDialect: llvm.br ^bb2
66+
!LLVMIRDialect: ^bb2: // 2 preds: ^bb0, ^bb1
67+
!LLVMIRDialect: llvm.call @_FortranAioBeginExternalListOutput
68+
!LLVMIRDialect: llvm.load %[[VAR_C]] : !llvm.ptr<i32>
69+
!LLVMIRDialect: llvm.call @_FortranAioOutputInteger64
70+
!LLVMIRDialect: llvm.call @_FortranAioEndIoStatement
71+
!LLVMIRDialect: omp.terminator
72+
!LLVMIRDialect-NEXT: }
73+
74+
!LLVMIR: call {{.*}} @__kmpc_fork_call(%struct.ident_t* @{{.*}} @_QQmain..omp_par
75+
76+
!LLVMIR-LABEL: define internal void @_QQmain..omp_par
77+
!LLVMIR: br label %[[REGION_1:.*]]
78+
!LLVMIR: [[REGION_1]]:
79+
!LLVMIR: br label %[[REGION_1_1:.*]]
80+
!LLVMIR: [[REGION_1_1]]:
81+
!LLVMIR: %[[COND_RES:.*]] = icmp sgt i32 %{{.*}}, 4
82+
!LLVMIR: br i1 %[[COND_RES]], label %{{.*}}, label %{{.*}}
83+
!LLVMIR: call i8* @_FortranAioBeginExternalListOutput
84+
!LLVMIR: call i1 @_FortranAioOutputInteger64
85+
!LLVMIR: call i32 @_FortranAioEndIoStatement
86+
c = a + b
87+
88+
if (c .gt. 4) then
89+
print*, "Inside If Statement"
90+
endif
91+
92+
print*, c
93+
94+
!$OMP END PARALLEL
95+
96+
!$OMP PARALLEL
97+
print*, "Second Region"
98+
!FIRDialect: omp.parallel {
99+
!FIRDialect: fir.call @_FortranAioBeginExternalListOutput
100+
!FIRDialect: fir.call @_FortranAioOutputAscii
101+
!FIRDialect: fir.call @_FortranAioEndIoStatement
102+
!FIRDialect: omp.terminator
103+
!FIRDialect-NEXT: }
104+
105+
!LLVMIRDialect: omp.parallel {
106+
!LLVMIRDialect: llvm.call @_FortranAioBeginExternalListOutput
107+
!LLVMIRDialect: llvm.call @_FortranAioOutputAscii
108+
!LLVMIRDialect: llvm.call @_FortranAioEndIoStatement
109+
!LLVMIRDialect: omp.terminator
110+
!LLVMIRDialect: }
111+
112+
!LLVMIR-DAG-LABEL: call {{.*}} @__kmpc_fork_call(%struct.ident_t* @{{.*}} @_QQmain..omp_par.1
113+
!LLVMIR-DAG-LABEL: define internal void @_QQmain..omp_par.1
114+
!LLVMIR: call i8* @_FortranAioBeginExternalListOutput
115+
!LLVMIR: call i32 @_FortranAioEndIoStatement
116+
!$OMP END PARALLEL
117+
118+
end program

0 commit comments

Comments
 (0)