-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[MLIR][Flang][DebugInfo] Set debug info format in MLIR->IR translation #95098
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
MLIR's LLVM dialect does not internally support debug records, only converting to/from debug intrinsics. To smooth the transition from intrinsics to records, there is a step prior to IR->MLIR translation that switches the IR module to intrinsic-form; this patch adds the equivalent conversion to record-form at MLIR->IR translation, and also modifies the flang front end to use the WriteNewDbgInfoFormat flag when it is emitting LLVM IR.
@llvm/pr-subscribers-mlir-llvm @llvm/pr-subscribers-flang-driver Author: Stephen Tozer (SLTozer) ChangesMLIR's LLVM dialect does not internally support debug records, only converting to/from debug intrinsics. To smooth the transition from intrinsics to records, there is a step prior to IR->MLIR translation that switches the IR module to intrinsic-form; this patch adds the equivalent conversion to record-form at MLIR->IR translation, and also modifies the flang front end to use the WriteNewDbgInfoFormat flag when it is emitting LLVM IR. Full diff: https://github.com/llvm/llvm-project/pull/95098.diff 2 Files Affected:
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index b1b6391f1439c..585177b5c7647 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -50,6 +50,7 @@
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
+#include "llvm/IR/DebugProgramInstruction.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
@@ -81,6 +82,8 @@ using namespace Fortran::frontend;
llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
#include "llvm/Support/Extension.def"
+extern llvm::cl::opt<bool> WriteNewDbgInfoFormat;
+
/// Save the given \c mlirModule to a temporary .mlir file, in a location
/// decided by the -save-temps flag. No files are produced if the flag is not
/// specified.
@@ -1271,6 +1274,10 @@ void CodeGenAction::executeAction() {
runOptimizationPipeline(ci.isOutputStreamNull() ? *os : ci.getOutputStream());
if (action == BackendActionTy::Backend_EmitLL) {
+ llvm::ScopedDbgInfoFormatSetter FormatSetter(*llvmModule,
+ WriteNewDbgInfoFormat);
+ if (WriteNewDbgInfoFormat)
+ llvmModule->removeDebugIntrinsicDeclarations();
llvmModule->print(ci.isOutputStreamNull() ? *os : ci.getOutputStream(),
/*AssemblyAnnotationWriter=*/nullptr);
return;
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 7b86b250c294b..a5c8c26483edf 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -64,6 +64,8 @@ using namespace mlir;
using namespace mlir::LLVM;
using namespace mlir::LLVM::detail;
+extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
+
#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
namespace {
@@ -1789,6 +1791,7 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
StringRef name) {
m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
+ llvmModule->setNewDbgInfoFormatFlag(false);
if (auto dataLayoutAttr =
m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
@@ -1867,6 +1870,8 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext,
if (failed(translator.convertFunctions()))
return nullptr;
+ translator.llvmModule->setIsNewDbgInfoFormat(UseNewDbgInfoFormat);
+
if (!disableVerification &&
llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
return nullptr;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that this is just adding our debug-info-transition calls a the point where IR enters/exits, this seems fine, I reckon we could add some more comments to assist readers, see inline.
llvm::ScopedDbgInfoFormatSetter FormatSetter(*llvmModule, | ||
WriteNewDbgInfoFormat); | ||
if (WriteNewDbgInfoFormat) | ||
llvmModule->removeDebugIntrinsicDeclarations(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO you want to put a comment here briefly indicating the purpose, and when it can be removed (this is all transitory, right?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not quite transitory - it will eventually go, but this should remain for long as we support intrinsics at all, the same as all other code that selects the debug info format.
@@ -1789,6 +1791,7 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext, | |||
StringRef name) { | |||
m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>(); | |||
auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext); | |||
llvmModule->setNewDbgInfoFormatFlag(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment directing people to the RemoveDIs page would be good, we can assure readers that the meaning of the debug-info is the same, only the format is different.
I ran the lit tests previously, but didn't rebuild all the MLIR binaries first - updated the patch with some more conversion sites and confirmed |
Following from the previous commit, this patch converts to the appropriate debug info format before printing LLVM IR. See: #95098
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why aren't any tests added to this PR?
@@ -81,6 +82,8 @@ using namespace Fortran::frontend; | |||
llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); | |||
#include "llvm/Support/Extension.def" | |||
|
|||
extern llvm::cl::opt<bool> WriteNewDbgInfoFormat; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this. The driver should be controlled exclusively through options defined in clang/include/clang/Driver/Options.td.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright - I can revert the patch while figuring out another way to get the right behaviour. Just to clarify though - the issue isn't just that an LLVM opt appears here, but that the state of any llvm flag should have no influence on the output of the driver?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify though - the issue isn't just that an LLVM opt appears here, but that the state of any llvm flag should have no influence on the output of the driver?
Indeed. The design goal is to avoid "leaking" the internals of LLVM into the driver. Otherwise things can get very complex very quickly :) This declaration is just a manifestation of the fact that the layering has been violated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I get the idea, but just to be clear; LLVM flags can influence the output of the clang driver as-is right now, in the sense that LLVM flags control the behaviour of LLVM internal functions, and those functions are invoked by the driver, but there's no direct use of those flags from the driver.
Currently, --write-experimental-debuginfo
(the flag I added here) influences the output of the clang frontend, because the frontend uses llvm::PrintModulePass
to print the final LLVM IR. I think the appropriate change to the flang frontend would be to have it do the same, so that there's no behavioural drift between the two - for an action like printing LLVM IR, I think it's probably sensible for both to offload that logic to LLVM's internals.
Does that sound like the right approach to you? Resulting change is something like:
@@ -995,6 +995,8 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
if (action == BackendActionTy::Backend_EmitBC)
mpm.addPass(llvm::BitcodeWriterPass(os));
+ else if (action == BackendActionTy::Backend_EmitLL)
+ mpm.addPass(llvm::PrintModulePass(os));
// Run the passes.
mpm.run(*llvmModule, mam);
@@ -1270,13 +1272,7 @@ void CodeGenAction::executeAction() {
// Run LLVM's middle-end (i.e. the optimizer).
runOptimizationPipeline(ci.isOutputStreamNull() ? *os : ci.getOutputStream());
- if (action == BackendActionTy::Backend_EmitLL) {
- llvmModule->print(ci.isOutputStreamNull() ? *os : ci.getOutputStream(),
- /*AssemblyAnnotationWriter=*/nullptr);
- return;
- }
-
- if (action == BackendActionTy::Backend_EmitBC) {
+ if (action == BackendActionTy::Backend_EmitLL || action == BackendActionTy::Backend_EmitBC) {
// This action has effectively been completed in runOptimizationPipeline.
return;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LLVM flags can influence the output of the clang driver as-is right now, in the sense that LLVM flags control the behaviour of LLVM internal functions, and those functions are invoked by the driver, but there's no direct use of those flags from the driver.
Interesting. IMHO, that should not be allowed - it means that the internals of LLVM leak higher up the compilation stack. Flang will complain if the compiler is invoked with an unrecognised flag (-write-experimental-debuginf
would qualify as such). There's a bit of context at the bottom of my comment.
Does that sound like the right approach to you? Resulting change is something like:
Yes, that makes sense to me. Not sure why we didn't use llvm::PrintModulePass
to begin with. Looks like a relatively new addition to LLVM, so perhaps it wasn't available when we worked on this in Flang? 🤔
Btw, if you want to pass a flag to LLVM, use -mllvm
;-) In fact, that should be sufficient for what you are trying to achieve here?
Context
Since roughly ~1yr ago, we have this concept of "visibility" when defining compiler flags:
At that point, I made Flang reject all compilation flags that are not supported
That was primarily to avoid a situations where people get unexpected behaviour (e.g. "hey, I am passing this flag and nothing happens"). That also helps us quickly identify flags that are missing (if the compiler was to ignore unsupported flags, it would hard to tell what's supported and what is not). Admittedly, it can be a nuisance at times, but so far we've managed to support all users that raised issues related to this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. IMHO, that should not be allowed - it means that the internals of LLVM leak higher up the compilation stack. Flang will complain if the compiler is invoked with an unrecognised flag (
-write-experimental-debuginf
would qualify as such). There's a bit of context at the bottom of my comment.
Ah, I think there's a terminology mismatch here - I do mean that the flag is being passed under -llvm
, to an invocation of -fc1
, and that affects the results of LLVM internal behaviour invoked by the frontend, which is what I'm going for here. The patch here seems to work, so this is probably the right way: #95142
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, this makes more sense now 😅
If I read GitHub logs correctly, this was uploaded+reviewed+merged ~2hrs ago, i.e. within a very narrow time window. Please, could you allow more time for reviews next time? We are distributed throughout the world and start work at different times, 2hrs is a very very narrow window, even for 1 time-zone. |
A further patch that I intend(ed) to land very shortly afterwards would update the state of the flags would lead to this getting coverage, but I'm happy to pull this back to make sure the patch itself has proper test coverage.
Apologies - I'll revert the patch for now, and reopen the review for a longer period of time before landing. This looked like a hotfix situation to me based on similar changes elsewhere, but based on your comment about controlling the driver, this probably needs a slightly more involved fix. |
llvm#95098) MLIR's LLVM dialect does not internally support debug records, only converting to/from debug intrinsics. To smooth the transition from intrinsics to records, there is a step prior to IR->MLIR translation that switches the IR module to intrinsic-form; this patch adds the equivalent conversion to record-form at MLIR->IR translation, and also modifies the flang front end to use the WriteNewDbgInfoFormat flag when it is emitting LLVM IR.
…anslation (llvm#95098)" Reverted due to failure on buildbot due to missing use of the WriteNewDbgInfoFormat flag in MLIR. This reverts commit ca920bb.
MLIR's LLVM dialect does not internally support debug records, only converting to/from debug intrinsics. To smooth the transition from intrinsics to records, there is a step prior to IR->MLIR translation that switches the IR module to intrinsic-form; this patch adds the equivalent conversion to record-form at MLIR->IR translation. This is a partial reapply of #95098 which can be landed once the flang frontend has been updated by #95306. This is the counterpart to the earlier patch #89735 which handled the IR->MLIR conversion.
…#95329) MLIR's LLVM dialect does not internally support debug records, only converting to/from debug intrinsics. To smooth the transition from intrinsics to records, there is a step prior to IR->MLIR translation that switches the IR module to intrinsic-form; this patch adds the equivalent conversion to record-form at MLIR->IR translation. This is a partial reapply of llvm#95098 which can be landed once the flang frontend has been updated by llvm#95306. This is the counterpart to the earlier patch llvm#89735 which handled the IR->MLIR conversion.
MLIR's LLVM dialect does not internally support debug records, only converting to/from debug intrinsics. To smooth the transition from intrinsics to records, there is a step prior to IR->MLIR translation that switches the IR module to intrinsic-form; this patch adds the equivalent conversion to record-form at MLIR->IR translation, and also modifies the flang front end to use the WriteNewDbgInfoFormat flag when it is emitting LLVM IR.