[clang] 4a1e9f7 - [CIR] Make the -save-temps flag emit .cir and .mlir files (#186814)

via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 20 07:44:51 PDT 2026


Author: Jan Leyonberg
Date: 2026-03-20T10:44:47-04:00
New Revision: 4a1e9f73103fa3d66c7db93f1047905c07d543e2

URL: https://github.com/llvm/llvm-project/commit/4a1e9f73103fa3d66c7db93f1047905c07d543e2
DIFF: https://github.com/llvm/llvm-project/commit/4a1e9f73103fa3d66c7db93f1047905c07d543e2.diff

LOG: [CIR] Make the -save-temps flag emit .cir and .mlir files (#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 noreply at anthropic.com

Added: 
    clang/test/CIR/CodeGen/save-temps.c

Modified: 
    clang/include/clang/CIR/LowerToLLVM.h
    clang/lib/CIR/FrontendAction/CIRGenAction.cpp
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Removed: 
    


################################################################################
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 60c3030bfbea1..6463c662ade6d 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;
@@ -4925,7 +4926,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();
@@ -4941,6 +4943,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;
+}


        


More information about the cfe-commits mailing list