llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> Upstreaming FAbsOp as a prerequisite for upstreaming ComplexDivOp --- Full diff: https://github.com/llvm/llvm-project/pull/151750.diff 10 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+18) - (modified) clang/include/clang/CIR/Dialect/IR/CMakeLists.txt (+4) - (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+23) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+7) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+4) - (added) clang/test/CIR/CodeGen/builtins.cpp (+14) - (added) clang/utils/TableGen/CIRLoweringEmitter.cpp (+108) - (modified) clang/utils/TableGen/CMakeLists.txt (+1) - (modified) clang/utils/TableGen/TableGen.cpp (+7) - (modified) clang/utils/TableGen/TableGenBackends.h (+3) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 5ef5b60ed5a52..975a8d102d800 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3199,4 +3199,22 @@ def CIR_ExpectOp : CIR_Op<"expect", [ }]; } +//===----------------------------------------------------------------------===// +// Floating Point Ops +//===----------------------------------------------------------------------===// + +class CIR_UnaryFPToFPBuiltinOp<string mnemonic, string llvmOpName> + : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> +{ + let arguments = (ins CIR_AnyFloatOrVecOfFloatType:$src); + let results = (outs CIR_AnyFloatOrVecOfFloatType:$result); + let summary = "libc builtin equivalent ignoring " + "floating point exceptions and errno"; + let assemblyFormat = "$src `:` type($src) attr-dict"; + + let llvmOp = llvmOpName; +} + +def CIR_FAbsOp : CIR_UnaryFPToFPBuiltinOp<"fabs", "FAbsOp">; + #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt index 6e7f3da4add3e..3a574b96340e7 100644 --- a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt +++ b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt @@ -20,6 +20,10 @@ mlir_tablegen(CIROpsAttributes.h.inc -gen-attrdef-decls) mlir_tablegen(CIROpsAttributes.cpp.inc -gen-attrdef-defs) add_public_tablegen_target(MLIRCIREnumsGen) +clang_tablegen(CIRBuiltinsLowering.inc -gen-cir-builtins-lowering + SOURCE CIROps.td + TARGET CIRBuiltinsLowering) + set(LLVM_TARGET_DEFINITIONS CIRTypeConstraints.td) mlir_tablegen(CIRTypeConstraints.h.inc -gen-type-constraint-decls) mlir_tablegen(CIRTypeConstraints.cpp.inc -gen-type-constraint-defs) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 9049a016b2b9b..201c119c1747f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -71,6 +71,19 @@ RValue CIRGenFunction::emitRotate(const CallExpr *e, bool isRotateLeft) { return RValue::get(r); } +template <class Operation> +static RValue emitUnaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, + const CallExpr &e) { + mlir::Value arg = cgf.emitScalarExpr(e.getArg(0)); + + assert(!cir::MissingFeatures::cgFPOptionsRAII()); + assert(!cir::MissingFeatures::fpConstraints()); + + auto call = + cgf.getBuilder().create<Operation>(arg.getLoc(), arg.getType(), arg); + return RValue::get(call->getResult(0)); +} + RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, const CallExpr *e, ReturnValueSlot returnValue) { @@ -111,6 +124,16 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, default: break; + case Builtin::BIfabs: + case Builtin::BIfabsf: + case Builtin::BIfabsl: + case Builtin::BI__builtin_fabs: + case Builtin::BI__builtin_fabsf: + case Builtin::BI__builtin_fabsf16: + case Builtin::BI__builtin_fabsl: + case Builtin::BI__builtin_fabsf128: + return emitUnaryMaybeConstrainedFPBuiltin<cir::FAbsOp>(*this, *e); + case Builtin::BI__assume: case Builtin::BI__builtin_assume: { if (e->getArg(0)->HasSideEffects(getContext())) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 957a51ab334aa..8d18176be8218 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2215,6 +2215,9 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMVecShuffleOpLowering, CIRToLLVMVecSplatOpLowering, CIRToLLVMVecTernaryOpLowering +#define GET_BUILTIN_LOWERING_LIST +#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc" +#undef GET_BUILTIN_LOWERING_LIST // clang-format on >(converter, patterns.getContext()); @@ -2792,6 +2795,10 @@ mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite( return mlir::success(); } +#define GET_BUILTIN_LOWERING_CLASSES_DEF +#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc" +#undef GET_BUILTIN_LOWERING_CLASSES_DEF + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index f339d4310ae0c..486a6b5daa563 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -628,6 +628,10 @@ class CIRToLLVMGetBitfieldOpLowering mlir::ConversionPatternRewriter &) const override; }; +#define GET_BUILTIN_LOWERING_CLASSES_DECLARE +#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc" +#undef GET_BUILTIN_LOWERING_CLASSES_DECLARE + } // namespace direct } // namespace cir diff --git a/clang/test/CIR/CodeGen/builtins.cpp b/clang/test/CIR/CodeGen/builtins.cpp new file mode 100644 index 0000000000000..3d43821af4e51 --- /dev/null +++ b/clang/test/CIR/CodeGen/builtins.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +double fabs(double x) { + return __builtin_fabs(x); +} + +// CIR: {{.*}} = cir.fabs {{.*}} : !cir.double +// LLVM: {{.*}} = call double @llvm.fabs.f64(double {{.*}}) +// OGCG: {{.*}} = call double @llvm.fabs.f64(double {{.*}}) diff --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp b/clang/utils/TableGen/CIRLoweringEmitter.cpp new file mode 100644 index 0000000000000..e494f38ef5b02 --- /dev/null +++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp @@ -0,0 +1,108 @@ +//===- CIRLoweringEmitter.cpp - Generate lowering of builtins --=-*- C++ -*--=// +// +// 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 "TableGenBackends.h" +#include "llvm/TableGen/TableGenBackend.h" + +using namespace llvm; + +namespace { +std::string ClassDeclaration; +std::string ClassDefinitions; +std::string ClassList; + +// Adapted from mlir/lib/TableGen/Operator.cpp +// Returns the C++ class name of the operation, which is the name of the +// operation with the dialect prefix removed and the first underscore removed. +// If the operation name starts with an underscore, the underscore is considered +// part of the class name. +std::string getCppClassName(const Record *Operation) { + StringRef Name = Operation->getName(); + auto [prefix, cppClassName] = Name.split('_'); + if (prefix.empty()) { + // Class name with a leading underscore and without dialect prefix + return Name.str(); + } + + if (cppClassName.empty()) { + // Class name without dialect prefix + return prefix.str(); + } + + return cppClassName.str(); +} + +void GenerateLowering(const Record *Operation) { + using namespace std::string_literals; + std::string Name = getCppClassName(Operation); + std::string LLVMOp = Operation->getValueAsString("llvmOp").str(); + + ClassDeclaration += + "class CIR" + Name + + "Lowering : public mlir::OpConversionPattern<cir::" + Name + + R"C++(> { + public: + using OpConversionPattern<cir::)C++" + + Name + R"C++(>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::)C++" + + Name + + " op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) " + "const " + "override;" + + R"C++( +}; +)C++"; + + ClassDefinitions += + R"C++(mlir::LogicalResult +CIR)C++" + + Name + "Lowering::matchAndRewrite(cir::" + Name + + R"C++( op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const {)C++"; + + auto ResultCount = Operation->getValueAsDag("results")->getNumArgs(); + if (ResultCount > 0) + ClassDefinitions += R"C++( + auto resTy = this->getTypeConverter()->convertType(op.getType());)C++"; + + ClassDefinitions += R"C++( + rewriter.replaceOpWithNewOp<mlir::LLVM::)C++" + + LLVMOp + ">(op"; + + if (ResultCount > 0) + ClassDefinitions += ", resTy"; + + size_t ArgCount = Operation->getValueAsDag("arguments")->getNumArgs(); + for (size_t i = 0; i != ArgCount; ++i) + ClassDefinitions += ", adaptor.getOperands()[" + std::to_string(i) + ']'; + + ClassDefinitions += R"C++(); + return mlir::success(); +} +)C++"; + + ClassList += ", CIR" + Name + "Lowering\n"; +} +} // namespace + +void clang::EmitCIRBuiltinsLowering(const RecordKeeper &Records, + raw_ostream &OS) { + emitSourceFileHeader("Lowering of ClangIR builtins to LLVM IR builtins", OS); + for (const auto *Builtin : + Records.getAllDerivedDefinitions("LLVMLoweringInfo")) { + if (!Builtin->getValueAsString("llvmOp").empty()) + GenerateLowering(Builtin); + } + + OS << "#ifdef GET_BUILTIN_LOWERING_CLASSES_DECLARE\n" + << ClassDeclaration << "\n#endif\n"; + OS << "#ifdef GET_BUILTIN_LOWERING_CLASSES_DEF\n" + << ClassDefinitions << "\n#endif\n"; + OS << "#ifdef GET_BUILTIN_LOWERING_LIST\n" << ClassList << "\n#endif\n"; +} diff --git a/clang/utils/TableGen/CMakeLists.txt b/clang/utils/TableGen/CMakeLists.txt index ce759ec8548d9..14f13824e9575 100644 --- a/clang/utils/TableGen/CMakeLists.txt +++ b/clang/utils/TableGen/CMakeLists.txt @@ -4,6 +4,7 @@ add_tablegen(clang-tblgen CLANG DESTINATION "${CLANG_TOOLS_INSTALL_DIR}" EXPORT Clang ASTTableGen.cpp + CIRLoweringEmitter.cpp ClangASTNodesEmitter.cpp ClangASTPropertiesEmitter.cpp ClangAttrEmitter.cpp diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index 98c4a07a99c42..d4a383e801085 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -25,6 +25,7 @@ using namespace clang; enum ActionType { PrintRecords, DumpJSON, + GenCIRBuiltinsLowering, GenClangAttrClasses, GenClangAttrParserStringSwitches, GenClangAttrSubjectMatchRulesParserStringSwitches, @@ -128,6 +129,9 @@ cl::opt<ActionType> Action( "Print all records to stdout (default)"), clEnumValN(DumpJSON, "dump-json", "Dump all records as machine-readable JSON"), + clEnumValN(GenCIRBuiltinsLowering, "gen-cir-builtins-lowering", + "Generate lowering of ClangIR builtins to equivalent LLVM " + "IR builtins"), clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes", "Generate clang attribute clases"), clEnumValN(GenClangAttrParserStringSwitches, @@ -354,6 +358,9 @@ bool ClangTableGenMain(raw_ostream &OS, const RecordKeeper &Records) { case DumpJSON: EmitJSON(Records, OS); break; + case GenCIRBuiltinsLowering: + EmitCIRBuiltinsLowering(Records, OS); + break; case GenClangAttrClasses: EmitClangAttrClass(Records, OS); break; diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h index 79b1f66d0e49e..26d9e2c611898 100644 --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -24,6 +24,9 @@ class RecordKeeper; namespace clang { +void EmitCIRBuiltinsLowering(const llvm::RecordKeeper &RK, + llvm::raw_ostream &OS); + void EmitClangDeclContext(const llvm::RecordKeeper &RK, llvm::raw_ostream &OS); /** @param PriorizeIfSubclassOf These classes should be prioritized in the output. `````````` </details> https://github.com/llvm/llvm-project/pull/151750 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits