Skip to content

Commit d9415cd

Browse files
committed
[OpenMP][JIT] Introduce more debugging configuration options
The JIT is a great debugging tool since we can modify the IR manually before launching it in an existing test case. The new flasks allow to skip optimizations, to use the exact given IR, as well as to provide a finished object file. The latter is useful to try out different backend options and to have complete freedom with pass pipelines. Documentation is included. Minimal refactoring was performed to make the second object fit in nicely.
1 parent f8e094b commit d9415cd

File tree

3 files changed

+64
-16
lines changed

3 files changed

+64
-16
lines changed

openmp/docs/design/Runtimes.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,8 @@ variables is defined below.
714714
* ``LIBOMPTARGET_SHARED_MEMORY_SIZE=<Num>``
715715
* ``LIBOMPTARGET_MAP_FORCE_ATOMIC=[TRUE/FALSE] (default TRUE)``
716716
* ``LIBOMPTARGET_JIT_OPT_LEVEL={0,1,2,3} (default 3)``
717+
* ``LIBOMPTARGET_JIT_SKIP_OPT=[TRUE/FALSE] (default FALSE)``
718+
* ``LIBOMPTARGET_JIT_REPLACEMENT_OBJECT=<in:Filename> (object file)``
717719
* ``LIBOMPTARGET_JIT_REPLACEMENT_MODULE=<in:Filename> (LLVM-IR file)``
718720
* ``LIBOMPTARGET_JIT_PRE_OPT_IR_MODULE=<out:Filename> (LLVM-IR file)``
719721
* ``LIBOMPTARGET_JIT_POST_OPT_IR_MODULE=<out:Filename> (LLVM-IR file)``
@@ -1062,6 +1064,22 @@ This environment variable can be used to change the optimization pipeleine used
10621064
to optimize the embedded device code as part of the device JIT. The value is
10631065
corresponds to the ``-O{0,1,2,3}`` command line argument passed to ``clang``.
10641066

1067+
LIBOMPTARGET_JIT_SKIP_OPT
1068+
""""""""""""""""""""""""""
1069+
1070+
This environment variable can be used to skip the optimization pipeline during
1071+
JIT compilation. If set, the image will only be passed through the backend. The
1072+
backend is invoked with the ``LIBOMPTARGET_JIT_OPT_LEVEL`` flag.
1073+
1074+
LIBOMPTARGET_JIT_REPLACEMENT_OBJECT
1075+
"""""""""""""""""""""""""""""""""""
1076+
1077+
This environment variable can be used to replace the embedded device code
1078+
before the device JIT finishes compilation for the target. The value is
1079+
expected to be a filename to an object file, thus containing the output of the
1080+
assembler in object format for the respective target. The JIT optimization
1081+
pipeline and backend are skipped and only target specific post-processing is
1082+
performed on the object file before it is loaded onto the device.
10651083

10661084
LIBOMPTARGET_JIT_REPLACEMENT_MODULE
10671085
"""""""""""""""""""""""""""""""""""

openmp/libomptarget/plugins-nextgen/common/PluginInterface/JIT.cpp

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,8 @@ JITEngine::backend(Module &M, const std::string &ComputeUnitKind,
275275
M.print(FD, nullptr);
276276
}
277277

278-
opt(TM.get(), &TLII, M, OptLevel);
278+
if (!JITSkipOpt)
279+
opt(TM.get(), &TLII, M, OptLevel);
279280

280281
if (PostOptIRModuleFileName.isPresent()) {
281282
std::error_code EC;
@@ -296,23 +297,27 @@ JITEngine::backend(Module &M, const std::string &ComputeUnitKind,
296297
return MemoryBuffer::getMemBufferCopy(OS.str());
297298
}
298299

299-
Expected<const __tgt_device_image *>
300-
JITEngine::compile(const __tgt_device_image &Image,
301-
const std::string &ComputeUnitKind,
302-
PostProcessingFn PostProcessing) {
303-
std::lock_guard<std::mutex> Lock(ComputeUnitMapMutex);
300+
Expected<std::unique_ptr<MemoryBuffer>>
301+
JITEngine::getOrCreateObjFile(const __tgt_device_image &Image, LLVMContext &Ctx,
302+
const std::string &ComputeUnitKind) {
304303

305-
// Check if we JITed this image for the given compute unit kind before.
306-
ComputeUnitInfo &CUI = ComputeUnitMap[ComputeUnitKind];
307-
if (__tgt_device_image *JITedImage = CUI.TgtImageMap.lookup(&Image))
308-
return JITedImage;
304+
// Check if the user replaces the module at runtime with a finished object.
305+
if (ReplacementObjectFileName.isPresent()) {
306+
auto MBOrErr =
307+
MemoryBuffer::getFileOrSTDIN(ReplacementObjectFileName.get());
308+
if (!MBOrErr)
309+
return createStringError(MBOrErr.getError(),
310+
"Could not read replacement obj from %s\n",
311+
ReplacementModuleFileName.get().c_str());
312+
return std::move(*MBOrErr);
313+
}
309314

310315
Module *Mod = nullptr;
311316
// Check if the user replaces the module at runtime or we read it from the
312317
// image.
313318
// TODO: Allow the user to specify images per device (Arch + ComputeUnitKind).
314319
if (!ReplacementModuleFileName.isPresent()) {
315-
auto ModOrErr = createModuleFromImage(Image, CUI.Context);
320+
auto ModOrErr = createModuleFromImage(Image, Ctx);
316321
if (!ModOrErr)
317322
return ModOrErr.takeError();
318323
Mod = ModOrErr->release();
@@ -323,17 +328,31 @@ JITEngine::compile(const __tgt_device_image &Image,
323328
return createStringError(MBOrErr.getError(),
324329
"Could not read replacement module from %s\n",
325330
ReplacementModuleFileName.get().c_str());
326-
auto ModOrErr = createModuleFromMemoryBuffer(MBOrErr.get(), CUI.Context);
331+
auto ModOrErr = createModuleFromMemoryBuffer(MBOrErr.get(), Ctx);
327332
if (!ModOrErr)
328333
return ModOrErr.takeError();
329334
Mod = ModOrErr->release();
330335
}
331336

332-
auto MBOrError = backend(*Mod, ComputeUnitKind, JITOptLevel);
333-
if (!MBOrError)
334-
return MBOrError.takeError();
337+
return backend(*Mod, ComputeUnitKind, JITOptLevel);
338+
}
339+
340+
Expected<const __tgt_device_image *>
341+
JITEngine::compile(const __tgt_device_image &Image,
342+
const std::string &ComputeUnitKind,
343+
PostProcessingFn PostProcessing) {
344+
std::lock_guard<std::mutex> Lock(ComputeUnitMapMutex);
345+
346+
// Check if we JITed this image for the given compute unit kind before.
347+
ComputeUnitInfo &CUI = ComputeUnitMap[ComputeUnitKind];
348+
if (__tgt_device_image *JITedImage = CUI.TgtImageMap.lookup(&Image))
349+
return JITedImage;
350+
351+
auto ObjMBOrErr = getOrCreateObjFile(Image, CUI.Context, ComputeUnitKind);
352+
if (!ObjMBOrErr)
353+
return ObjMBOrErr.takeError();
335354

336-
auto ImageMBOrErr = PostProcessing(std::move(*MBOrError));
355+
auto ImageMBOrErr = PostProcessing(std::move(*ObjMBOrErr));
337356
if (!ImageMBOrErr)
338357
return ImageMBOrErr.takeError();
339358

openmp/libomptarget/plugins-nextgen/common/PluginInterface/JIT.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ADT/StringRef.h"
1818
#include "llvm/ADT/Triple.h"
1919
#include "llvm/Analysis/TargetLibraryInfo.h"
20+
#include "llvm/IR/LLVMContext.h"
2021
#include "llvm/IR/Module.h"
2122
#include "llvm/Support/Error.h"
2223
#include "llvm/Target/TargetMachine.h"
@@ -67,6 +68,12 @@ struct JITEngine {
6768
compile(const __tgt_device_image &Image, const std::string &ComputeUnitKind,
6869
PostProcessingFn PostProcessing);
6970

71+
/// Create or retrieve the object image file from the file system or via
72+
/// compilation of the \p Image.
73+
Expected<std::unique_ptr<MemoryBuffer>>
74+
getOrCreateObjFile(const __tgt_device_image &Image, LLVMContext &Ctx,
75+
const std::string &ComputeUnitKind);
76+
7077
/// Run backend, which contains optimization and code generation.
7178
Expected<std::unique_ptr<MemoryBuffer>>
7279
backend(Module &M, const std::string &ComputeUnitKind, unsigned OptLevel);
@@ -99,6 +106,8 @@ struct JITEngine {
99106
std::mutex ComputeUnitMapMutex;
100107

101108
/// Control environment variables.
109+
target::StringEnvar ReplacementObjectFileName =
110+
target::StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_OBJECT");
102111
target::StringEnvar ReplacementModuleFileName =
103112
target::StringEnvar("LIBOMPTARGET_JIT_REPLACEMENT_MODULE");
104113
target::StringEnvar PreOptIRModuleFileName =
@@ -107,6 +116,8 @@ struct JITEngine {
107116
target::StringEnvar("LIBOMPTARGET_JIT_POST_OPT_IR_MODULE");
108117
target::UInt32Envar JITOptLevel =
109118
target::UInt32Envar("LIBOMPTARGET_JIT_OPT_LEVEL", 3);
119+
target::BoolEnvar JITSkipOpt =
120+
target::BoolEnvar("LIBOMPTARGET_JIT_SKIP_OPT", false);
110121
};
111122

112123
} // namespace target

0 commit comments

Comments
 (0)