forked from OSchip/llvm-project
[Flang] Add OpenMP Conversion patterns
This patch adds the OpenMP conversion patterns to the FIR to LLVM dialect lowering pass in Codegen. Appropriate legalization conditions are also added. This ensures that a mix of FIR and OpenMP dialects can be lowered to LLVM and OpenMP dialects. Also adds two tests. This is part of the upstreaming effort from the fir-dev branch in [1]. [1] https://github.com/flang-compiler/f18-llvm-project Reviewed By: clementval, peixin Differential Revision: https://reviews.llvm.org/D121793 Co-authored-by: Sourabh Singh Tomar <SourabhSingh.Tomar@amd.com> Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
This commit is contained in:
parent
7a2e12e0a7
commit
c6ac937091
|
@ -23,6 +23,7 @@
|
|||
#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
|
||||
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
|
||||
#include "mlir/Conversion/LLVMCommon/Pattern.h"
|
||||
#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
|
||||
#include "mlir/IR/BuiltinTypes.h"
|
||||
#include "mlir/IR/Matchers.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
|
@ -3328,12 +3329,21 @@ public:
|
|||
XEmboxOpConversion, XReboxOpConversion, ZeroOpConversion>(typeConverter,
|
||||
options);
|
||||
mlir::populateFuncToLLVMConversionPatterns(typeConverter, pattern);
|
||||
mlir::populateOpenMPToLLVMConversionPatterns(typeConverter, pattern);
|
||||
mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter,
|
||||
pattern);
|
||||
mlir::cf::populateControlFlowToLLVMConversionPatterns(typeConverter,
|
||||
pattern);
|
||||
mlir::ConversionTarget target{*context};
|
||||
target.addLegalDialect<mlir::LLVM::LLVMDialect>();
|
||||
// The OpenMP dialect is legal for Operations without regions, for those
|
||||
// which contains regions it is legal if the region contains only the
|
||||
// LLVM dialect.
|
||||
target.addDynamicallyLegalOp<mlir::omp::ParallelOp, mlir::omp::WsLoopOp,
|
||||
mlir::omp::MasterOp>([&](Operation *op) {
|
||||
return typeConverter.isLegal(&op->getRegion(0));
|
||||
});
|
||||
target.addLegalDialect<mlir::omp::OpenMPDialect>();
|
||||
|
||||
// required NOPs for applying a full conversion
|
||||
target.addLegalOp<mlir::ModuleOp>();
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
|
||||
|
||||
func @_QPsb1(%arg0: !fir.ref<i32> {fir.bindc_name = "n"}, %arg1: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr"}) {
|
||||
%c1_i64 = arith.constant 1 : i64
|
||||
%c1_i32 = arith.constant 1 : i32
|
||||
%0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsbEi"}
|
||||
omp.parallel {
|
||||
%1 = fir.alloca i32 {adapt.valuebyref, pinned}
|
||||
%2 = fir.load %arg0 : !fir.ref<i32>
|
||||
omp.wsloop (%arg2) : i32 = (%c1_i32) to (%2) inclusive step (%c1_i32) nowait {
|
||||
fir.store %arg2 to %1 : !fir.ref<i32>
|
||||
%3 = fir.load %1 : !fir.ref<i32>
|
||||
%4 = fir.convert %3 : (i32) -> i64
|
||||
%5 = arith.subi %4, %c1_i64 : i64
|
||||
%6 = fir.coordinate_of %arg1, %5 : (!fir.ref<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
|
||||
fir.store %3 to %6 : !fir.ref<i32>
|
||||
omp.yield
|
||||
}
|
||||
omp.terminator
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: _QPsb1
|
||||
// CHECK-SAME: %[[N_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "n"}, %[[ARR_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "arr"}) {
|
||||
// CHECK: %[[ONE_1:.*]] = llvm.mlir.constant(1 : i64) : i64
|
||||
// CHECK: %[[ONE_2:.*]] = llvm.mlir.constant(1 : i32) : i32
|
||||
// CHECK: omp.parallel {
|
||||
// CHECK: %[[ONE_3:.*]] = llvm.mlir.constant(1 : i64) : i64
|
||||
// CHECK: %[[I_VAR:.*]] = llvm.alloca %[[ONE_3]] x i32 {adapt.valuebyref, in_type = i32, operand_segment_sizes = dense<0> : vector<2xi32>, pinned} : (i64) -> !llvm.ptr<i32>
|
||||
// CHECK: %[[N:.*]] = llvm.load %[[N_REF]] : !llvm.ptr<i32>
|
||||
// CHECK: omp.wsloop (%[[I:.*]]) : i32 = (%[[ONE_2]]) to (%[[N]]) inclusive step (%[[ONE_2]]) nowait {
|
||||
// CHECK: llvm.store %[[I]], %[[I_VAR]] : !llvm.ptr<i32>
|
||||
// CHECK: %[[I1:.*]] = llvm.load %[[I_VAR]] : !llvm.ptr<i32>
|
||||
// CHECK: %[[I1_EXT:.*]] = llvm.sext %[[I1]] : i32 to i64
|
||||
// CHECK: %[[I_CSTYLE:.*]] = llvm.sub %[[I1_EXT]], %[[ONE_1]] : i64
|
||||
// CHECK: %[[ARR_I_REF:.*]] = llvm.getelementptr %[[ARR_REF]][%[[I_CSTYLE]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
|
||||
// CHECK: llvm.store %[[I1]], %[[ARR_I_REF]] : !llvm.ptr<i32>
|
||||
// CHECK: omp.yield
|
||||
// CHECK: }
|
||||
// CHECK: omp.terminator
|
||||
// CHECK: }
|
||||
// CHECK: llvm.return
|
||||
// CHECK: }
|
||||
|
||||
// -----
|
||||
|
||||
func @_QPsb2(%arg0: !fir.ref<i32> {fir.bindc_name = "x"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) {
|
||||
omp.parallel {
|
||||
omp.master {
|
||||
%0 = fir.load %arg1 : !fir.ref<i32>
|
||||
fir.store %0 to %arg0 : !fir.ref<i32>
|
||||
omp.terminator
|
||||
}
|
||||
omp.terminator
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: _QPsb2
|
||||
// CHECK-SAME: %[[X_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "x"}, %[[N_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "n"}) {
|
||||
// CHECK: omp.parallel {
|
||||
// CHECK: omp.master {
|
||||
// CHECK: %[[N:.*]] = llvm.load %[[N_REF]] : !llvm.ptr<i32>
|
||||
// CHECK: llvm.store %[[N]], %[[X_REF]] : !llvm.ptr<i32>
|
||||
// CHECK: omp.terminator
|
||||
// CHECK: }
|
||||
// CHECK: omp.terminator
|
||||
// CHECK: }
|
||||
// CHECK: llvm.return
|
||||
// CHECK: }
|
Loading…
Reference in New Issue