diff --git a/clang/include/clang/CIR/CIRToCIRPasses.h b/clang/include/clang/CIR/CIRToCIRPasses.h index a88fba7a76e3..4ad4aeebb22e 100644 --- a/clang/include/clang/CIR/CIRToCIRPasses.h +++ b/clang/include/clang/CIR/CIRToCIRPasses.h @@ -34,8 +34,8 @@ mlir::LogicalResult runCIRToCIRPasses( llvm::StringRef lifetimeOpts, bool enableIdiomRecognizer, llvm::StringRef idiomRecognizerOpts, bool enableLibOpt, llvm::StringRef libOptOpts, std::string &passOptParsingFailure, - bool flattenCIR, bool emitMLIR, bool enableCallConvLowering, - bool enableMem2reg); + bool enableCIRSimplify, bool flattenCIR, bool emitMLIR, + bool enableCallConvLowering, bool enableMem2reg); } // namespace cir diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h index 116966d52f15..67e9da2246b6 100644 --- a/clang/include/clang/CIR/Dialect/Passes.h +++ b/clang/include/clang/CIR/Dialect/Passes.h @@ -26,6 +26,7 @@ std::unique_ptr createLifetimeCheckPass(ArrayRef remark, ArrayRef hist, unsigned hist_limit, clang::ASTContext *astCtx); +std::unique_ptr createCIRCanonicalizePass(); std::unique_ptr createCIRSimplifyPass(); std::unique_ptr createDropASTPass(); std::unique_ptr createSCFPreparePass(); diff --git a/clang/include/clang/CIR/Dialect/Passes.td b/clang/include/clang/CIR/Dialect/Passes.td index 1c17ca9c5ed1..d72bf0bfd420 100644 --- a/clang/include/clang/CIR/Dialect/Passes.td +++ b/clang/include/clang/CIR/Dialect/Passes.td @@ -11,22 +11,33 @@ include "mlir/Pass/PassBase.td" -def CIRSimplify : Pass<"cir-simplify"> { - let summary = "Performs CIR simplification"; +def CIRCanonicalize : Pass<"cir-canonicalize"> { + let summary = "Performs CIR canonicalization"; let description = [{ - The pass rewrites CIR and removes some redundant operations. + Perform canonicalizations on CIR and removes some redundant operations. + + This pass performs basic cleanup and canonicalization transformations that + hopefully do not affect CIR-to-source fidelity and high-level code analysis + passes too much. Example transformations performed in this pass include + empty scope cleanup, trivial try cleanup, redundant branch cleanup, etc. + Those more "heavyweight" transformations and those transformations that + could significantly affect CIR-to-source fidelity are performed in the + `cir-simplify` pass. + }]; - For example, due to canonicalize pass is too aggressive for CIR when - the pipeline is used for C/C++ analysis, this pass runs some rewrites - for scopes, merging some blocks and eliminating unnecessary control-flow. + let constructor = "mlir::createCIRCanonicalizePass()"; + let dependentDialects = ["cir::CIRDialect"]; +} - Also, the pass removes redundant and/or unneccessary cast and unary not - operation e.g. - ```mlir - %1 = cir.cast(bool_to_int, %0 : !cir.bool), !s32i - %2 = cir.cast(int_to_bool, %1 : !s32i), !cir.bool - ``` +def CIRSimplify : Pass<"cir-simplify"> { + let summary = "Performs CIR simplification and code optimization"; + let description = [{ + The pass performs code simplification and optimization on CIR. + Unlike the `cir-canonicalize` pass, this pass contains more aggresive code + transformations that could significantly affect CIR-to-source fidelity. + Example transformations performed in this pass include ternary folding, + code hoisting, etc. }]; let constructor = "mlir::createCIRSimplifyPass()"; let dependentDialects = ["cir::CIRDialect"]; diff --git a/clang/lib/CIR/CodeGen/CIRPasses.cpp b/clang/lib/CIR/CodeGen/CIRPasses.cpp index 60e393f7985f..4f89daa1cee4 100644 --- a/clang/lib/CIR/CodeGen/CIRPasses.cpp +++ b/clang/lib/CIR/CodeGen/CIRPasses.cpp @@ -26,11 +26,11 @@ mlir::LogicalResult runCIRToCIRPasses( llvm::StringRef lifetimeOpts, bool enableIdiomRecognizer, llvm::StringRef idiomRecognizerOpts, bool enableLibOpt, llvm::StringRef libOptOpts, std::string &passOptParsingFailure, - bool flattenCIR, bool emitMLIR, bool enableCallConvLowering, - bool enableMem2Reg) { + bool enableCIRSimplify, bool flattenCIR, bool emitMLIR, + bool enableCallConvLowering, bool enableMem2Reg) { mlir::PassManager pm(mlirCtx); - pm.addPass(mlir::createCIRSimplifyPass()); + pm.addPass(mlir::createCIRCanonicalizePass()); // TODO(CIR): Make this actually propagate errors correctly. This is stubbed // in to get rebases going. @@ -66,6 +66,9 @@ mlir::LogicalResult runCIRToCIRPasses( pm.addPass(std::move(libOpPass)); } + if (enableCIRSimplify) + pm.addPass(mlir::createCIRSimplifyPass()); + pm.addPass(mlir::createLoweringPreparePass(&astCtx)); // FIXME(cir): This pass should run by default, but it is lacking support for diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp new file mode 100644 index 000000000000..5c5ba4b573ce --- /dev/null +++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp @@ -0,0 +1,187 @@ +//===- CIRSimplify.cpp - performs CIR canonicalization --------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "PassDetail.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Block.h" +#include "mlir/IR/Operation.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/IR/Region.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/Passes.h" + +using namespace mlir; +using namespace cir; + +namespace { + +/// Removes branches between two blocks if it is the only branch. +/// +/// From: +/// ^bb0: +/// cir.br ^bb1 +/// ^bb1: // pred: ^bb0 +/// cir.return +/// +/// To: +/// ^bb0: +/// cir.return +struct RemoveRedundantBranches : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(BrOp op, + PatternRewriter &rewriter) const final { + Block *block = op.getOperation()->getBlock(); + Block *dest = op.getDest(); + + if (isa(dest->front())) + return failure(); + + // Single edge between blocks: merge it. + if (block->getNumSuccessors() == 1 && + dest->getSinglePredecessor() == block) { + rewriter.eraseOp(op); + rewriter.mergeBlocks(dest, block); + return success(); + } + + return failure(); + } +}; + +struct RemoveEmptyScope : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult match(ScopeOp op) const final { + return success(op.getRegion().empty() || + (op.getRegion().getBlocks().size() == 1 && + op.getRegion().front().empty())); + } + + void rewrite(ScopeOp op, PatternRewriter &rewriter) const final { + rewriter.eraseOp(op); + } +}; + +struct RemoveEmptySwitch : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult match(SwitchOp op) const final { + return success(op.getRegions().empty()); + } + + void rewrite(SwitchOp op, PatternRewriter &rewriter) const final { + rewriter.eraseOp(op); + } +}; + +struct RemoveTrivialTry : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult match(TryOp op) const final { + // FIXME: also check all catch regions are empty + // return success(op.getTryRegion().hasOneBlock()); + return mlir::failure(); + } + + void rewrite(TryOp op, PatternRewriter &rewriter) const final { + // Move try body to the parent. + assert(op.getTryRegion().hasOneBlock()); + + Block *parentBlock = op.getOperation()->getBlock(); + mlir::Block *tryBody = &op.getTryRegion().getBlocks().front(); + YieldOp y = dyn_cast(tryBody->getTerminator()); + assert(y && "expected well wrapped up try block"); + y->erase(); + + rewriter.inlineBlockBefore(tryBody, parentBlock, Block::iterator(op)); + rewriter.eraseOp(op); + } +}; + +// Remove call exception with empty cleanups +struct SimplifyCallOp : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult match(CallOp op) const final { + // Applicable to cir.call exception ... clean { cir.yield } + mlir::Region *r = &op.getCleanup(); + if (r->empty() || !r->hasOneBlock()) + return failure(); + + mlir::Block *b = &r->getBlocks().back(); + if (&b->back() != &b->front()) + return failure(); + + return success(isa(&b->getOperations().back())); + } + + void rewrite(CallOp op, PatternRewriter &rewriter) const final { + mlir::Block *b = &op.getCleanup().back(); + rewriter.eraseOp(&b->back()); + rewriter.eraseBlock(b); + } +}; + +//===----------------------------------------------------------------------===// +// CIRCanonicalizePass +//===----------------------------------------------------------------------===// + +struct CIRCanonicalizePass : public CIRCanonicalizeBase { + using CIRCanonicalizeBase::CIRCanonicalizeBase; + + // The same operation rewriting done here could have been performed + // by CanonicalizerPass (adding hasCanonicalizer for target Ops and + // implementing the same from above in CIRDialects.cpp). However, it's + // currently too aggressive for static analysis purposes, since it might + // remove things where a diagnostic can be generated. + // + // FIXME: perhaps we can add one more mode to GreedyRewriteConfig to + // disable this behavior. + void runOnOperation() override; +}; + +void populateCIRCanonicalizePatterns(RewritePatternSet &patterns) { + // clang-format off + patterns.add< + RemoveRedundantBranches, + RemoveEmptyScope, + RemoveEmptySwitch, + RemoveTrivialTry, + SimplifyCallOp + >(patterns.getContext()); + // clang-format on +} + +void CIRCanonicalizePass::runOnOperation() { + // Collect rewrite patterns. + RewritePatternSet patterns(&getContext()); + populateCIRCanonicalizePatterns(patterns); + + // Collect operations to apply patterns. + SmallVector ops; + getOperation()->walk([&](Operation *op) { + // CastOp here is to perform a manual `fold` in + // applyOpPatternsAndFold + if (isa(op)) + ops.push_back(op); + }); + + // Apply patterns. + if (applyOpPatternsAndFold(ops, std::move(patterns)).failed()) + signalPassFailure(); +} + +} // namespace + +std::unique_ptr mlir::createCIRCanonicalizePass() { + return std::make_unique(); +} diff --git a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp index 349d51a083f9..f573691b20f4 100644 --- a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp @@ -27,114 +27,6 @@ using namespace cir; namespace { -/// Removes branches between two blocks if it is the only branch. -/// -/// From: -/// ^bb0: -/// cir.br ^bb1 -/// ^bb1: // pred: ^bb0 -/// cir.return -/// -/// To: -/// ^bb0: -/// cir.return -struct RemoveRedundantBranches : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - LogicalResult matchAndRewrite(BrOp op, - PatternRewriter &rewriter) const final { - Block *block = op.getOperation()->getBlock(); - Block *dest = op.getDest(); - - if (isa(dest->front())) - return failure(); - - // Single edge between blocks: merge it. - if (block->getNumSuccessors() == 1 && - dest->getSinglePredecessor() == block) { - rewriter.eraseOp(op); - rewriter.mergeBlocks(dest, block); - return success(); - } - - return failure(); - } -}; - -struct RemoveEmptyScope : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - LogicalResult match(ScopeOp op) const final { - return success(op.getRegion().empty() || - (op.getRegion().getBlocks().size() == 1 && - op.getRegion().front().empty())); - } - - void rewrite(ScopeOp op, PatternRewriter &rewriter) const final { - rewriter.eraseOp(op); - } -}; - -struct RemoveEmptySwitch : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - LogicalResult match(SwitchOp op) const final { - return success(op.getRegions().empty()); - } - - void rewrite(SwitchOp op, PatternRewriter &rewriter) const final { - rewriter.eraseOp(op); - } -}; - -struct RemoveTrivialTry : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - LogicalResult match(TryOp op) const final { - // FIXME: also check all catch regions are empty - // return success(op.getTryRegion().hasOneBlock()); - return mlir::failure(); - } - - void rewrite(TryOp op, PatternRewriter &rewriter) const final { - // Move try body to the parent. - assert(op.getTryRegion().hasOneBlock()); - - Block *parentBlock = op.getOperation()->getBlock(); - mlir::Block *tryBody = &op.getTryRegion().getBlocks().front(); - YieldOp y = dyn_cast(tryBody->getTerminator()); - assert(y && "expected well wrapped up try block"); - y->erase(); - - rewriter.inlineBlockBefore(tryBody, parentBlock, Block::iterator(op)); - rewriter.eraseOp(op); - } -}; - -// Remove call exception with empty cleanups -struct SimplifyCallOp : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - LogicalResult match(CallOp op) const final { - // Applicable to cir.call exception ... clean { cir.yield } - mlir::Region *r = &op.getCleanup(); - if (r->empty() || !r->hasOneBlock()) - return failure(); - - mlir::Block *b = &r->getBlocks().back(); - if (&b->back() != &b->front()) - return failure(); - - return success(isa(&b->getOperations().back())); - } - - void rewrite(CallOp op, PatternRewriter &rewriter) const final { - mlir::Block *b = &op.getCleanup().back(); - rewriter.eraseOp(&b->back()); - rewriter.eraseBlock(b); - } -}; - /// Simplify suitable ternary operations into select operations. /// /// For now we only simplify those ternary operations whose true and false @@ -207,10 +99,7 @@ struct SimplifyTernary final : public OpRewritePattern { auto yieldOp = mlir::cast(onlyBlock.getTerminator()); auto yieldValueDefOp = mlir::dyn_cast_if_present( yieldOp.getArgs()[0].getDefiningOp()); - if (!yieldValueDefOp || yieldValueDefOp->getBlock() != &onlyBlock) - return false; - - return true; + return yieldValueDefOp && yieldValueDefOp->getBlock() == &onlyBlock; } }; @@ -242,7 +131,7 @@ struct SimplifySelect : public OpRewritePattern { return mlir::success(); } - // cir.seleft if %0 then #false else #true -> cir.unary not %0 + // cir.select if %0 then #false else #true -> cir.unary not %0 if (!trueValue.getValue() && falseValue.getValue()) { rewriter.replaceOpWithNewOp( op, mlir::cir::UnaryOpKind::Not, op.getCondition()); @@ -260,27 +149,14 @@ struct SimplifySelect : public OpRewritePattern { struct CIRSimplifyPass : public CIRSimplifyBase { using CIRSimplifyBase::CIRSimplifyBase; - // The same operation rewriting done here could have been performed - // by CanonicalizerPass (adding hasCanonicalizer for target Ops and - // implementing the same from above in CIRDialects.cpp). However, it's - // currently too aggressive for static analysis purposes, since it might - // remove things where a diagnostic can be generated. - // - // FIXME: perhaps we can add one more mode to GreedyRewriteConfig to - // disable this behavior. void runOnOperation() override; }; void populateMergeCleanupPatterns(RewritePatternSet &patterns) { // clang-format off patterns.add< - RemoveRedundantBranches, - RemoveEmptyScope, - RemoveEmptySwitch, - RemoveTrivialTry, SimplifyTernary, - SimplifySelect, - SimplifyCallOp + SimplifySelect >(patterns.getContext()); // clang-format on } @@ -293,11 +169,7 @@ void CIRSimplifyPass::runOnOperation() { // Collect operations to apply patterns. SmallVector ops; getOperation()->walk([&](Operation *op) { - // CastOp here is to perform a manual `fold` in - // applyOpPatternsAndFold - if (isa(op)) + if (isa(op)) ops.push_back(op); }); diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt index ffe1efbe0839..d675f17042b6 100644 --- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory(TargetLowering) add_clang_library(MLIRCIRTransforms LifetimeCheck.cpp LoweringPrepare.cpp + CIRCanonicalize.cpp CIRSimplify.cpp DropAST.cpp IdiomRecognizer.cpp diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 0ccd58cc9faf..8e3dbb0d35f7 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -203,6 +203,7 @@ class CIRGenConsumer : public clang::ASTConsumer { feOptions.ClangIRLifetimeCheck, lifetimeOpts, feOptions.ClangIRIdiomRecognizer, idiomRecognizerOpts, feOptions.ClangIRLibOpt, libOptOpts, passOptParsingFailure, + codeGenOptions.OptimizationLevel > 0, action == CIRGenAction::OutputType::EmitCIRFlat, action == CIRGenAction::OutputType::EmitMLIR, feOptions.ClangIREnableCallConvLowering, diff --git a/clang/test/CIR/CodeGen/binop.cpp b/clang/test/CIR/CodeGen/binop.cpp index 045e78ccf021..dcfdf7704045 100644 --- a/clang/test/CIR/CodeGen/binop.cpp +++ b/clang/test/CIR/CodeGen/binop.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck --input-file=%t.cir %s void b0(int a, int b) { diff --git a/clang/test/CIR/CodeGen/complex.c b/clang/test/CIR/CodeGen/complex.c index a1cab1070aca..1bdf62fe9666 100644 --- a/clang/test/CIR/CodeGen/complex.c +++ b/clang/test/CIR/CodeGen/complex.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-simplify -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-BEFORE %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x c++ -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-simplify -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-BEFORE %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-simplify -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-AFTER %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x c++ -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-simplify -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-AFTER %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-BEFORE %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x c++ -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-BEFORE %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-AFTER %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x c++ -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CHECK-AFTER %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -o %t.ll %s // RUN: FileCheck --input-file=%t.ll --check-prefixes=LLVM %s diff --git a/clang/test/CIR/CodeGen/ternary.cpp b/clang/test/CIR/CodeGen/ternary.cpp index 5c17ef5d1a74..7238459bd520 100644 --- a/clang/test/CIR/CodeGen/ternary.cpp +++ b/clang/test/CIR/CodeGen/ternary.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -O1 -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck --input-file=%t.cir %s int x(int y) { diff --git a/clang/test/CIR/Transforms/builtin-assume.cir b/clang/test/CIR/Transforms/builtin-assume.cir index 72afb3812e53..c4f1317abb2b 100644 --- a/clang/test/CIR/Transforms/builtin-assume.cir +++ b/clang/test/CIR/Transforms/builtin-assume.cir @@ -1,6 +1,4 @@ -// RUN: cir-opt --canonicalize -o %t.cir %s -// RUN: FileCheck --input-file %t.cir %s -// RUN: cir-opt -cir-simplify -o %t.cir %s +// RUN: cir-opt -cir-canonicalize -o %t.cir %s // RUN: FileCheck --input-file %t.cir %s !s32i = !cir.int diff --git a/clang/test/CIR/Transforms/merge-cleanups.cir b/clang/test/CIR/Transforms/merge-cleanups.cir index 4280768fc4b0..c9d927b7cae7 100644 --- a/clang/test/CIR/Transforms/merge-cleanups.cir +++ b/clang/test/CIR/Transforms/merge-cleanups.cir @@ -1,4 +1,4 @@ -// RUN: cir-opt %s -cir-simplify -o %t.out.cir +// RUN: cir-opt %s -cir-canonicalize -o %t.out.cir // RUN: FileCheck --input-file=%t.out.cir %s #false = #cir.bool : !cir.bool diff --git a/clang/test/CIR/Transforms/select.cir b/clang/test/CIR/Transforms/select.cir index 6d18be0b9439..29a5d1ed1dde 100644 --- a/clang/test/CIR/Transforms/select.cir +++ b/clang/test/CIR/Transforms/select.cir @@ -1,4 +1,4 @@ -// RUN: cir-opt -cir-simplify -o %t.cir %s +// RUN: cir-opt -cir-canonicalize -cir-simplify -o %t.cir %s // RUN: FileCheck --input-file=%t.cir %s !s32i = !cir.int diff --git a/clang/test/CIR/Transforms/simpl.c b/clang/test/CIR/Transforms/simpl.c index efb22ddb3f57..dda9f495ca4c 100644 --- a/clang/test/CIR/Transforms/simpl.c +++ b/clang/test/CIR/Transforms/simpl.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-simplify %s -o %t1.cir 2>&1 | FileCheck -check-prefix=BEFORE %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-simplify %s -o %t2.cir 2>&1 | FileCheck -check-prefix=AFTER %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize %s -o %t1.cir 2>&1 | FileCheck -check-prefix=BEFORE %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-canonicalize %s -o %t2.cir 2>&1 | FileCheck -check-prefix=AFTER %s #define CHECK_PTR(ptr) \ diff --git a/clang/test/CIR/Transforms/simpl.cir b/clang/test/CIR/Transforms/simpl.cir index 1ebedc323471..3d5d5ec75ad6 100644 --- a/clang/test/CIR/Transforms/simpl.cir +++ b/clang/test/CIR/Transforms/simpl.cir @@ -1,4 +1,4 @@ -// RUN: cir-opt %s -cir-simplify -o - | FileCheck %s +// RUN: cir-opt %s -cir-canonicalize -o - | FileCheck %s !s32i = !cir.int !s64i = !cir.int diff --git a/clang/test/CIR/Transforms/ternary-fold.cir b/clang/test/CIR/Transforms/ternary-fold.cir index 6778d4744a32..72ba4815b2db 100644 --- a/clang/test/CIR/Transforms/ternary-fold.cir +++ b/clang/test/CIR/Transforms/ternary-fold.cir @@ -1,4 +1,4 @@ -// RUN: cir-opt -cir-simplify -o %t.cir %s +// RUN: cir-opt -cir-canonicalize -cir-simplify -o %t.cir %s // RUN: FileCheck --input-file=%t.cir %s !s32i = !cir.int diff --git a/clang/test/CIR/Transforms/ternary-fold.cpp b/clang/test/CIR/Transforms/ternary-fold.cpp index 5f37a8a36b95..69934da793df 100644 --- a/clang/test/CIR/Transforms/ternary-fold.cpp +++ b/clang/test/CIR/Transforms/ternary-fold.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-simplify %s -o %t1.cir 2>&1 | FileCheck -check-prefix=CIR-BEFORE %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-simplify %s -o %t2.cir 2>&1 | FileCheck -check-prefix=CIR-AFTER %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize %s -o %t1.cir 2>&1 | FileCheck -check-prefix=CIR-BEFORE %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-simplify %s -o %t2.cir 2>&1 | FileCheck -check-prefix=CIR-AFTER %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -fclangir -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll --check-prefix=LLVM %s int test(bool x) { @@ -23,7 +23,7 @@ int test(bool x) { // CIR-AFTER-NEXT: %{{.+}} = cir.select if %{{.+}} then %[[#A]] else %[[#B]] : (!cir.bool, !s32i, !s32i) -> !s32i // CIR-AFTER: } -// LLVM: define dso_local i32 @_Z4testb +// LLVM: @_Z4testb // LLVM: %{{.+}} = select i1 %{{.+}}, i32 1, i32 2 // LLVM: } @@ -51,6 +51,6 @@ int test2(bool cond) { // CIR-AFTER-NEXT: %{{.+}} = cir.select if %[[#COND]] then %[[#A]] else %[[#B]] : (!cir.bool, !s32i, !s32i) -> !s32i // CIR-AFTER: } -// LLVM: define dso_local i32 @_Z5test2b +// LLVM: @_Z5test2b // LLVM: %{{.+}} = select i1 %{{.+}}, i32 1, i32 2 // LLVM: } diff --git a/clang/test/CIR/mlirprint.c b/clang/test/CIR/mlirprint.c index 83336cc73792..3514eb895381 100644 --- a/clang/test/CIR/mlirprint.c +++ b/clang/test/CIR/mlirprint.c @@ -11,7 +11,7 @@ int foo(void) { } -// CIR: IR Dump After CIRSimplify (cir-simplify) +// CIR: IR Dump After CIRCanonicalize (cir-canonicalize) // CIR: cir.func @foo() -> !s32i // CIR: IR Dump After LoweringPrepare (cir-lowering-prepare) // CIR: cir.func @foo() -> !s32i @@ -19,14 +19,14 @@ int foo(void) { // CIR-NOT: IR Dump After SCFPrepare // CIR: IR Dump After DropAST (cir-drop-ast) // CIR: cir.func @foo() -> !s32i -// CIRFLAT: IR Dump After CIRSimplify (cir-simplify) +// CIRFLAT: IR Dump After CIRCanonicalize (cir-canonicalize) // CIRFLAT: cir.func @foo() -> !s32i // CIRFLAT: IR Dump After LoweringPrepare (cir-lowering-prepare) // CIRFLAT: cir.func @foo() -> !s32i // CIRFLAT: IR Dump After FlattenCFG (cir-flatten-cfg) // CIRFLAT: IR Dump After DropAST (cir-drop-ast) // CIRFLAT: cir.func @foo() -> !s32i -// CIRMLIR: IR Dump After CIRSimplify (cir-simplify) +// CIRMLIR: IR Dump After CIRCanonicalize (cir-canonicalize) // CIRMLIR: IR Dump After LoweringPrepare (cir-lowering-prepare) // CIRMLIR: IR Dump After SCFPrepare (cir-mlir-scf-prepare // CIRMLIR: IR Dump After DropAST (cir-drop-ast) @@ -35,7 +35,7 @@ int foo(void) { // LLVM: IR Dump After // LLVM: define dso_local i32 @foo() -// CIRPASS-NOT: IR Dump After CIRSimplify +// CIRPASS-NOT: IR Dump After CIRCanonicalize // CIRPASS: IR Dump After DropAST // CFGPASS: IR Dump Before FlattenCFG (cir-flatten-cfg) diff --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp index 343f2d317137..e7af0b214462 100644 --- a/clang/tools/cir-opt/cir-opt.cpp +++ b/clang/tools/cir-opt/cir-opt.cpp @@ -38,6 +38,9 @@ int main(int argc, char **argv) { ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> { return cir::createConvertMLIRToLLVMPass(); }); + ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> { + return mlir::createCIRCanonicalizePass(); + }); ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> { return mlir::createCIRSimplifyPass(); });