[clang] 719f52b - [CIR] Intitial upstreaming of LibOpt pass (#172487)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 30 01:53:53 PDT 2026
Author: Hendrik Hübner
Date: 2026-06-30T08:53:47Z
New Revision: 719f52b3d532a52393afe6b1ab4a3df4746acc23
URL: https://github.com/llvm/llvm-project/commit/719f52b3d532a52393afe6b1ab4a3df4746acc23
DIFF: https://github.com/llvm/llvm-project/commit/719f52b3d532a52393afe6b1ab4a3df4746acc23.diff
LOG: [CIR] Intitial upstreaming of LibOpt pass (#172487)
This PR Upstreams a skeleton for the LibOpt pass, including the Clang frontend wiring.
Added:
clang/lib/CIR/Dialect/Transforms/LibOpt.cpp
clang/test/CIR/Transforms/lib-opt.cpp
Modified:
clang/include/clang/CIR/CIRToCIRPasses.h
clang/include/clang/CIR/Dialect/Passes.h
clang/include/clang/CIR/Dialect/Passes.td
clang/include/clang/Frontend/FrontendOptions.h
clang/include/clang/Options/Options.td
clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
clang/lib/CIR/FrontendAction/CIRGenAction.cpp
clang/lib/CIR/Lowering/CIRPasses.cpp
clang/lib/Frontend/CompilerInvocation.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/CIRToCIRPasses.h b/clang/include/clang/CIR/CIRToCIRPasses.h
index ec6d75332bed9..de0d4fab8597d 100644
--- a/clang/include/clang/CIR/CIRToCIRPasses.h
+++ b/clang/include/clang/CIR/CIRToCIRPasses.h
@@ -32,7 +32,8 @@ namespace cir {
mlir::LogicalResult
runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirCtx,
clang::ASTContext &astCtx, bool enableVerifier,
- bool enableIdiomRecognizer, bool enableCIRSimplify);
+ bool enableIdiomRecognizer, bool enableCIRSimplify,
+ bool enableLibOpt, llvm::StringRef libOptOptions);
} // namespace cir
diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h
index a68f7b621f5d8..651a1319cfe5d 100644
--- a/clang/include/clang/CIR/Dialect/Passes.h
+++ b/clang/include/clang/CIR/Dialect/Passes.h
@@ -34,6 +34,8 @@ std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx);
std::unique_ptr<Pass> createGotoSolverPass();
std::unique_ptr<Pass> createIdiomRecognizerPass();
std::unique_ptr<Pass> createIdiomRecognizerPass(clang::ASTContext *astCtx);
+std::unique_ptr<Pass> createLibOptPass();
+std::unique_ptr<Pass> createLibOptPass(clang::ASTContext *astCtx);
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);
diff --git a/clang/include/clang/CIR/Dialect/Passes.td b/clang/include/clang/CIR/Dialect/Passes.td
index 6a7c4bf9aac88..9cdeb4d42d5a1 100644
--- a/clang/include/clang/CIR/Dialect/Passes.td
+++ b/clang/include/clang/CIR/Dialect/Passes.td
@@ -195,6 +195,18 @@ def IdiomRecognizer : Pass<"cir-idiom-recognizer", "mlir::ModuleOp"> {
let dependentDialects = ["cir::CIRDialect"];
}
+def LibOpt : Pass<"cir-lib-opt"> {
+ let summary = "Optimize C/C++ library calls";
+ let description = [{
+ This pass applies transformations on C/C++ standard library idioms,
+ such as library function calls and structs raised to CIR operations
+ using the `cir-idiom-recognize` pass.
+ }];
+
+ let constructor = "mlir::createLibOptPass()";
+ let dependentDialects = ["cir::CIRDialect"];
+}
+
def CallConvLowering : Pass<"cir-call-conv-lowering", "mlir::ModuleOp"> {
let summary = "Lower CIR function signatures and call sites to match target ABI";
let description = [{
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index f65547e68b29d..ec42e44d035b6 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -426,6 +426,14 @@ class FrontendOptions {
LLVM_PREFERRED_TYPE(bool)
unsigned ClangIREnableIdiomRecognizer : 1;
+ /// Enable ClangIR library optimization.
+ /// Set when -fclangir-lib-opt or -fclangir-lib-opt= was passed.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned ClangIRLibOptEnabled : 1;
+
+ /// Options to control ClangIR library optimization
+ std::string ClangIRLibOptOptions;
+
CodeCompleteOptions CodeCompleteOpts;
/// Specifies the output format of the AST.
@@ -560,7 +568,8 @@ class FrontendOptions {
EmitPrettySymbolGraphs(false), GenReducedBMI(false),
UseClangIRPipeline(false), ClangIRDisablePasses(false),
ClangIRDisableCIRVerifier(false), ClangIREnableIdiomRecognizer(false),
- TimeTraceGranularity(500), TimeTraceVerbose(false) {}
+ ClangIRLibOptEnabled(false), TimeTraceGranularity(500),
+ TimeTraceVerbose(false) {}
/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return Language::C.
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index c998446ac0a22..3a3952a4397be 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3405,6 +3405,16 @@ def clangir_enable_idiom_recognizer : Flag<["-"], "clangir-enable-idiom-recogniz
HelpText<"ClangIR: Enable Idiom Recognizer pass">,
MarshallingInfoFlag<FrontendOpts<"ClangIREnableIdiomRecognizer">>;
+def clangir_lib_opt_EQ : Joined<["-"], "clangir-lib-opt=">,
+ Visibility<[ClangOption, CC1Option]>, Group<f_Group>, Values<"all">,
+ HelpText<"Enable C/C++ library based optimizations (with options)">,
+ MarshallingInfoString<FrontendOpts<"ClangIRLibOptOptions">>;
+
+def clangir_lib_opt : Flag<["-"], "clangir-lib-opt">,
+ Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
+ Alias<clangir_lib_opt_EQ>, AliasArgs<["all"]>,
+ HelpText<"Enable C/C++ library based optimizations">;
+
defm clangir : BoolFOption<"clangir",
FrontendOpts<"UseClangIRPipeline">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">,
diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
index 27d9d26c28bd4..5edbfcf467f90 100644
--- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
@@ -13,6 +13,7 @@ add_clang_library(MLIRCIRTransforms
LoweringPrepare.cpp
GotoSolver.cpp
IdiomRecognizer.cpp
+ LibOpt.cpp
DEPENDS
MLIRCIRPassIncGen
diff --git a/clang/lib/CIR/Dialect/Transforms/LibOpt.cpp b/clang/lib/CIR/Dialect/Transforms/LibOpt.cpp
new file mode 100644
index 0000000000000..92a9339545931
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/LibOpt.cpp
@@ -0,0 +1,77 @@
+//===- LibOpt.cpp - Optimize CIR raised C/C++ library idioms --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass optimizes C/C++ standard library idioms in Clang IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PassDetail.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/Region.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Mangle.h"
+#include "clang/Basic/Module.h"
+#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Path.h"
+
+using cir::CIRBaseBuilderTy;
+using namespace mlir;
+using namespace cir;
+
+namespace mlir {
+#define GEN_PASS_DEF_LIBOPT
+#include "clang/CIR/Dialect/Passes.h.inc"
+} // namespace mlir
+
+namespace {
+
+struct LibOptPass : public impl::LibOptBase<LibOptPass> {
+ LibOptPass() = default;
+ mlir::LogicalResult
+ initializeOptions(llvm::StringRef options,
+ llvm::function_ref<mlir::LogicalResult(const llvm::Twine &)>
+ errorHandler) override;
+ void runOnOperation() override;
+
+ // Raw libopt option string forwarded by the frontend. This will later control
+ // which optimizations the pass enables.
+ std::string optimizationOptions;
+
+ /// Tracks current module.
+ ModuleOp theModule;
+};
+} // namespace
+
+mlir::LogicalResult LibOptPass::initializeOptions(
+ llvm::StringRef options,
+ llvm::function_ref<mlir::LogicalResult(const llvm::Twine &)> errorHandler) {
+ (void)errorHandler;
+ optimizationOptions = options.str();
+ // TODO(cir): Parse options to select the active transformations for the
+ // pass.
+ return mlir::success();
+}
+
+void LibOptPass::runOnOperation() {
+ auto *op = getOperation();
+ if (isa<::mlir::ModuleOp>(op))
+ theModule = cast<::mlir::ModuleOp>(op);
+}
+
+std::unique_ptr<Pass> mlir::createLibOptPass() {
+ return std::make_unique<LibOptPass>();
+}
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index fccd270a95ccd..92c9ef5499693 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -135,10 +135,15 @@ class CIRGenConsumer : public clang::ASTConsumer {
mlir::MLIRContext &MlirCtx = Gen->getMLIRContext();
if (!FEOptions.ClangIRDisablePasses) {
+ std::string LibOptOptions = FEOptions.ClangIRLibOptOptions;
+
// Setup and run CIR pipeline.
+ const bool EnableLibOpt =
+ FEOptions.ClangIRLibOptEnabled && (CGO.OptimizationLevel > 0);
if (runCIRToCIRPasses(
MlirModule, MlirCtx, C, !FEOptions.ClangIRDisableCIRVerifier,
- FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0)
+ FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0,
+ EnableLibOpt, LibOptOptions)
.failed()) {
CI.getDiagnostics().Report(diag::err_cir_to_cir_transform_failed);
return;
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 7b93356a34c38..f476ee04430cd 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -17,10 +17,12 @@
#include "llvm/Support/TimeProfiler.h"
namespace cir {
+
mlir::LogicalResult
runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
clang::ASTContext &astContext, bool enableVerifier,
- bool enableIdiomRecognizer, bool enableCIRSimplify) {
+ bool enableIdiomRecognizer, bool enableCIRSimplify,
+ bool enableLibOpt, llvm::StringRef libOptOptions) {
llvm::TimeTraceScope scope("CIR To CIR Passes");
@@ -33,6 +35,18 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
if (enableIdiomRecognizer)
pm.addPass(mlir::createIdiomRecognizerPass(&astContext));
+ if (enableLibOpt) {
+ auto libOptPass = mlir::createLibOptPass();
+ auto errorHandler = [](const llvm::Twine &) -> mlir::LogicalResult {
+ return mlir::LogicalResult::failure();
+ };
+
+ if (libOptPass->initializeOptions(libOptOptions, errorHandler).failed())
+ return mlir::failure();
+
+ pm.addPass(std::move(libOptPass));
+ }
+
pm.addPass(mlir::createTargetLoweringPass());
pm.addPass(mlir::createCXXABILoweringPass());
pm.addPass(mlir::createLoweringPreparePass(&astContext));
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 35d6e6b6f3145..6f50defcfaf07 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3192,6 +3192,9 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_clangir_disable_verifier))
Opts.ClangIRDisableCIRVerifier = true;
+
+ if (Args.hasArg(OPT_clangir_lib_opt) || Args.hasArg(OPT_clangir_lib_opt_EQ))
+ Opts.ClangIRLibOptEnabled = true;
#endif // CLANG_ENABLE_CIR
if (Args.hasArg(OPT_aux_target_cpu))
diff --git a/clang/test/CIR/Transforms/lib-opt.cpp b/clang/test/CIR/Transforms/lib-opt.cpp
new file mode 100644
index 0000000000000..9790d8d237461
--- /dev/null
+++ b/clang/test/CIR/Transforms/lib-opt.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fclangir -O1 -emit-cir -mmlir --mlir-print-ir-after-all -clangir-lib-opt=all %s -o - 2>&1 | FileCheck %s -check-prefix=ENABLED
+// RUN: %clang_cc1 -fclangir -O1 -emit-cir -mmlir --mlir-print-ir-after-all %s -o - 2>&1 | FileCheck %s -check-prefix=DISABLED
+// RUN: %clang_cc1 -fclangir -O0 -emit-cir -mmlir --mlir-print-ir-after-all -clangir-lib-opt=all %s -o - 2>&1 | FileCheck %s -check-prefix=DISABLED
+
+// ENABLED: IR Dump After LibOpt: cir-lib-opt
+// DISABLED-NOT: IR Dump After LibOpt: cir-lib-opt
More information about the cfe-commits
mailing list