https://github.com/jsjodin created 
https://github.com/llvm/llvm-project/pull/186814

This patch makes ClangIR emit .cir and .mlir files when the-save-temps flag is 
specified. Having these files emitted is useful e.g. when inspecting the 
generated code for OpenMP offloading.

Co-authored-by: Claude Opus 4.6 [email protected]

>From b29321b44bd55d771719fa03ee200aec7026d1e8 Mon Sep 17 00:00:00 2001
From: Jan Leyonberg <[email protected]>
Date: Mon, 16 Mar 2026 10:04:18 -0400
Subject: [PATCH] [CIR] Make the -save-temps flag emit .cir and .mlir files

This patch makes ClangIR emit .cir and .mlir files when the-save-temps flag is
specified. Having these files emitted is useful e.g. when inspecting the
generated code for OpenMP offloading.

Co-authored-by: Claude Opus 4.6 [email protected]
---
 clang/include/clang/CIR/LowerToLLVM.h         |  4 ++-
 clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 28 +++++++++++++++++--
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 11 +++++++-
 clang/test/CIR/CodeGen/save-temps.c           | 20 +++++++++++++
 4 files changed, 58 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/save-temps.c

diff --git a/clang/include/clang/CIR/LowerToLLVM.h 
b/clang/include/clang/CIR/LowerToLLVM.h
index 6e1b0270fcd2b..393b997c50695 100644
--- a/clang/include/clang/CIR/LowerToLLVM.h
+++ b/clang/include/clang/CIR/LowerToLLVM.h
@@ -12,6 +12,7 @@
 #ifndef CLANG_CIR_LOWERTOLLVM_H
 #define CLANG_CIR_LOWERTOLLVM_H
 
+#include "llvm/ADT/StringRef.h"
 #include <memory>
 
 namespace llvm {
@@ -28,7 +29,8 @@ namespace cir {
 namespace direct {
 std::unique_ptr<llvm::Module>
 lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule,
-                             llvm::LLVMContext &llvmCtx);
+                             llvm::LLVMContext &llvmCtx,
+                             llvm::StringRef mlirSaveTempsOutFile = {});
 } // namespace direct
 } // namespace cir
 
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp 
b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index 19c407545b961..ab273539b1ce2 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -15,7 +15,10 @@
 #include "clang/CIR/LowerToLLVM.h"
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace cir;
 using namespace clang;
@@ -44,8 +47,10 @@ getBackendActionFromOutputType(CIRGenAction::OutputType 
Action) {
 }
 
 static std::unique_ptr<llvm::Module>
-lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx) {
-  return direct::lowerDirectlyFromCIRToLLVMIR(MLIRModule, LLVMCtx);
+lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx,
+                     llvm::StringRef mlirSaveTempsOutFile = {}) {
+  return direct::lowerDirectlyFromCIRToLLVMIR(MLIRModule, LLVMCtx,
+                                              mlirSaveTempsOutFile);
 }
 
 class CIRGenConsumer : public clang::ASTConsumer {
@@ -136,9 +141,26 @@ class CIRGenConsumer : public clang::ASTConsumer {
     case CIRGenAction::OutputType::EmitBC:
     case CIRGenAction::OutputType::EmitObj:
     case CIRGenAction::OutputType::EmitAssembly: {
+      StringRef saveTempsPrefix = CGO.SaveTempsFilePrefix;
+      std::string cirSaveTempsOutFile, mlirSaveTempsOutFile;
+      if (!saveTempsPrefix.empty()) {
+        SmallString<128> stem(saveTempsPrefix);
+        llvm::sys::path::replace_extension(stem, "cir");
+        cirSaveTempsOutFile = std::string(stem);
+        llvm::sys::path::replace_extension(stem, "mlir");
+        mlirSaveTempsOutFile = std::string(stem);
+      }
+
+      if (!cirSaveTempsOutFile.empty()) {
+        std::error_code ec;
+        llvm::raw_fd_ostream out(cirSaveTempsOutFile, ec);
+        if (!ec)
+          MlirModule->print(out);
+      }
+
       llvm::LLVMContext LLVMCtx;
       std::unique_ptr<llvm::Module> LLVMModule =
-          lowerFromCIRToLLVMIR(MlirModule, LLVMCtx);
+          lowerFromCIRToLLVMIR(MlirModule, LLVMCtx, mlirSaveTempsOutFile);
 
       BackendAction BEAction = getBackendActionFromOutputType(Action);
       emitBackendOutput(
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4a1b4292b23dd..7bd232cefbb2e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -46,6 +46,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/TimeProfiler.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace cir;
 using namespace llvm;
@@ -4926,7 +4927,8 @@ void populateCIRToLLVMPasses(mlir::OpPassManager &pm) {
 }
 
 std::unique_ptr<llvm::Module>
-lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, LLVMContext &llvmCtx) {
+lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, LLVMContext &llvmCtx,
+                             StringRef mlirSaveTempsOutFile) {
   llvm::TimeTraceScope scope("lower from CIR to LLVM directly");
 
   mlir::MLIRContext *mlirCtx = mlirModule.getContext();
@@ -4942,6 +4944,13 @@ lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, 
LLVMContext &llvmCtx) {
         "The pass manager failed to lower CIR to LLVMIR dialect!");
   }
 
+  if (!mlirSaveTempsOutFile.empty()) {
+    std::error_code ec;
+    llvm::raw_fd_ostream out(mlirSaveTempsOutFile, ec);
+    if (!ec)
+      mlirModule->print(out);
+  }
+
   mlir::registerBuiltinDialectTranslation(*mlirCtx);
   mlir::registerLLVMDialectTranslation(*mlirCtx);
   mlir::registerOpenMPDialectTranslation(*mlirCtx);
diff --git a/clang/test/CIR/CodeGen/save-temps.c 
b/clang/test/CIR/CodeGen/save-temps.c
new file mode 100644
index 0000000000000..8449ce38bace5
--- /dev/null
+++ b/clang/test/CIR/CodeGen/save-temps.c
@@ -0,0 +1,20 @@
+// Test that -save-temps with -fclangir emits .cir and .mlir intermediate 
files.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm \
+// RUN:   -save-temps=obj -o %t.ll %s
+
+// Check that the .cir file was created and contains CIR dialect ops
+// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
+
+// CIR: cir.func
+// CIR: cir.return
+
+// Check that the .mlir file was created and contains LLVM dialect ops
+// RUN: FileCheck --input-file=%t.mlir %s --check-prefix=MLIR
+
+// MLIR: llvm.func
+// MLIR: llvm.return
+
+int foo(int x) {
+  return x + 1;
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to