[flang][MLIR][OpenMP][llvm]Atomic Control Support (#150860)
This commit is contained in:
parent
6ccc9e559d
commit
9d642b0ec8
@ -2320,21 +2320,21 @@ def fsymbol_partition_EQ : Joined<["-"], "fsymbol-partition=">, Group<f_Group>,
|
||||
|
||||
defm atomic_remote_memory : BoolFOption<"atomic-remote-memory",
|
||||
LangOpts<"AtomicRemoteMemory">, DefaultFalse,
|
||||
PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">,
|
||||
NegFlag<SetFalse, [], [ClangOption], "Assume no">,
|
||||
BothFlags<[], [ClangOption], " atomic operations on remote memory">>;
|
||||
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May have">,
|
||||
NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">,
|
||||
BothFlags<[], [ClangOption, FlangOption], " atomic operations on remote memory">>;
|
||||
|
||||
defm atomic_fine_grained_memory : BoolFOption<"atomic-fine-grained-memory",
|
||||
LangOpts<"AtomicFineGrainedMemory">, DefaultFalse,
|
||||
PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">,
|
||||
NegFlag<SetFalse, [], [ClangOption], "Assume no">,
|
||||
BothFlags<[], [ClangOption], " atomic operations on fine-grained memory">>;
|
||||
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May have">,
|
||||
NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">,
|
||||
BothFlags<[], [ClangOption, FlangOption], " atomic operations on fine-grained memory">>;
|
||||
|
||||
defm atomic_ignore_denormal_mode : BoolFOption<"atomic-ignore-denormal-mode",
|
||||
LangOpts<"AtomicIgnoreDenormalMode">, DefaultFalse,
|
||||
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Allow">,
|
||||
NegFlag<SetFalse, [], [ClangOption], "Disallow">,
|
||||
BothFlags<[], [ClangOption], " atomic operations to ignore denormal mode">>;
|
||||
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "Allow">,
|
||||
NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disallow">,
|
||||
BothFlags<[], [ClangOption, FlangOption], " atomic operations to ignore denormal mode">>;
|
||||
|
||||
defm memory_profile : OptInCC1FFlag<"memory-profile", "Enable", "Disable", " heap memory profiling">;
|
||||
def fmemory_profile_EQ : Joined<["-"], "fmemory-profile=">,
|
||||
@ -5370,9 +5370,9 @@ defm amdgpu_precise_memory_op
|
||||
" precise memory mode (AMDGPU only)">;
|
||||
|
||||
def munsafe_fp_atomics : Flag<["-"], "munsafe-fp-atomics">,
|
||||
Visibility<[ClangOption, CC1Option]>, Alias<fatomic_ignore_denormal_mode>;
|
||||
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, Alias<fatomic_ignore_denormal_mode>;
|
||||
def mno_unsafe_fp_atomics : Flag<["-"], "mno-unsafe-fp-atomics">,
|
||||
Visibility<[ClangOption]>, Alias<fno_atomic_ignore_denormal_mode>;
|
||||
Visibility<[ClangOption, FlangOption]>, Alias<fno_atomic_ignore_denormal_mode>;
|
||||
|
||||
def faltivec : Flag<["-"], "faltivec">, Group<f_Group>;
|
||||
def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>;
|
||||
|
@ -53,6 +53,11 @@ public:
|
||||
|
||||
/// Print verbose assembly
|
||||
bool asmVerbose = false;
|
||||
|
||||
/// Atomic control options
|
||||
bool atomicIgnoreDenormalMode = false;
|
||||
bool atomicRemoteMemory = false;
|
||||
bool atomicFineGrainedMemory = false;
|
||||
};
|
||||
|
||||
} // end namespace Fortran::frontend
|
||||
|
@ -58,6 +58,25 @@ void setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
|
||||
/// Get the target CPU string from the Module or return a null reference.
|
||||
llvm::StringRef getTargetCPU(mlir::ModuleOp mod);
|
||||
|
||||
/// Sets whether Denormal Mode can be ignored or not for lowering of floating
|
||||
/// point atomic operations.
|
||||
void setAtomicIgnoreDenormalMode(mlir::ModuleOp mod, bool value);
|
||||
/// Gets whether Denormal Mode can be ignored or not for lowering of floating
|
||||
/// point atomic operations.
|
||||
bool getAtomicIgnoreDenormalMode(mlir::ModuleOp mod);
|
||||
/// Sets whether fine grained memory can be used or not for lowering of atomic
|
||||
/// operations.
|
||||
void setAtomicFineGrainedMemory(mlir::ModuleOp mod, bool value);
|
||||
/// Gets whether fine grained memory can be used or not for lowering of atomic
|
||||
/// operations.
|
||||
bool getAtomicFineGrainedMemory(mlir::ModuleOp mod);
|
||||
/// Sets whether remote memory can be used or not for lowering of atomic
|
||||
/// operations.
|
||||
void setAtomicRemoteMemory(mlir::ModuleOp mod, bool value);
|
||||
/// Gets whether remote memory can be used or not for lowering of atomic
|
||||
/// operations.
|
||||
bool getAtomicRemoteMemory(mlir::ModuleOp mod);
|
||||
|
||||
/// Set the tune CPU for the module. `cpu` must not be deallocated while
|
||||
/// module `mod` is still live.
|
||||
void setTuneCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
|
||||
|
@ -512,6 +512,16 @@ static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) {
|
||||
args.getLastArg(clang::driver::options::OPT_triple))
|
||||
opts.triple = a->getValue();
|
||||
|
||||
opts.atomicIgnoreDenormalMode = args.hasFlag(
|
||||
clang::driver::options::OPT_fatomic_ignore_denormal_mode,
|
||||
clang::driver::options::OPT_fno_atomic_ignore_denormal_mode, false);
|
||||
opts.atomicFineGrainedMemory = args.hasFlag(
|
||||
clang::driver::options::OPT_fatomic_fine_grained_memory,
|
||||
clang::driver::options::OPT_fno_atomic_fine_grained_memory, false);
|
||||
opts.atomicRemoteMemory =
|
||||
args.hasFlag(clang::driver::options::OPT_fatomic_remote_memory,
|
||||
clang::driver::options::OPT_fno_atomic_remote_memory, false);
|
||||
|
||||
if (const llvm::opt::Arg *a =
|
||||
args.getLastArg(clang::driver::options::OPT_target_cpu))
|
||||
opts.cpu = a->getValue();
|
||||
|
@ -6733,6 +6733,10 @@ Fortran::lower::LoweringBridge::LoweringBridge(
|
||||
fir::setKindMapping(*module, kindMap);
|
||||
fir::setTargetCPU(*module, targetMachine.getTargetCPU());
|
||||
fir::setTuneCPU(*module, targetOpts.cpuToTuneFor);
|
||||
fir::setAtomicIgnoreDenormalMode(*module,
|
||||
targetOpts.atomicIgnoreDenormalMode);
|
||||
fir::setAtomicFineGrainedMemory(*module, targetOpts.atomicFineGrainedMemory);
|
||||
fir::setAtomicRemoteMemory(*module, targetOpts.atomicRemoteMemory);
|
||||
fir::setTargetFeatures(*module, targetMachine.getTargetFeatureString());
|
||||
fir::support::setMLIRDataLayout(*module, targetMachine.createDataLayout());
|
||||
fir::setIdent(*module, Fortran::common::getFlangFullVersion());
|
||||
|
@ -635,9 +635,16 @@ genAtomicUpdate(lower::AbstractConverter &converter,
|
||||
}
|
||||
}
|
||||
|
||||
mlir::ModuleOp module = builder.getModule();
|
||||
mlir::omp::AtomicControlAttr atomicControlAttr =
|
||||
mlir::omp::AtomicControlAttr::get(
|
||||
builder.getContext(), fir::getAtomicIgnoreDenormalMode(module),
|
||||
fir::getAtomicFineGrainedMemory(module),
|
||||
fir::getAtomicRemoteMemory(module));
|
||||
builder.restoreInsertionPoint(atomicAt);
|
||||
auto updateOp = mlir::omp::AtomicUpdateOp::create(
|
||||
builder, loc, atomAddr, hint, makeMemOrderAttr(converter, memOrder));
|
||||
builder, loc, atomAddr, atomicControlAttr, hint,
|
||||
makeMemOrderAttr(converter, memOrder));
|
||||
|
||||
mlir::Region ®ion = updateOp->getRegion(0);
|
||||
mlir::Block *block = builder.createBlock(®ion, {}, {atomType}, {loc});
|
||||
|
@ -88,6 +88,57 @@ void fir::setTuneCPU(mlir::ModuleOp mod, llvm::StringRef cpu) {
|
||||
mod->setAttr(tuneCpuName, mlir::StringAttr::get(ctx, cpu));
|
||||
}
|
||||
|
||||
static constexpr const char *atomicIgnoreDenormalModeName =
|
||||
"fir.atomic_ignore_denormal_mode";
|
||||
|
||||
void fir::setAtomicIgnoreDenormalMode(mlir::ModuleOp mod, bool value) {
|
||||
if (value) {
|
||||
auto *ctx = mod.getContext();
|
||||
mod->setAttr(atomicIgnoreDenormalModeName, mlir::UnitAttr::get(ctx));
|
||||
} else {
|
||||
if (mod->hasAttr(atomicIgnoreDenormalModeName))
|
||||
mod->removeAttr(atomicIgnoreDenormalModeName);
|
||||
}
|
||||
}
|
||||
|
||||
bool fir::getAtomicIgnoreDenormalMode(mlir::ModuleOp mod) {
|
||||
return mod->hasAttr(atomicIgnoreDenormalModeName);
|
||||
}
|
||||
|
||||
static constexpr const char *atomicFineGrainedMemoryName =
|
||||
"fir.atomic_fine_grained_memory";
|
||||
|
||||
void fir::setAtomicFineGrainedMemory(mlir::ModuleOp mod, bool value) {
|
||||
if (value) {
|
||||
auto *ctx = mod.getContext();
|
||||
mod->setAttr(atomicFineGrainedMemoryName, mlir::UnitAttr::get(ctx));
|
||||
} else {
|
||||
if (mod->hasAttr(atomicFineGrainedMemoryName))
|
||||
mod->removeAttr(atomicFineGrainedMemoryName);
|
||||
}
|
||||
}
|
||||
|
||||
bool fir::getAtomicFineGrainedMemory(mlir::ModuleOp mod) {
|
||||
return mod->hasAttr(atomicFineGrainedMemoryName);
|
||||
}
|
||||
|
||||
static constexpr const char *atomicRemoteMemoryName =
|
||||
"fir.atomic_remote_memory";
|
||||
|
||||
void fir::setAtomicRemoteMemory(mlir::ModuleOp mod, bool value) {
|
||||
if (value) {
|
||||
auto *ctx = mod.getContext();
|
||||
mod->setAttr(atomicRemoteMemoryName, mlir::UnitAttr::get(ctx));
|
||||
} else {
|
||||
if (mod->hasAttr(atomicRemoteMemoryName))
|
||||
mod->removeAttr(atomicRemoteMemoryName);
|
||||
}
|
||||
}
|
||||
|
||||
bool fir::getAtomicRemoteMemory(mlir::ModuleOp mod) {
|
||||
return mod->hasAttr(atomicRemoteMemoryName);
|
||||
}
|
||||
|
||||
llvm::StringRef fir::getTuneCPU(mlir::ModuleOp mod) {
|
||||
if (auto attr = mod->getAttrOfType<mlir::StringAttr>(tuneCpuName))
|
||||
return attr.getValue();
|
||||
|
37
flang/test/Lower/OpenMP/atomic-control-options.f90
Normal file
37
flang/test/Lower/OpenMP/atomic-control-options.f90
Normal file
@ -0,0 +1,37 @@
|
||||
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device -munsafe-fp-atomics %s -o - | FileCheck -check-prefix=UNSAFE-FP-ATOMICS %s
|
||||
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device -fatomic-ignore-denormal-mode %s -o - | FileCheck -check-prefix=IGNORE-DENORMAL %s
|
||||
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device -fatomic-fine-grained-memory %s -o - | FileCheck -check-prefix=FINE-GRAINED-MEMORY %s
|
||||
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device -fatomic-remote-memory %s -o - | FileCheck -check-prefix=REMOTE-MEMORY %s
|
||||
program test
|
||||
implicit none
|
||||
integer :: A, B, threads
|
||||
threads = 128
|
||||
A = 0
|
||||
B = 0
|
||||
!UNSAFE-FP-ATOMICS: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!UNSAFE-FP-ATOMICS: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
|
||||
!IGNORE-DENORMAL: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!IGNORE-DENORMAL: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
|
||||
!FINE-GRAINED-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!FINE-GRAINED-MEMORY: } {atomic_control = #omp.atomic_control<fine_grained_memory = true>}
|
||||
!REMOTE-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!REMOTE-MEMORY: } {atomic_control = #omp.atomic_control<remote_memory = true>}
|
||||
!$omp target parallel num_threads(threads)
|
||||
!$omp atomic
|
||||
A = A + 1
|
||||
!$omp end target parallel
|
||||
!UNSAFE-FP-ATOMICS: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!UNSAFE-FP-ATOMICS: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
|
||||
!IGNORE-DENORMAL: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!IGNORE-DENORMAL: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
|
||||
!FINE-GRAINED-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!FINE-GRAINED-MEMORY: } {atomic_control = #omp.atomic_control<fine_grained_memory = true>}
|
||||
!REMOTE-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
|
||||
!REMOTE-MEMORY: } {atomic_control = #omp.atomic_control<remote_memory = true>}
|
||||
!$omp target parallel num_threads(threads)
|
||||
!$omp atomic capture
|
||||
A = A + B
|
||||
B = A
|
||||
!$omp end atomic
|
||||
!$omp end target parallel
|
||||
end program test
|
@ -22,6 +22,21 @@ class OpenMP_Attr<string name, string attrMnemonic, list<Trait> traits = [],
|
||||
let mnemonic = attrMnemonic;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AtomicControlAttr
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Atomic control attributes hold information about architectural
|
||||
// characteristics which are required for lowering atomic operations.
|
||||
def AtomicControlAttr : OpenMP_Attr<"AtomicControl", "atomic_control"> {
|
||||
let parameters =
|
||||
(ins DefaultValuedParameter<"bool", "false">:$ignore_denormal_mode,
|
||||
DefaultValuedParameter<"bool", "false">:$fine_grained_memory,
|
||||
DefaultValuedParameter<"bool", "false">:$remote_memory);
|
||||
|
||||
let assemblyFormat = "`<` struct(params) `>`";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DeclareTargetAttr
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1750,9 +1750,11 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", traits = [
|
||||
operations.
|
||||
}] # clausesDescription;
|
||||
|
||||
let arguments = !con((ins Arg<OpenMP_PointerLikeType,
|
||||
"Address of variable to be updated",
|
||||
[MemRead, MemWrite]>:$x), clausesArgs);
|
||||
let arguments = !con(
|
||||
(ins Arg<OpenMP_PointerLikeType,
|
||||
"Address of variable to be updated", [MemRead, MemWrite]>:$x,
|
||||
OptionalAttr<AtomicControlAttr>:$atomic_control),
|
||||
clausesArgs);
|
||||
|
||||
// Override region definition.
|
||||
let regions = (region SizedRegion<1>:$region);
|
||||
|
@ -1406,7 +1406,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>,
|
||||
// CHECK-NEXT: (%[[XVAL:.*]]: i1):
|
||||
// CHECK-NEXT: %[[NEWVAL:.*]] = llvm.icmp "eq" %[[XVAL]], %[[EXPRBOOL]] : i1
|
||||
// CHECK-NEXT: omp.yield(%[[NEWVAL]] : i1)
|
||||
// }
|
||||
// CHECK-NEXT: }
|
||||
omp.atomic.update %xBool : memref<i1> {
|
||||
^bb0(%xval: i1):
|
||||
%newval = llvm.icmp "eq" %xval, %exprBool : i1
|
||||
@ -1562,6 +1562,14 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>,
|
||||
omp.yield(%newval : i32)
|
||||
}
|
||||
|
||||
// CHECK: omp.atomic.update %[[X]] : memref<i32> {
|
||||
// CHECK-NEXT: (%[[XVAL:.*]]: i32):
|
||||
// CHECK-NEXT: omp.yield(%{{.+}} : i32)
|
||||
// CHECK-NEXT: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true, fine_grained_memory = true, remote_memory = true>}
|
||||
omp.atomic.update %x : memref<i32> {
|
||||
^bb0(%xval:i32):
|
||||
omp.yield(%const:i32)
|
||||
} {atomic_control = #omp.atomic_control<ignore_denormal_mode = true, fine_grained_memory = true, remote_memory = true>}
|
||||
return
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user