Skip to content

Commit a0f4349

Browse files
anchurajmahesh-attarde
authored andcommitted
[flang][flang-driver][mlir][OpenMP] atomic control support (llvm#143441)
Atomic Control Options are used to specify architectural characteristics to help lowering of atomic operations. The options used are: `-f[no-]atomic-remote-memory`, `-f[no-]atomic-fine-grained-memory`, `-f[no-]atomic-ignore-denormal-mode`. Legacy option `-m[no-]unsafe-fp-atomics` is aliased to `-f[no-]ignore-denormal-mode`. More details can be found in llvm#102569. This PR implements the frontend support for these options with OpenMP atomic in flang. Backend changes are available in the draft PR: llvm#143769 which will be raised after this merged.
1 parent 2f0295e commit a0f4349

File tree

11 files changed

+174
-16
lines changed

11 files changed

+174
-16
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,21 +2320,21 @@ def fsymbol_partition_EQ : Joined<["-"], "fsymbol-partition=">, Group<f_Group>,
23202320

23212321
defm atomic_remote_memory : BoolFOption<"atomic-remote-memory",
23222322
LangOpts<"AtomicRemoteMemory">, DefaultFalse,
2323-
PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">,
2324-
NegFlag<SetFalse, [], [ClangOption], "Assume no">,
2325-
BothFlags<[], [ClangOption], " atomic operations on remote memory">>;
2323+
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May have">,
2324+
NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">,
2325+
BothFlags<[], [ClangOption, FlangOption], " atomic operations on remote memory">>;
23262326

23272327
defm atomic_fine_grained_memory : BoolFOption<"atomic-fine-grained-memory",
23282328
LangOpts<"AtomicFineGrainedMemory">, DefaultFalse,
2329-
PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">,
2330-
NegFlag<SetFalse, [], [ClangOption], "Assume no">,
2331-
BothFlags<[], [ClangOption], " atomic operations on fine-grained memory">>;
2329+
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May have">,
2330+
NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">,
2331+
BothFlags<[], [ClangOption, FlangOption], " atomic operations on fine-grained memory">>;
23322332

23332333
defm atomic_ignore_denormal_mode : BoolFOption<"atomic-ignore-denormal-mode",
23342334
LangOpts<"AtomicIgnoreDenormalMode">, DefaultFalse,
2335-
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Allow">,
2336-
NegFlag<SetFalse, [], [ClangOption], "Disallow">,
2337-
BothFlags<[], [ClangOption], " atomic operations to ignore denormal mode">>;
2335+
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "Allow">,
2336+
NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disallow">,
2337+
BothFlags<[], [ClangOption, FlangOption], " atomic operations to ignore denormal mode">>;
23382338

23392339
defm memory_profile : OptInCC1FFlag<"memory-profile", "Enable", "Disable", " heap memory profiling">;
23402340
def fmemory_profile_EQ : Joined<["-"], "fmemory-profile=">,
@@ -5360,9 +5360,9 @@ defm amdgpu_precise_memory_op
53605360
" precise memory mode (AMDGPU only)">;
53615361

53625362
def munsafe_fp_atomics : Flag<["-"], "munsafe-fp-atomics">,
5363-
Visibility<[ClangOption, CC1Option]>, Alias<fatomic_ignore_denormal_mode>;
5363+
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, Alias<fatomic_ignore_denormal_mode>;
53645364
def mno_unsafe_fp_atomics : Flag<["-"], "mno-unsafe-fp-atomics">,
5365-
Visibility<[ClangOption]>, Alias<fno_atomic_ignore_denormal_mode>;
5365+
Visibility<[ClangOption, FlangOption]>, Alias<fno_atomic_ignore_denormal_mode>;
53665366

53675367
def faltivec : Flag<["-"], "faltivec">, Group<f_Group>;
53685368
def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>;

flang/include/flang/Frontend/TargetOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ class TargetOptions {
5353

5454
/// Print verbose assembly
5555
bool asmVerbose = false;
56+
57+
/// Atomic control options
58+
bool atomicIgnoreDenormalMode = false;
59+
bool atomicRemoteMemory = false;
60+
bool atomicFineGrainedMemory = false;
5661
};
5762

5863
} // end namespace Fortran::frontend

flang/include/flang/Optimizer/Dialect/Support/FIRContext.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,25 @@ void setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
5858
/// Get the target CPU string from the Module or return a null reference.
5959
llvm::StringRef getTargetCPU(mlir::ModuleOp mod);
6060

61+
/// Sets whether Denormal Mode can be ignored or not for lowering of floating
62+
/// point atomic operations.
63+
void setAtomicIgnoreDenormalMode(mlir::ModuleOp mod, bool value);
64+
/// Gets whether Denormal Mode can be ignored or not for lowering of floating
65+
/// point atomic operations.
66+
bool getAtomicIgnoreDenormalMode(mlir::ModuleOp mod);
67+
/// Sets whether fine grained memory can be used or not for lowering of atomic
68+
/// operations.
69+
void setAtomicFineGrainedMemory(mlir::ModuleOp mod, bool value);
70+
/// Gets whether fine grained memory can be used or not for lowering of atomic
71+
/// operations.
72+
bool getAtomicFineGrainedMemory(mlir::ModuleOp mod);
73+
/// Sets whether remote memory can be used or not for lowering of atomic
74+
/// operations.
75+
void setAtomicRemoteMemory(mlir::ModuleOp mod, bool value);
76+
/// Gets whether remote memory can be used or not for lowering of atomic
77+
/// operations.
78+
bool getAtomicRemoteMemory(mlir::ModuleOp mod);
79+
6180
/// Set the tune CPU for the module. `cpu` must not be deallocated while
6281
/// module `mod` is still live.
6382
void setTuneCPU(mlir::ModuleOp mod, llvm::StringRef cpu);

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,16 @@ static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) {
512512
args.getLastArg(clang::driver::options::OPT_triple))
513513
opts.triple = a->getValue();
514514

515+
opts.atomicIgnoreDenormalMode = args.hasFlag(
516+
clang::driver::options::OPT_fatomic_ignore_denormal_mode,
517+
clang::driver::options::OPT_fno_atomic_ignore_denormal_mode, false);
518+
opts.atomicFineGrainedMemory = args.hasFlag(
519+
clang::driver::options::OPT_fatomic_fine_grained_memory,
520+
clang::driver::options::OPT_fno_atomic_fine_grained_memory, false);
521+
opts.atomicRemoteMemory =
522+
args.hasFlag(clang::driver::options::OPT_fatomic_remote_memory,
523+
clang::driver::options::OPT_fno_atomic_remote_memory, false);
524+
515525
if (const llvm::opt::Arg *a =
516526
args.getLastArg(clang::driver::options::OPT_target_cpu))
517527
opts.cpu = a->getValue();

flang/lib/Lower/Bridge.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6733,6 +6733,10 @@ Fortran::lower::LoweringBridge::LoweringBridge(
67336733
fir::setKindMapping(*module, kindMap);
67346734
fir::setTargetCPU(*module, targetMachine.getTargetCPU());
67356735
fir::setTuneCPU(*module, targetOpts.cpuToTuneFor);
6736+
fir::setAtomicIgnoreDenormalMode(*module,
6737+
targetOpts.atomicIgnoreDenormalMode);
6738+
fir::setAtomicFineGrainedMemory(*module, targetOpts.atomicFineGrainedMemory);
6739+
fir::setAtomicRemoteMemory(*module, targetOpts.atomicRemoteMemory);
67366740
fir::setTargetFeatures(*module, targetMachine.getTargetFeatureString());
67376741
fir::support::setMLIRDataLayout(*module, targetMachine.createDataLayout());
67386742
fir::setIdent(*module, Fortran::common::getFlangFullVersion());

flang/lib/Lower/OpenMP/Atomic.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,9 +635,16 @@ genAtomicUpdate(lower::AbstractConverter &converter,
635635
}
636636
}
637637

638+
mlir::ModuleOp module = builder.getModule();
639+
mlir::omp::AtomicControlAttr atomicControlAttr =
640+
mlir::omp::AtomicControlAttr::get(
641+
builder.getContext(), fir::getAtomicIgnoreDenormalMode(module),
642+
fir::getAtomicFineGrainedMemory(module),
643+
fir::getAtomicRemoteMemory(module));
638644
builder.restoreInsertionPoint(atomicAt);
639645
auto updateOp = mlir::omp::AtomicUpdateOp::create(
640-
builder, loc, atomAddr, hint, makeMemOrderAttr(converter, memOrder));
646+
builder, loc, atomAddr, atomicControlAttr, hint,
647+
makeMemOrderAttr(converter, memOrder));
641648

642649
mlir::Region &region = updateOp->getRegion(0);
643650
mlir::Block *block = builder.createBlock(&region, {}, {atomType}, {loc});

flang/lib/Optimizer/Dialect/Support/FIRContext.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,57 @@ void fir::setTuneCPU(mlir::ModuleOp mod, llvm::StringRef cpu) {
8888
mod->setAttr(tuneCpuName, mlir::StringAttr::get(ctx, cpu));
8989
}
9090

91+
static constexpr const char *atomicIgnoreDenormalModeName =
92+
"fir.atomic_ignore_denormal_mode";
93+
94+
void fir::setAtomicIgnoreDenormalMode(mlir::ModuleOp mod, bool value) {
95+
if (value) {
96+
auto *ctx = mod.getContext();
97+
mod->setAttr(atomicIgnoreDenormalModeName, mlir::UnitAttr::get(ctx));
98+
} else {
99+
if (mod->hasAttr(atomicIgnoreDenormalModeName))
100+
mod->removeAttr(atomicIgnoreDenormalModeName);
101+
}
102+
}
103+
104+
bool fir::getAtomicIgnoreDenormalMode(mlir::ModuleOp mod) {
105+
return mod->hasAttr(atomicIgnoreDenormalModeName);
106+
}
107+
108+
static constexpr const char *atomicFineGrainedMemoryName =
109+
"fir.atomic_fine_grained_memory";
110+
111+
void fir::setAtomicFineGrainedMemory(mlir::ModuleOp mod, bool value) {
112+
if (value) {
113+
auto *ctx = mod.getContext();
114+
mod->setAttr(atomicFineGrainedMemoryName, mlir::UnitAttr::get(ctx));
115+
} else {
116+
if (mod->hasAttr(atomicFineGrainedMemoryName))
117+
mod->removeAttr(atomicFineGrainedMemoryName);
118+
}
119+
}
120+
121+
bool fir::getAtomicFineGrainedMemory(mlir::ModuleOp mod) {
122+
return mod->hasAttr(atomicFineGrainedMemoryName);
123+
}
124+
125+
static constexpr const char *atomicRemoteMemoryName =
126+
"fir.atomic_remote_memory";
127+
128+
void fir::setAtomicRemoteMemory(mlir::ModuleOp mod, bool value) {
129+
if (value) {
130+
auto *ctx = mod.getContext();
131+
mod->setAttr(atomicRemoteMemoryName, mlir::UnitAttr::get(ctx));
132+
} else {
133+
if (mod->hasAttr(atomicRemoteMemoryName))
134+
mod->removeAttr(atomicRemoteMemoryName);
135+
}
136+
}
137+
138+
bool fir::getAtomicRemoteMemory(mlir::ModuleOp mod) {
139+
return mod->hasAttr(atomicRemoteMemoryName);
140+
}
141+
91142
llvm::StringRef fir::getTuneCPU(mlir::ModuleOp mod) {
92143
if (auto attr = mod->getAttrOfType<mlir::StringAttr>(tuneCpuName))
93144
return attr.getValue();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp -fopenmp-is-device -munsafe-fp-atomics %s -o - | FileCheck -check-prefix=UNSAFE-FP-ATOMICS %s
2+
! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp -fopenmp-is-device -fatomic-ignore-denormal-mode %s -o - | FileCheck -check-prefix=IGNORE-DENORMAL %s
3+
! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp -fopenmp-is-device -fatomic-fine-grained-memory %s -o - | FileCheck -check-prefix=FINE-GRAINED-MEMORY %s
4+
! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp -fopenmp-is-device -fatomic-remote-memory %s -o - | FileCheck -check-prefix=REMOTE-MEMORY %s
5+
program test
6+
implicit none
7+
integer :: A, B, threads
8+
threads = 128
9+
A = 0
10+
B = 0
11+
!UNSAFE-FP-ATOMICS: omp.atomic.update %{{.*}} : !fir.ref<i32> {
12+
!UNSAFE-FP-ATOMICS: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
13+
!IGNORE-DENORMAL: omp.atomic.update %{{.*}} : !fir.ref<i32> {
14+
!IGNORE-DENORMAL: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
15+
!FINE-GRAINED-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
16+
!FINE-GRAINED-MEMORY: } {atomic_control = #omp.atomic_control<fine_grained_memory = true>}
17+
!REMOTE-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
18+
!REMOTE-MEMORY: } {atomic_control = #omp.atomic_control<remote_memory = true>}
19+
!$omp target parallel num_threads(threads)
20+
!$omp atomic
21+
A = A + 1
22+
!$omp end target parallel
23+
!UNSAFE-FP-ATOMICS: omp.atomic.update %{{.*}} : !fir.ref<i32> {
24+
!UNSAFE-FP-ATOMICS: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
25+
!IGNORE-DENORMAL: omp.atomic.update %{{.*}} : !fir.ref<i32> {
26+
!IGNORE-DENORMAL: } {atomic_control = #omp.atomic_control<ignore_denormal_mode = true>}
27+
!FINE-GRAINED-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
28+
!FINE-GRAINED-MEMORY: } {atomic_control = #omp.atomic_control<fine_grained_memory = true>}
29+
!REMOTE-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
30+
!REMOTE-MEMORY: } {atomic_control = #omp.atomic_control<remote_memory = true>}
31+
!$omp target parallel num_threads(threads)
32+
!$omp atomic capture
33+
A = A + B
34+
B = A
35+
!$omp end atomic
36+
!$omp end target parallel
37+
end program test

mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,21 @@ class OpenMP_Attr<string name, string attrMnemonic, list<Trait> traits = [],
2222
let mnemonic = attrMnemonic;
2323
}
2424

25+
//===----------------------------------------------------------------------===//
26+
// AtomicControlAttr
27+
//===----------------------------------------------------------------------===//
28+
29+
// Atomic control attributes hold information about architectural
30+
// characteristics which are required for lowering atomic operations.
31+
def AtomicControlAttr : OpenMP_Attr<"AtomicControl", "atomic_control"> {
32+
let parameters =
33+
(ins DefaultValuedParameter<"bool", "false">:$ignore_denormal_mode,
34+
DefaultValuedParameter<"bool", "false">:$fine_grained_memory,
35+
DefaultValuedParameter<"bool", "false">:$remote_memory);
36+
37+
let assemblyFormat = "`<` struct(params) `>`";
38+
}
39+
2540
//===----------------------------------------------------------------------===//
2641
// DeclareTargetAttr
2742
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,9 +1750,11 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", traits = [
17501750
operations.
17511751
}] # clausesDescription;
17521752

1753-
let arguments = !con((ins Arg<OpenMP_PointerLikeType,
1754-
"Address of variable to be updated",
1755-
[MemRead, MemWrite]>:$x), clausesArgs);
1753+
let arguments = !con(
1754+
(ins Arg<OpenMP_PointerLikeType,
1755+
"Address of variable to be updated", [MemRead, MemWrite]>:$x,
1756+
OptionalAttr<AtomicControlAttr>:$atomic_control),
1757+
clausesArgs);
17561758

17571759
// Override region definition.
17581760
let regions = (region SizedRegion<1>:$region);

0 commit comments

Comments
 (0)