diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d3ee08c0063d2..aceb427cfc44f4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -920,6 +920,7 @@ Bug Fixes to C++ Support - Clang now diagnoses explicit specializations with storage class specifiers in all contexts. - Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a forward-declared class. (#GH93512). +- Fixed a bug in access checking inside return-type-requirement of compound requirements. (#GH93788). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 63a028a6f47793..55c5ecee45e0ce 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2837,6 +2837,11 @@ class AnnotatingParser { if (!AfterRParen->Next) return false; + if (AfterRParen->is(tok::l_brace) && + AfterRParen->getBlockKind() == BK_BracedInit) { + return true; + } + // If the next token after the parenthesis is a unary operator, assume // that this is cast, unless there are unexpected tokens inside the // parenthesis. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 863cc53c55afa4..1fe1fe9d4f833b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2735,7 +2735,7 @@ TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) { if (TPLInst.isInvalid()) return nullptr; TemplateParameterList *TPL = TransformTemplateParameterList(OrigTPL); - if (!TPL) + if (!TPL || Trap.hasErrorOccurred()) TransRetReq.emplace(createSubstDiag(SemaRef, Info, [&] (llvm::raw_ostream& OS) { RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint() diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp index b7366207882f9e..dc0e84280e0567 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp @@ -189,3 +189,39 @@ namespace std_example { template struct C5_check {}; // expected-note{{because 'short' does not satisfy 'C5'}} using c5 = C5_check; // expected-error{{constraints not satisfied for class template 'C5_check' [with T = short]}} } + +namespace access_checks { +namespace in_return_type_requirement { + +// https://github.com/llvm/llvm-project/issues/93788 +template +concept is_assignable = requires(From from, To to) { + from = to; +}; + +template +class trait { + public: + using public_type = int; + private: + using private_type = int; +}; + +template +concept has_field = requires(T t) { + { t.field } -> is_assignable::private_type>; // expected-note {{'private_type' is a private member}} +}; +template +concept has_field2 = requires(T t) { + { t.field } -> is_assignable::public_type>; +}; + +struct A { + int field; +}; +static_assert(has_field); // expected-error {{static assertion failed}} \ + // expected-note {{because 'A' does not satisfy 'has_field'}} +static_assert(has_field2); + +} // namespace access_checks +} // namespace in_return_type_requirement diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 0dc506458f7c36..12c4b7fdd5ac27 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -662,6 +662,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) { EXPECT_TOKEN(Tokens[3], tok::r_paren, TT_Unknown); EXPECT_TOKEN(Tokens[4], tok::amp, TT_BinaryOperator); + Tokens = annotate("return (struct foo){};"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::r_paren, TT_CastRParen); + Tokens = annotate("#define FOO(bar) foo((uint64_t)&bar)"); ASSERT_EQ(Tokens.size(), 15u) << Tokens; EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_CastRParen); diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index 1443d1e44e10a2..b8e97783c77237 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -176,6 +176,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.calloc libc.src.stdlib.div libc.src.stdlib.free + libc.src.stdlib.freelist_malloc libc.src.stdlib.labs libc.src.stdlib.ldiv libc.src.stdlib.llabs diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 99ae20b726ae26..c9070c2691b192 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -172,6 +172,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.calloc libc.src.stdlib.div libc.src.stdlib.free + libc.src.stdlib.freelist_malloc libc.src.stdlib.labs libc.src.stdlib.ldiv libc.src.stdlib.llabs diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt index 7d99fdf38141ab..61c05f07389590 100644 --- a/libc/src/stdlib/CMakeLists.txt +++ b/libc/src/stdlib/CMakeLists.txt @@ -317,96 +317,121 @@ add_entrypoint_object( libc.include.stdlib ) -if(LLVM_LIBC_INCLUDE_SCUDO) - set(SCUDO_DEPS "") +if(NOT LIBC_TARGET_OS_IS_GPU) + if(LLVM_LIBC_INCLUDE_SCUDO) + set(SCUDO_DEPS "") + + include(${LIBC_SOURCE_DIR}/../compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake) + + # scudo distinguishes riscv32 and riscv64, so we need to translate the architecture + set(LIBC_TARGET_ARCHITECTURE_FOR_SCUDO ${LIBC_TARGET_ARCHITECTURE}) + if(LIBC_TARGET_ARCHITECTURE_IS_RISCV64) + set(LIBC_TARGET_ARCHITECTURE_FOR_SCUDO riscv64) + elseif(LIBC_TARGET_ARCHITECTURE_IS_RISCV32) + set(LIBC_TARGET_ARCHITECTURE_FOR_SCUDO riscv32) + endif() + + if(NOT (LIBC_TARGET_ARCHITECTURE_FOR_SCUDO IN_LIST ALL_SCUDO_STANDALONE_SUPPORTED_ARCH)) + message(FATAL_ERROR "Architecture ${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} is not supported by SCUDO. + Either disable LLVM_LIBC_INCLUDE_SCUDO or change your target architecture.") + endif() + + list(APPEND SCUDO_DEPS RTScudoStandalone.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} + RTScudoStandaloneCWrappers.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO}) + + list(APPEND SCUDO_DEPS + RTGwpAsan.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} + RTGwpAsanBacktraceLibc.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} + RTGwpAsanSegvHandler.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} + ) - include(${LIBC_SOURCE_DIR}/../compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake) - - # scudo distinguishes riscv32 and riscv64, so we need to translate the architecture - set(LIBC_TARGET_ARCHITECTURE_FOR_SCUDO ${LIBC_TARGET_ARCHITECTURE}) - if(LIBC_TARGET_ARCHITECTURE_IS_RISCV64) - set(LIBC_TARGET_ARCHITECTURE_FOR_SCUDO riscv64) - elseif(LIBC_TARGET_ARCHITECTURE_IS_RISCV32) - set(LIBC_TARGET_ARCHITECTURE_FOR_SCUDO riscv32) - endif() + add_entrypoint_external( + malloc + DEPENDS + ${SCUDO_DEPS} + ) + add_entrypoint_external( + calloc + DEPENDS + ${SCUDO_DEPS} + ) + add_entrypoint_external( + realloc + DEPENDS + ${SCUDO_DEPS} + ) + add_entrypoint_external( + aligned_alloc + DEPENDS + ${SCUDO_DEPS} + ) + add_entrypoint_external( + free + DEPENDS + ${SCUDO_DEPS} + ) + else() + # Only use freelist malloc for baremetal targets. + add_entrypoint_object( + freelist_malloc + SRCS + freelist_malloc.cpp + HDRS + malloc.h + DEPENDS + libc.src.__support.freelist_heap + COMPILE_OPTIONS + -DLIBC_FREELIST_MALLOC_SIZE=${LIBC_CONF_FREELIST_MALLOC_BUFFER_SIZE} + ) + get_target_property(freelist_malloc_is_skipped libc.src.stdlib.freelist_malloc "SKIPPED") + if(LIBC_TARGET_OS_IS_BAREMETAL AND NOT freelist_malloc_is_skipped) + add_entrypoint_object( + malloc + ALIAS + DEPENDS + .freelist_malloc + ) + else() + add_entrypoint_external( + malloc + ) + endif() - if(NOT (LIBC_TARGET_ARCHITECTURE_FOR_SCUDO IN_LIST ALL_SCUDO_STANDALONE_SUPPORTED_ARCH)) - message(FATAL_ERROR "Architecture ${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} is not supported by SCUDO. - Either disable LLVM_LIBC_INCLUDE_SCUDO or change your target architecture.") + add_entrypoint_external( + free + ) + add_entrypoint_external( + calloc + ) + add_entrypoint_external( + realloc + ) + add_entrypoint_external( + aligned_alloc + ) endif() +endif() - list(APPEND SCUDO_DEPS RTScudoStandalone.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} - RTScudoStandaloneCWrappers.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO}) +if(NOT LLVM_LIBC_FULL_BUILD) + return() +endif() - list(APPEND SCUDO_DEPS - RTGwpAsan.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} - RTGwpAsanBacktraceLibc.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} - RTGwpAsanSegvHandler.${LIBC_TARGET_ARCHITECTURE_FOR_SCUDO} - ) +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) +endif() - add_entrypoint_external( +if(LIBC_TARGET_OS_IS_GPU) + add_entrypoint_object( malloc + ALIAS DEPENDS - ${SCUDO_DEPS} - ) - add_entrypoint_external( - calloc - DEPENDS - ${SCUDO_DEPS} - ) - add_entrypoint_external( - realloc - DEPENDS - ${SCUDO_DEPS} - ) - add_entrypoint_external( - aligned_alloc - DEPENDS - ${SCUDO_DEPS} - ) - add_entrypoint_external( - free - DEPENDS - ${SCUDO_DEPS} - ) -elseif(LIBC_TARGET_OS_IS_GPU) - add_entrypoint_external( - calloc - ) - add_entrypoint_external( - realloc - ) - add_entrypoint_external( - aligned_alloc + .${LIBC_TARGET_OS}.malloc ) -else() - # Only use freelist malloc for baremetal targets. add_entrypoint_object( - freelist_malloc - SRCS - freelist_malloc.cpp - HDRS - malloc.h - DEPENDS - libc.src.__support.freelist_heap - COMPILE_OPTIONS - -DLIBC_FREELIST_MALLOC_SIZE=${LIBC_CONF_FREELIST_MALLOC_BUFFER_SIZE} - ) - if(LIBC_TARGET_OS_IS_BAREMETAL) - add_entrypoint_object( - malloc - ALIAS - DEPENDS - .freelist_malloc - ) - else() - add_entrypoint_external( - malloc - ) - endif() - - add_entrypoint_external( free + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.free ) add_entrypoint_external( calloc @@ -419,14 +444,6 @@ else() ) endif() -if(NOT LLVM_LIBC_FULL_BUILD) - return() -endif() - -if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) -endif() - add_entrypoint_object( _Exit SRCS @@ -498,19 +515,3 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.abort ) - -if(LIBC_TARGET_OS_IS_GPU) - add_entrypoint_object( - malloc - ALIAS - DEPENDS - .${LIBC_TARGET_OS}.malloc - ) - - add_entrypoint_object( - free - ALIAS - DEPENDS - .${LIBC_TARGET_OS}.free - ) -endif() diff --git a/lldb/include/lldb/Expression/ExpressionParser.h b/lldb/include/lldb/Expression/ExpressionParser.h index ab5223c9155307..2ef7e036909c7b 100644 --- a/lldb/include/lldb/Expression/ExpressionParser.h +++ b/lldb/include/lldb/Expression/ExpressionParser.h @@ -119,14 +119,35 @@ class ExpressionParser { /// \return /// An error code indicating the success or failure of the operation. /// Test with Success(). - virtual Status + Status PrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, std::shared_ptr &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, - lldb_private::ExecutionPolicy execution_policy) = 0; + lldb_private::ExecutionPolicy execution_policy); bool GetGenerateDebugInfo() const { return m_generate_debug_info; } +protected: + virtual Status + DoPrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, + std::shared_ptr &execution_unit_sp, + ExecutionContext &exe_ctx, bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) = 0; + +private: + /// Run all static initializers for an execution unit. + /// + /// \param[in] execution_unit_sp + /// The execution unit. + /// + /// \param[in] exe_ctx + /// The execution context to use when running them. Thread can't be null. + /// + /// \return + /// The error code indicating the + Status RunStaticInitializers(lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx); + protected: Expression &m_expr; ///< The expression to be parsed bool m_generate_debug_info; diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt index 9ba5fefc09b6a7..be1e132f7aaad0 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -3,6 +3,7 @@ add_lldb_library(lldbExpression NO_PLUGIN_DEPENDENCIES DWARFExpression.cpp DWARFExpressionList.cpp Expression.cpp + ExpressionParser.cpp ExpressionTypeSystemHelper.cpp ExpressionVariable.cpp FunctionCaller.cpp diff --git a/lldb/source/Expression/ExpressionParser.cpp b/lldb/source/Expression/ExpressionParser.cpp new file mode 100644 index 00000000000000..e9f7121c2499ef --- /dev/null +++ b/lldb/source/Expression/ExpressionParser.cpp @@ -0,0 +1,72 @@ +//===-- ExpressionParser.cpp ----------------------------------------------===// +// +// 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 "lldb/Expression/ExpressionParser.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +using namespace lldb; +using namespace lldb_private; + +Status ExpressionParser::PrepareForExecution( + addr_t &func_addr, addr_t &func_end, + std::shared_ptr &execution_unit_sp, + ExecutionContext &exe_ctx, bool &can_interpret, + ExecutionPolicy execution_policy) { + Status status = + DoPrepareForExecution(func_addr, func_end, execution_unit_sp, exe_ctx, + can_interpret, execution_policy); + if (status.Success() && exe_ctx.GetProcessPtr() && exe_ctx.HasThreadScope()) + status = RunStaticInitializers(execution_unit_sp, exe_ctx); + + return status; +} + +Status +ExpressionParser::RunStaticInitializers(IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx) { + Status err; + + if (!execution_unit_sp.get()) { + err.SetErrorString( + "can't run static initializers for a NULL execution unit"); + return err; + } + + if (!exe_ctx.HasThreadScope()) { + err.SetErrorString("can't run static initializers without a thread"); + return err; + } + + std::vector static_initializers; + + execution_unit_sp->GetStaticInitializers(static_initializers); + + for (addr_t static_initializer : static_initializers) { + EvaluateExpressionOptions options; + + ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction( + exe_ctx.GetThreadRef(), Address(static_initializer), CompilerType(), + llvm::ArrayRef(), options)); + + DiagnosticManager execution_errors; + ExpressionResults results = + exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan( + exe_ctx, call_static_initializer, options, execution_errors); + + if (results != eExpressionCompleted) { + err.SetErrorStringWithFormat("couldn't run static initializer: %s", + execution_errors.GetString().c_str()); + return err; + } + } + + return err; +} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 1dd98567f8d69b..303e88feea20b6 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -1296,7 +1296,7 @@ static bool FindFunctionInModule(ConstString &mangled_name, return false; } -lldb_private::Status ClangExpressionParser::PrepareForExecution( +lldb_private::Status ClangExpressionParser::DoPrepareForExecution( lldb::addr_t &func_addr, lldb::addr_t &func_end, lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { @@ -1472,47 +1472,3 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( return err; } - -lldb_private::Status ClangExpressionParser::RunStaticInitializers( - lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx) { - lldb_private::Status err; - - lldbassert(execution_unit_sp.get()); - lldbassert(exe_ctx.HasThreadScope()); - - if (!execution_unit_sp.get()) { - err.SetErrorString( - "can't run static initializers for a NULL execution unit"); - return err; - } - - if (!exe_ctx.HasThreadScope()) { - err.SetErrorString("can't run static initializers without a thread"); - return err; - } - - std::vector static_initializers; - - execution_unit_sp->GetStaticInitializers(static_initializers); - - for (lldb::addr_t static_initializer : static_initializers) { - EvaluateExpressionOptions options; - - lldb::ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction( - exe_ctx.GetThreadRef(), Address(static_initializer), CompilerType(), - llvm::ArrayRef(), options)); - - DiagnosticManager execution_errors; - lldb::ExpressionResults results = - exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan( - exe_ctx, call_static_initializer, options, execution_errors); - - if (results != lldb::eExpressionCompleted) { - err.SetErrorStringWithFormat("couldn't run static initializer: %s", - execution_errors.GetString().c_str()); - return err; - } - } - - return err; -} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 185a5a381f23c6..0852e928a9d421 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -113,24 +113,11 @@ class ClangExpressionParser : public ExpressionParser { /// \return /// An error code indicating the success or failure of the operation. /// Test with Success(). - Status - PrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, - lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx, bool &can_interpret, - lldb_private::ExecutionPolicy execution_policy) override; - - /// Run all static initializers for an execution unit. - /// - /// \param[in] execution_unit_sp - /// The execution unit. - /// - /// \param[in] exe_ctx - /// The execution context to use when running them. Thread can't be null. - /// - /// \return - /// The error code indicating the - Status RunStaticInitializers(lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx); + Status DoPrepareForExecution( + lldb::addr_t &func_addr, lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, + bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) override; /// Returns a string representing current ABI. /// diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index c7e98d12590d99..35038a56440d59 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -698,21 +698,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, if (!parse_success) return false; - if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) { - Status static_init_error = - m_parser->RunStaticInitializers(m_execution_unit_sp, exe_ctx); - - if (!static_init_error.Success()) { - const char *error_cstr = static_init_error.AsCString(); - if (error_cstr && error_cstr[0]) - diagnostic_manager.Printf(lldb::eSeverityError, "%s\n", error_cstr); - else - diagnostic_manager.PutString(lldb::eSeverityError, - "couldn't run static initializers\n"); - return false; - } - } - if (m_execution_unit_sp) { bool register_execution_unit = false; diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h index 7d15664fbe7548..8c4a70493383ad 100644 --- a/llvm/include/llvm/CodeGen/MachinePassManager.h +++ b/llvm/include/llvm/CodeGen/MachinePassManager.h @@ -36,35 +36,20 @@ class MachineFunction; extern template class AnalysisManager; using MachineFunctionAnalysisManager = AnalysisManager; -namespace detail { - -template -struct MachinePassModel - : PassModel { - explicit MachinePassModel(PassT &&Pass) - : PassModel( - std::move(Pass)) {} - - friend void swap(MachinePassModel &LHS, MachinePassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - - MachinePassModel &operator=(MachinePassModel RHS) { - swap(*this, RHS); - return *this; - } - - MachinePassModel &operator=(const MachinePassModel &) = delete; - PreservedAnalyses run(MachineFunction &IR, - MachineFunctionAnalysisManager &AM) override { +/// An RAII based helper class to modify MachineFunctionProperties when running +/// pass. Define a MFPropsModifier in PassT::run to set +/// MachineFunctionProperties properly. +template class MFPropsModifier { +public: + MFPropsModifier(PassT &P_, MachineFunction &MF_) : P(P_), MF(MF_) { + auto &MFProps = MF.getProperties(); #ifndef NDEBUG - if constexpr (is_detected::value) { - auto &MFProps = IR.getProperties(); - auto RequiredProperties = this->Pass.getRequiredProperties(); + if constexpr (has_get_required_properties_v) { + auto &MFProps = MF.getProperties(); + auto RequiredProperties = P.getRequiredProperties(); if (!MFProps.verifyRequiredProperties(RequiredProperties)) { errs() << "MachineFunctionProperties required by " << PassT::name() - << " pass are not met by function " << IR.getName() << ".\n" + << " pass are not met by function " << MF.getName() << ".\n" << "Required properties: "; RequiredProperties.print(errs()); errs() << "\nCurrent properties: "; @@ -73,18 +58,22 @@ struct MachinePassModel report_fatal_error("MachineFunctionProperties check failed"); } } -#endif - - auto PA = this->Pass.run(IR, AM); +#endif // NDEBUG + if constexpr (has_get_cleared_properties_v) + MFProps.reset(P.getClearedProperties()); + } - if constexpr (is_detected::value) - IR.getProperties().set(this->Pass.getSetProperties()); - if constexpr (is_detected::value) - IR.getProperties().reset(this->Pass.getClearedProperties()); - return PA; + ~MFPropsModifier() { + if constexpr (has_get_set_properties_v) { + auto &MFProps = MF.getProperties(); + MFProps.set(P.getSetProperties()); + } } private: + PassT &P; + MachineFunction &MF; + template using has_get_required_properties_t = decltype(std::declval().getRequiredProperties()); @@ -96,8 +85,19 @@ struct MachinePassModel template using has_get_cleared_properties_t = decltype(std::declval().getClearedProperties()); + + template + static constexpr bool has_get_required_properties_v = + is_detected::value; + + template + static constexpr bool has_get_set_properties_v = + is_detected::value; + + template + static constexpr bool has_get_cleared_properties_v = + is_detected::value; }; -} // namespace detail using MachineFunctionAnalysisManagerModuleProxy = InnerAnalysisManagerProxy; @@ -219,21 +219,6 @@ createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) { new PassModelT(std::forward(Pass)))); } -template <> -template -void PassManager::addPass(PassT &&Pass) { - using MachinePassModelT = detail::MachinePassModel; - // Do not use make_unique or emplace_back, they cause too many template - // instantiations, causing terrible compile times. - if constexpr (std::is_same_v>) { - for (auto &P : Pass.Passes) - Passes.push_back(std::move(P)); - } else { - Passes.push_back(std::unique_ptr( - new MachinePassModelT(std::forward(Pass)))); - } -} - template <> PreservedAnalyses PassManager::run(MachineFunction &, diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index 97405ecffdb559..23a05c056dfafd 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -189,24 +189,27 @@ class PassManager : public PassInfoMixin< PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs); - // FIXME: Revert to enable_if style when gcc >= 11.1 - template LLVM_ATTRIBUTE_MINSIZE void addPass(PassT &&Pass) { + template + LLVM_ATTRIBUTE_MINSIZE std::enable_if_t> + addPass(PassT &&Pass) { using PassModelT = detail::PassModel; - if constexpr (!std::is_same_v) { - // Do not use make_unique or emplace_back, they cause too many template - // instantiations, causing terrible compile times. - Passes.push_back(std::unique_ptr( - new PassModelT(std::forward(Pass)))); - } else { - /// When adding a pass manager pass that has the same type as this pass - /// manager, simply move the passes over. This is because we don't have - /// use cases rely on executing nested pass managers. Doing this could - /// reduce implementation complexity and avoid potential invalidation - /// issues that may happen with nested pass managers of the same type. - for (auto &P : Pass.Passes) - Passes.push_back(std::move(P)); - } + // Do not use make_unique or emplace_back, they cause too many template + // instantiations, causing terrible compile times. + Passes.push_back(std::unique_ptr( + new PassModelT(std::forward(Pass)))); + } + + /// When adding a pass manager pass that has the same type as this pass + /// manager, simply move the passes over. This is because we don't have + /// use cases rely on executing nested pass managers. Doing this could + /// reduce implementation complexity and avoid potential invalidation + /// issues that may happen with nested pass managers of the same type. + template + LLVM_ATTRIBUTE_MINSIZE std::enable_if_t> + addPass(PassT &&Pass) { + for (auto &P : Pass.Passes) + Passes.push_back(std::move(P)); } /// Returns if the pass manager contains any passes. diff --git a/llvm/include/llvm/MC/MCAsmLayout.h b/llvm/include/llvm/MC/MCAsmLayout.h index 6fbfce78759e1b..e3f707fd21a186 100644 --- a/llvm/include/llvm/MC/MCAsmLayout.h +++ b/llvm/include/llvm/MC/MCAsmLayout.h @@ -45,7 +45,7 @@ class MCAsmLayout { /// its bundle padding will be recomputed. void invalidateFragmentsFrom(MCFragment *F); - void layoutBundle(MCFragment *F); + void layoutBundle(MCFragment *Prev, MCFragment *F); /// \name Section Access (in layout order) /// @{ diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h index 5f8ae5ace56fd1..f96bddd7365335 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -48,7 +48,7 @@ class MCELFStreamer : public MCObjectStreamer { void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override; void changeSection(MCSection *Section, const MCExpr *Subsection) override; void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment *F, + void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F, uint64_t Offset) override; void emitAssemblerFlag(MCAssemblerFlag Flag) override; void emitThumbFunc(MCSymbol *Func) override; diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h index 555730828b4625..72db28cb5eb67d 100644 --- a/llvm/include/llvm/MC/MCFragment.h +++ b/llvm/include/llvm/MC/MCFragment.h @@ -58,7 +58,7 @@ class MCFragment { MCFragment *Next = nullptr; /// The data for the section this fragment is in. - MCSection *Parent; + MCSection *Parent = nullptr; /// The offset of this fragment in its section. uint64_t Offset = 0; @@ -72,8 +72,7 @@ class MCFragment { bool HasInstructions : 1; bool LinkerRelaxable : 1; - MCFragment(FragmentType Kind, bool HasInstructions, - MCSection *Parent = nullptr); + MCFragment(FragmentType Kind, bool HasInstructions); public: MCFragment() = delete; @@ -107,7 +106,7 @@ class MCFragment { class MCDummyFragment : public MCFragment { public: - explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {} + explicit MCDummyFragment() : MCFragment(FT_Dummy, false) {} static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; } }; @@ -122,9 +121,8 @@ class MCEncodedFragment : public MCFragment { uint8_t BundlePadding = 0; protected: - MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions, - MCSection *Sec) - : MCFragment(FType, HasInstructions, Sec) {} + MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions) + : MCFragment(FType, HasInstructions) {} /// The MCSubtargetInfo in effect when the instruction was encoded. /// It must be non-null for instructions. @@ -182,9 +180,8 @@ class MCEncodedFragmentWithContents : public MCEncodedFragment { protected: MCEncodedFragmentWithContents(MCFragment::FragmentType FType, - bool HasInstructions, - MCSection *Sec) - : MCEncodedFragment(FType, HasInstructions, Sec) {} + bool HasInstructions) + : MCEncodedFragment(FType, HasInstructions) {} public: SmallVectorImpl &getContents() { return Contents; } @@ -203,10 +200,8 @@ class MCEncodedFragmentWithFixups : protected: MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, - bool HasInstructions, - MCSection *Sec) - : MCEncodedFragmentWithContents(FType, HasInstructions, - Sec) {} + bool HasInstructions) + : MCEncodedFragmentWithContents(FType, HasInstructions) {} public: @@ -234,8 +229,7 @@ class MCEncodedFragmentWithFixups : /// class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { public: - MCDataFragment(MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} + MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {} static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; @@ -252,9 +246,8 @@ class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { /// class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> { public: - MCCompactEncodedInstFragment(MCSection *Sec = nullptr) - : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) { - } + MCCompactEncodedInstFragment() + : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true) {} static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_CompactEncodedInst; @@ -272,10 +265,10 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> { bool AllowAutoPadding = false; public: - MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, - MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec), - Inst(Inst) { this->STI = &STI; } + MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI) + : MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) { + this->STI = &STI; + } const MCInst &getInst() const { return Inst; } void setInst(const MCInst &Value) { Inst = Value; } @@ -312,8 +305,8 @@ class MCAlignFragment : public MCFragment { public: MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize, - unsigned MaxBytesToEmit, MCSection *Sec = nullptr) - : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false), + unsigned MaxBytesToEmit) + : MCFragment(FT_Align, false), Alignment(Alignment), EmitNops(false), Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} Align getAlignment() const { return Alignment; } @@ -349,8 +342,8 @@ class MCFillFragment : public MCFragment { public: MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues, - SMLoc Loc, MCSection *Sec = nullptr) - : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value), + SMLoc Loc) + : MCFragment(FT_Fill, false), ValueSize(VSize), Value(Value), NumValues(NumValues), Loc(Loc) {} uint64_t getValue() const { return Value; } @@ -378,8 +371,8 @@ class MCNopsFragment : public MCFragment { public: MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L, - const MCSubtargetInfo &STI, MCSection *Sec = nullptr) - : MCFragment(FT_Nops, false, Sec), Size(NumBytes), + const MCSubtargetInfo &STI) + : MCFragment(FT_Nops, false), Size(NumBytes), ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {} int64_t getNumBytes() const { return Size; } @@ -405,10 +398,8 @@ class MCOrgFragment : public MCFragment { SMLoc Loc; public: - MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc, - MCSection *Sec = nullptr) - : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset), - Loc(Loc) {} + MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc) + : MCFragment(FT_Org, false), Value(Value), Offset(&Offset), Loc(Loc) {} const MCExpr &getOffset() const { return *Offset; } @@ -429,9 +420,9 @@ class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> { const MCExpr *Value; public: - MCLEBFragment(const MCExpr &Value, bool IsSigned, MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false, Sec), - IsSigned(IsSigned), Value(&Value) { + MCLEBFragment(const MCExpr &Value, bool IsSigned) + : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned), + Value(&Value) { getContents().push_back(0); } @@ -457,9 +448,8 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> { const MCExpr *AddrDelta; public: - MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, - MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec), + MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta) + : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false), LineDelta(LineDelta), AddrDelta(&AddrDelta) {} int64_t getLineDelta() const { return LineDelta; } @@ -477,8 +467,8 @@ class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> { const MCExpr *AddrDelta; public: - MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec), + MCDwarfCallFrameFragment(const MCExpr &AddrDelta) + : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {} const MCExpr &getAddrDelta() const { return *AddrDelta; } @@ -494,8 +484,8 @@ class MCSymbolIdFragment : public MCFragment { const MCSymbol *Sym; public: - MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) - : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {} + MCSymbolIdFragment(const MCSymbol *Sym) + : MCFragment(FT_SymbolId, false), Sym(Sym) {} const MCSymbol *getSymbol() { return Sym; } const MCSymbol *getSymbol() const { return Sym; } @@ -522,9 +512,8 @@ class MCCVInlineLineTableFragment : public MCFragment { public: MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId, unsigned StartLineNum, const MCSymbol *FnStartSym, - const MCSymbol *FnEndSym, - MCSection *Sec = nullptr) - : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId), + const MCSymbol *FnEndSym) + : MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId), StartFileId(StartFileId), StartLineNum(StartLineNum), FnStartSym(FnStartSym), FnEndSym(FnEndSym) {} @@ -551,8 +540,8 @@ class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> { public: MCCVDefRangeFragment( ArrayRef> Ranges, - StringRef FixedSizePortion, MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec), + StringRef FixedSizePortion) + : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false), Ranges(Ranges.begin(), Ranges.end()), FixedSizePortion(FixedSizePortion) {} @@ -583,9 +572,8 @@ class MCBoundaryAlignFragment : public MCFragment { const MCSubtargetInfo &STI; public: - MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI, - MCSection *Sec = nullptr) - : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary), + MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI) + : MCFragment(FT_BoundaryAlign, false), AlignBoundary(AlignBoundary), STI(STI) {} uint64_t getSize() const { return Size; } @@ -613,8 +601,8 @@ class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> { const MCExpr *AddrDelta; public: - MCPseudoProbeAddrFragment(const MCExpr *AddrDelta, MCSection *Sec = nullptr) - : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false, Sec), + MCPseudoProbeAddrFragment(const MCExpr *AddrDelta) + : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false), AddrDelta(AddrDelta) {} const MCExpr &getAddrDelta() const { return *AddrDelta; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index c0a337f5ea45e5..f4406b255231db 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -91,7 +91,6 @@ class MCObjectStreamer : public MCStreamer { MCFragment *getCurrentFragment() const; void insert(MCFragment *F) { - flushPendingLabels(F); MCSection *CurSection = getCurrentSectionOnly(); CurSection->addFragment(*F); F->setParent(CurSection); @@ -106,31 +105,22 @@ class MCObjectStreamer : public MCStreamer { protected: bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection); - /// Assign a label to the current Section and Subsection even though a - /// fragment is not yet present. Use flushPendingLabels(F) to associate - /// a fragment with this label. - void addPendingLabel(MCSymbol* label); - /// If any labels have been emitted but not assigned fragments in the current /// Section and Subsection, ensure that they get assigned to fragment F. /// Optionally, one can provide an offset \p FOffset as a symbol offset within /// the fragment. - void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0); + void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0) {} public: void visitUsedSymbol(const MCSymbol &Sym) override; - /// Create a data fragment for any pending labels across all Sections - /// and Subsections. - void flushPendingLabels(); - MCAssembler &getAssembler() { return *Assembler; } MCAssembler *getAssemblerPtr() override; /// \name MCStreamer Interface /// @{ void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - virtual void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment *F, + virtual void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F, uint64_t Offset); void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void emitConditionalAssignment(MCSymbol *Symbol, diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 9b3df813242267..969f54cca2382e 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -226,13 +226,6 @@ class MCSection { /// Add a pending label for the requested subsection. This label will be /// associated with a fragment in flushPendingLabels() void addPendingLabel(MCSymbol* label, unsigned Subsection = 0); - - /// Associate all pending labels in a subsection with a fragment. - void flushPendingLabels(MCFragment *F, unsigned Subsection); - - /// Associate all pending labels with empty data fragments. One fragment - /// will be created for each subsection as necessary. - void flushPendingLabels(); }; } // end namespace llvm diff --git a/llvm/include/llvm/MC/MCWasmStreamer.h b/llvm/include/llvm/MC/MCWasmStreamer.h index f95628d5e0e5f7..6c9687f3ce442f 100644 --- a/llvm/include/llvm/MC/MCWasmStreamer.h +++ b/llvm/include/llvm/MC/MCWasmStreamer.h @@ -42,7 +42,7 @@ class MCWasmStreamer : public MCObjectStreamer { void changeSection(MCSection *Section, const MCExpr *Subsection) override; void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment *F, + void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F, uint64_t Offset) override; void emitAssemblerFlag(MCAssemblerFlag Flag) override; void emitThumbFunc(MCSymbol *Func) override; diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h index d5ddf16957c836..9bb1d8cbddc5e6 100644 --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -294,6 +294,13 @@ getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, uint32_t MaxNumValueData, uint32_t &ActualNumValueData, uint64_t &TotalC, bool GetNoICPValue = false); +/// Extract the value profile data from \p Inst and returns them if \p Inst is +/// annotated with value profile data. Returns an empty vector otherwise. +SmallVector +getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, + uint32_t MaxNumValueData, uint64_t &TotalC, + bool GetNoICPValue = false); + inline StringRef getPGOFuncNameMetadataName() { return "PGOFuncName"; } /// Return the PGOFuncName meta data associated with a function. diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index c6934f55ee1149..94ac0484f5ec7f 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -143,20 +143,15 @@ static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser, const Instruction *I = dyn_cast(CurUser); if (I) { - uint32_t ActualNumValueData = 0; uint64_t TotalCount = 0; // MaxNumVTableAnnotations is the maximum number of vtables annotated on // the instruction. - auto ValueDataArray = - getValueProfDataFromInst(*I, IPVK_VTableTarget, MaxNumVTableAnnotations, - ActualNumValueData, TotalCount); - - if (ValueDataArray.get()) { - for (uint32_t j = 0; j < ActualNumValueData; j++) { - RefEdges.insert(Index.getOrInsertValueInfo(/* VTableGUID = */ - ValueDataArray[j].Value)); - } - } + auto ValueDataArray = getValueProfDataFromInst( + *I, IPVK_VTableTarget, MaxNumVTableAnnotations, TotalCount); + + for (const auto &V : ValueDataArray) + RefEdges.insert(Index.getOrInsertValueInfo(/* VTableGUID = */ + V.Value)); } return HasBlockAddress; } diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 4b437b6f79d8ab..cbd291295359e3 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -2044,6 +2044,7 @@ bool RegAllocFastImpl::runOnMachineFunction(MachineFunction &MF) { PreservedAnalyses RegAllocFastPass::run(MachineFunction &MF, MachineFunctionAnalysisManager &) { + MFPropsModifier _(*this, MF); RegAllocFastImpl Impl(Opts.Filter, Opts.ClearVRegs); bool Changed = Impl.runOnMachineFunction(MF); if (!Changed) diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 17f09001b184aa..671f6f71b3a4f0 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -403,7 +403,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, llvm_unreachable("invalid fragment kind"); } -void MCAsmLayout::layoutBundle(MCFragment *F) { +void MCAsmLayout::layoutBundle(MCFragment *Prev, MCFragment *F) { // If bundling is enabled and this fragment has instructions in it, it has to // obey the bundling restrictions. With padding, we'll have: // @@ -439,6 +439,9 @@ void MCAsmLayout::layoutBundle(MCFragment *F) { report_fatal_error("Padding cannot exceed 255 bytes"); EF->setBundlePadding(static_cast(RequiredBundlePadding)); EF->Offset += RequiredBundlePadding; + if (auto *DF = dyn_cast_or_null(Prev)) + if (DF->getContents().empty()) + DF->Offset = EF->Offset; } uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { @@ -451,14 +454,16 @@ void MCAsmLayout::ensureValid(const MCFragment *Frag) const { if (Sec.hasLayout()) return; Sec.setHasLayout(true); + MCFragment *Prev = nullptr; uint64_t Offset = 0; for (MCFragment &F : Sec) { F.Offset = Offset; if (Assembler.isBundlingEnabled() && F.hasInstructions()) { - const_cast(this)->layoutBundle(&F); + const_cast(this)->layoutBundle(Prev, &F); Offset = F.Offset; } Offset += getAssembler().computeFragmentSize(*this, F); + Prev = &F; } } @@ -829,7 +834,8 @@ void MCAssembler::layout(MCAsmLayout &Layout) { Sec->setLayoutOrder(i); // Chain together fragments from all subsections. - MCDummyFragment Dummy(Sec); + MCDummyFragment Dummy; + Dummy.setParent(Sec); MCFragment *Tail = &Dummy; for (auto &[_, List] : Sec->Subsections) { if (!List.Head) diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index 8be3c0e7211891..a4788566926575 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -70,7 +70,7 @@ void MCELFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { Symbol->setType(ELF::STT_TLS); } -void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F, +void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, uint64_t Offset) { auto *Symbol = cast(S); MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset); diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index 0d8d639b0f8aff..d90fd34815bdac 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -198,13 +198,8 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, /* *** */ -MCFragment::MCFragment(FragmentType Kind, bool HasInstructions, - MCSection *Parent) - : Parent(Parent), Kind(Kind), HasInstructions(HasInstructions), - LinkerRelaxable(false) { - if (Parent && !isa(*this)) - Parent->addFragment(*this); -} +MCFragment::MCFragment(FragmentType Kind, bool HasInstructions) + : Kind(Kind), HasInstructions(HasInstructions), LinkerRelaxable(false) {} void MCFragment::destroy() { // First check if we are the sentinel. diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 35521ddab47772..f724973f46449a 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -46,59 +46,6 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() { return nullptr; } -void MCObjectStreamer::addPendingLabel(MCSymbol* S) { - MCSection *CurSection = getCurrentSectionOnly(); - if (CurSection) { - // Register labels that have not yet been assigned to a Section. - if (!PendingLabels.empty()) { - for (MCSymbol* Sym : PendingLabels) - CurSection->addPendingLabel(Sym); - PendingLabels.clear(); - } - - // Add this label to the current Section / Subsection. - CurSection->addPendingLabel(S, CurSubsectionIdx); - - // Add this Section to the list of PendingLabelSections. - PendingLabelSections.insert(CurSection); - } else - // There is no Section / Subsection for this label yet. - PendingLabels.push_back(S); -} - -void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) { - assert(F); - MCSection *CurSection = getCurrentSectionOnly(); - if (!CurSection) { - assert(PendingLabels.empty()); - return; - } - // Register labels that have not yet been assigned to a Section. - if (!PendingLabels.empty()) { - for (MCSymbol* Sym : PendingLabels) - CurSection->addPendingLabel(Sym, CurSubsectionIdx); - PendingLabels.clear(); - } - - // Associate the labels with F. - CurSection->flushPendingLabels(F, CurSubsectionIdx); -} - -void MCObjectStreamer::flushPendingLabels() { - // Register labels that have not yet been assigned to a Section. - if (!PendingLabels.empty()) { - MCSection *CurSection = getCurrentSectionOnly(); - assert(CurSection); - for (MCSymbol* Sym : PendingLabels) - CurSection->addPendingLabel(Sym, CurSubsectionIdx); - PendingLabels.clear(); - } - - // Assign an empty data fragment to all remaining pending labels. - for (MCSection* Section : PendingLabelSections) - Section->flushPendingLabels(); -} - // When fixup's offset is a forward declared label, e.g.: // // .reloc 1f, R_MIPS_JALR, foo @@ -113,7 +60,6 @@ void MCObjectStreamer::resolvePendingFixups() { "unresolved relocation offset"); continue; } - flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size()); PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() + PendingFixup.Fixup.getOffset()); @@ -245,7 +191,6 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { MCStreamer::emitValueImpl(Value, Size, Loc); MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); MCDwarfLineEntry::make(this, getCurrentSectionOnly()); @@ -291,17 +236,9 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { // If there is a current fragment, mark the symbol as pointing into it. // Otherwise queue the label and set its fragment pointer when we emit the // next fragment. - auto *F = dyn_cast_or_null(getCurrentFragment()); - if (F) { - Symbol->setFragment(F); - Symbol->setOffset(F->getContents().size()); - } else { - // Assign all pending labels to offset 0 within the dummy "pending" - // fragment. (They will all be reassigned to a real fragment in - // flushPendingLabels()) - Symbol->setOffset(0); - addPendingLabel(Symbol); - } + MCDataFragment *F = getOrCreateDataFragment(); + Symbol->setFragment(F); + Symbol->setOffset(F->getContents().size()); emitPendingAssignments(Symbol); } @@ -319,21 +256,12 @@ void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) { // Emit a label at a previously emitted fragment/offset position. This must be // within the currently-active section. void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, - MCFragment *F, uint64_t Offset) { - assert(F->getParent() == getCurrentSectionOnly()); - + MCDataFragment &F, uint64_t Offset) { + assert(F.getParent() == getCurrentSectionOnly()); MCStreamer::emitLabel(Symbol, Loc); getAssembler().registerSymbol(*Symbol); - auto *DF = dyn_cast_or_null(F); + Symbol->setFragment(&F); Symbol->setOffset(Offset); - if (DF) { - Symbol->setFragment(F); - } else { - assert(isa(F) && - "F must either be an MCDataFragment or the pending MCDummyFragment"); - assert(Offset == 0); - addPendingLabel(Symbol); - } } void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) { @@ -567,8 +495,7 @@ void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label, SMLoc Loc) { const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, Loc); - insert(getContext().allocFragment(*AddrDelta, - nullptr)); + insert(getContext().allocFragment(*AddrDelta)); } void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo, @@ -608,11 +535,9 @@ void MCObjectStreamer::emitCVInlineLinetableDirective( void MCObjectStreamer::emitCVDefRangeDirective( ArrayRef> Ranges, StringRef FixedSizePortion) { - MCFragment *Frag = - getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); + getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); // Attach labels that were pending before we created the defrange fragment to // the beginning of the new fragment. - flushPendingLabels(Frag, 0); this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion); } @@ -630,7 +555,6 @@ void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) { void MCObjectStreamer::emitBytes(StringRef Data) { MCDwarfLineEntry::make(this, getCurrentSectionOnly()); MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); DF->getContents().append(Data.begin(), Data.end()); } @@ -663,8 +587,6 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, // Associate DTPRel32 fixup with data and resize data area void MCObjectStreamer::emitDTPRel32Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), Value, FK_DTPRel_4)); DF->getContents().resize(DF->getContents().size() + 4, 0); @@ -673,8 +595,6 @@ void MCObjectStreamer::emitDTPRel32Value(const MCExpr *Value) { // Associate DTPRel64 fixup with data and resize data area void MCObjectStreamer::emitDTPRel64Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), Value, FK_DTPRel_8)); DF->getContents().resize(DF->getContents().size() + 8, 0); @@ -683,8 +603,6 @@ void MCObjectStreamer::emitDTPRel64Value(const MCExpr *Value) { // Associate TPRel32 fixup with data and resize data area void MCObjectStreamer::emitTPRel32Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), Value, FK_TPRel_4)); DF->getContents().resize(DF->getContents().size() + 4, 0); @@ -693,8 +611,6 @@ void MCObjectStreamer::emitTPRel32Value(const MCExpr *Value) { // Associate TPRel64 fixup with data and resize data area void MCObjectStreamer::emitTPRel64Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), Value, FK_TPRel_8)); DF->getContents().resize(DF->getContents().size() + 8, 0); @@ -703,8 +619,6 @@ void MCObjectStreamer::emitTPRel64Value(const MCExpr *Value) { // Associate GPRel32 fixup with data and resize data area void MCObjectStreamer::emitGPRel32Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back( MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 4, 0); @@ -713,8 +627,6 @@ void MCObjectStreamer::emitGPRel32Value(const MCExpr *Value) { // Associate GPRel64 fixup with data and resize data area void MCObjectStreamer::emitGPRel64Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back( MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 8, 0); @@ -799,8 +711,6 @@ MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext()); MCDataFragment *DF = getOrCreateDataFragment(&STI); - flushPendingLabels(DF, DF->getContents().size()); - MCValue OffsetVal; if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr, nullptr)) return std::make_pair(false, @@ -840,9 +750,6 @@ MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - assert(getCurrentSectionOnly() && "need a section"); insert( getContext().allocFragment(FillValue, 1, NumBytes, Loc)); @@ -871,9 +778,6 @@ void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size, } // Otherwise emit as fragment. - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - assert(getCurrentSectionOnly() && "need a section"); insert( getContext().allocFragment(Expr, Size, NumValues, Loc)); @@ -881,12 +785,7 @@ void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size, void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength, SMLoc Loc, const MCSubtargetInfo &STI) { - // Emit an NOP fragment. - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - assert(getCurrentSectionOnly() && "need a section"); - insert(getContext().allocFragment( NumBytes, ControlledNopLength, Loc, STI)); } @@ -926,9 +825,6 @@ void MCObjectStreamer::finishImpl() { // Emit pseudo probes for the current module. MCPseudoProbeTable::emit(this); - // Update any remaining pending labels with empty data fragments. - flushPendingLabels(); - resolvePendingFixups(); getAssembler().Finish(); } diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index 85f6492af20f59..495826efb6a2a4 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -23,8 +23,9 @@ using namespace llvm; MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText, MCSymbol *Begin) : Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false), - HasLayout(false), IsRegistered(false), IsText(IsText), - DummyFragment(this), Name(Name), Variant(V) { + HasLayout(false), IsRegistered(false), IsText(IsText), Name(Name), + Variant(V) { + DummyFragment.setParent(this); // The initial subsection number is 0. Create a fragment list. CurFragList = &Subsections.emplace_back(0u, FragList{}).second; } @@ -79,33 +80,6 @@ void MCSection::switchSubsection(unsigned Subsection) { StringRef MCSection::getVirtualSectionKind() const { return "virtual"; } void MCSection::addPendingLabel(MCSymbol *label, unsigned Subsection) { - PendingLabels.push_back(PendingLabel(label, Subsection)); -} - -void MCSection::flushPendingLabels(MCFragment *F, unsigned Subsection) { - // Set the fragment and fragment offset for all pending symbols in the - // specified Subsection, and remove those symbols from the pending list. - for (auto It = PendingLabels.begin(); It != PendingLabels.end(); ++It) { - PendingLabel& Label = *It; - if (Label.Subsection == Subsection) { - Label.Sym->setFragment(F); - assert(Label.Sym->getOffset() == 0); - PendingLabels.erase(It--); - } - } -} - -void MCSection::flushPendingLabels() { - // Make sure all remaining pending labels point to data fragments, by - // creating new empty data fragments for each Subsection with labels pending. - while (!PendingLabels.empty()) { - PendingLabel& Label = PendingLabels[0]; - switchSubsection(Label.Subsection); - MCFragment *F = new MCDataFragment(); - addFragment(*F); - F->setParent(this); - flushPendingLabels(F, Label.Subsection); - } } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) diff --git a/llvm/lib/MC/MCSymbol.cpp b/llvm/lib/MC/MCSymbol.cpp index 867a472377ca46..2a709f4aef80c3 100644 --- a/llvm/lib/MC/MCSymbol.cpp +++ b/llvm/lib/MC/MCSymbol.cpp @@ -22,7 +22,7 @@ using namespace llvm; // Only the address of this fragment is ever actually used. -static MCDummyFragment SentinelFragment(nullptr); +static MCDummyFragment SentinelFragment; // Sentinel value for the absolute pseudo fragment. MCFragment *MCSymbol::AbsolutePseudoFragment = &SentinelFragment; diff --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp index 8b59a6c3446f9d..4187de4d5eb8e1 100644 --- a/llvm/lib/MC/MCWasmStreamer.cpp +++ b/llvm/lib/MC/MCWasmStreamer.cpp @@ -49,7 +49,7 @@ void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { Symbol->setTLS(); } -void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F, +void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, uint64_t Offset) { auto *Symbol = cast(S); MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset); diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp index 5732b29b85d941..05445a3db10db4 100644 --- a/llvm/lib/MC/MCWinCOFFStreamer.cpp +++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp @@ -196,8 +196,9 @@ void MCWinCOFFStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) { getAssembler().registerSection(*SXData); SXData->ensureMinAlignment(Align(4)); - getContext().allocFragment(Symbol, SXData); - + auto *F = getContext().allocFragment(Symbol); + F->setParent(SXData); + SXData->addFragment(*F); getAssembler().registerSymbol(*Symbol); CSymbol->setIsSafeSEH(); @@ -212,9 +213,7 @@ void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) { getAssembler().registerSection(*Sec); Sec->ensureMinAlignment(Align(4)); - getContext().allocFragment(Symbol, - getCurrentSectionOnly()); - + insert(getContext().allocFragment(Symbol)); getAssembler().registerSymbol(*Symbol); } diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index dcbe5e98fa1db5..2e7fb789c98fd0 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -499,7 +499,8 @@ class TriggerVerifierErrorPass class RequireAllMachineFunctionPropertiesPass : public PassInfoMixin { public: - PreservedAnalyses run(MachineFunction &, MachineFunctionAnalysisManager &) { + PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &) { + MFPropsModifier _(*this, MF); return PreservedAnalyses::none(); } diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp index 3e0e2b2284d8fa..c7749f33d9af55 100644 --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -1382,6 +1382,45 @@ getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, return ValueDataArray; } +SmallVector +getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, + uint32_t MaxNumValueData, uint64_t &TotalC, + bool GetNoICPValue) { + // Four inline elements seem to work well in practice. With MaxNumValueData, + // this array won't grow very big anyway. + SmallVector ValueData; + MDNode *MD = mayHaveValueProfileOfKind(Inst, ValueKind); + if (!MD) + return ValueData; + const unsigned NOps = MD->getNumOperands(); + // Get total count + ConstantInt *TotalCInt = mdconst::dyn_extract(MD->getOperand(2)); + if (!TotalCInt) + return ValueData; + TotalC = TotalCInt->getZExtValue(); + + ValueData.reserve((NOps - 3) / 2); + for (unsigned I = 3; I < NOps; I += 2) { + if (ValueData.size() >= MaxNumValueData) + break; + ConstantInt *Value = mdconst::dyn_extract(MD->getOperand(I)); + ConstantInt *Count = + mdconst::dyn_extract(MD->getOperand(I + 1)); + if (!Value || !Count) { + ValueData.clear(); + return ValueData; + } + uint64_t CntValue = Count->getZExtValue(); + if (!GetNoICPValue && (CntValue == NOMORE_ICP_MAGICNUM)) + continue; + InstrProfValueData V; + V.Value = Value->getZExtValue(); + V.Count = CntValue; + ValueData.push_back(V); + } + return ValueData; +} + MDNode *getPGOFuncNameMetadata(const Function &F) { return F.getMetadata(getPGOFuncNameMetadataName()); } diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index afd7dccbeca9b3..655492f245027e 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -487,7 +487,7 @@ class ARMELFStreamer : public MCELFStreamer { LastEMSInfo = std::move(LastMappingSymbol->second); return; } - LastEMSInfo.reset(new ElfMappingSymbolInfo(SMLoc(), nullptr, 0)); + LastEMSInfo.reset(new ElfMappingSymbolInfo); } /// This function is the one used to emit instruction data into the ELF @@ -555,7 +555,7 @@ class ARMELFStreamer : public MCELFStreamer { if (!LastEMSInfo->hasInfo()) return; ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); - EmitMappingSymbol("$d", EMS->Loc, EMS->F, EMS->Offset); + emitMappingSymbol("$d", *EMS->F, EMS->Offset); EMS->resetInfo(); } @@ -625,17 +625,14 @@ class ARMELFStreamer : public MCELFStreamer { }; struct ElfMappingSymbolInfo { - explicit ElfMappingSymbolInfo(SMLoc Loc, MCFragment *F, uint64_t O) - : Loc(Loc), F(F), Offset(O), State(EMS_None) {} void resetInfo() { F = nullptr; Offset = 0; } bool hasInfo() { return F != nullptr; } - SMLoc Loc; - MCFragment *F; - uint64_t Offset; - ElfMappingSymbol State; + MCDataFragment *F = nullptr; + uint64_t Offset = 0; + ElfMappingSymbol State = EMS_None; }; void emitDataMappingSymbol() { @@ -648,8 +645,7 @@ class ARMELFStreamer : public MCELFStreamer { auto *DF = dyn_cast_or_null(getCurrentFragment()); if (!DF) return; - EMS->Loc = SMLoc(); - EMS->F = getCurrentFragment(); + EMS->F = DF; EMS->Offset = DF->getContents().size(); LastEMSInfo->State = EMS_Data; return; @@ -683,11 +679,10 @@ class ARMELFStreamer : public MCELFStreamer { Symbol->setBinding(ELF::STB_LOCAL); } - void EmitMappingSymbol(StringRef Name, SMLoc Loc, MCFragment *F, - uint64_t Offset) { + void emitMappingSymbol(StringRef Name, MCDataFragment &F, uint64_t Offset) { auto *Symbol = cast(getContext().getOrCreateSymbol( Name + "." + Twine(MappingSymbolCounter++))); - emitLabelAtPos(Symbol, Loc, F, Offset); + emitLabelAtPos(Symbol, SMLoc(), F, Offset); Symbol->setType(ELF::STT_NOTYPE); Symbol->setBinding(ELF::STB_LOCAL); } diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 68e78b31a28b13..00f58f9432e4d7 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -67,8 +67,8 @@ class X86MCInstLower { public: X86MCInstLower(const MachineFunction &MF, X86AsmPrinter &asmprinter); - std::optional LowerMachineOperand(const MachineInstr *MI, - const MachineOperand &MO) const; + MCOperand LowerMachineOperand(const MachineInstr *MI, + const MachineOperand &MO) const; void Lower(const MachineInstr *MI, MCInst &OutMI) const; MCSymbol *GetSymbolFromOperand(const MachineOperand &MO) const; @@ -326,9 +326,8 @@ static unsigned getRetOpcode(const X86Subtarget &Subtarget) { return Subtarget.is64Bit() ? X86::RET64 : X86::RET32; } -std::optional -X86MCInstLower::LowerMachineOperand(const MachineInstr *MI, - const MachineOperand &MO) const { +MCOperand X86MCInstLower::LowerMachineOperand(const MachineInstr *MI, + const MachineOperand &MO) const { switch (MO.getType()) { default: MI->print(errs()); @@ -336,7 +335,7 @@ X86MCInstLower::LowerMachineOperand(const MachineInstr *MI, case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) - return std::nullopt; + return MCOperand(); return MCOperand::createReg(MO.getReg()); case MachineOperand::MO_Immediate: return MCOperand::createImm(MO.getImm()); @@ -355,7 +354,7 @@ X86MCInstLower::LowerMachineOperand(const MachineInstr *MI, MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress())); case MachineOperand::MO_RegisterMask: // Ignore call clobbers. - return std::nullopt; + return MCOperand(); } } @@ -398,8 +397,8 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.setOpcode(MI->getOpcode()); for (const MachineOperand &MO : MI->operands()) - if (auto MaybeMCOp = LowerMachineOperand(MI, MO)) - OutMI.addOperand(*MaybeMCOp); + if (auto Op = LowerMachineOperand(MI, MO); Op.isValid()) + OutMI.addOperand(Op); bool In64BitMode = AsmPrinter.getSubtarget().is64Bit(); if (X86::optimizeInstFromVEX3ToVEX2(OutMI, MI->getDesc()) || @@ -867,8 +866,8 @@ void X86AsmPrinter::LowerFAULTING_OP(const MachineInstr &FaultingMI, for (const MachineOperand &MO : llvm::drop_begin(FaultingMI.operands(), OperandsBeginIdx)) - if (auto MaybeOperand = MCIL.LowerMachineOperand(&FaultingMI, MO)) - MI.addOperand(*MaybeOperand); + if (auto Op = MCIL.LowerMachineOperand(&FaultingMI, MO); Op.isValid()) + MI.addOperand(Op); OutStreamer->AddComment("on-fault: " + HandlerLabel->getName()); OutStreamer->emitInstruction(MI, getSubtargetInfo()); @@ -1139,9 +1138,10 @@ void X86AsmPrinter::LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, // emit nops appropriately sized to keep the sled the same size in every // situation. for (unsigned I = 0; I < MI.getNumOperands(); ++I) - if (auto Op = MCIL.LowerMachineOperand(&MI, MI.getOperand(I))) { - assert(Op->isReg() && "Only support arguments in registers"); - SrcRegs[I] = getX86SubSuperRegister(Op->getReg(), 64); + if (auto Op = MCIL.LowerMachineOperand(&MI, MI.getOperand(I)); + Op.isValid()) { + assert(Op.isReg() && "Only support arguments in registers"); + SrcRegs[I] = getX86SubSuperRegister(Op.getReg(), 64); assert(SrcRegs[I].isValid() && "Invalid operand"); if (SrcRegs[I] != DestRegs[I]) { UsedMask[I] = true; @@ -1237,10 +1237,11 @@ void X86AsmPrinter::LowerPATCHABLE_TYPED_EVENT_CALL(const MachineInstr &MI, // In case the arguments are already in the correct register, we emit nops // appropriately sized to keep the sled the same size in every situation. for (unsigned I = 0; I < MI.getNumOperands(); ++I) - if (auto Op = MCIL.LowerMachineOperand(&MI, MI.getOperand(I))) { + if (auto Op = MCIL.LowerMachineOperand(&MI, MI.getOperand(I)); + Op.isValid()) { // TODO: Is register only support adequate? - assert(Op->isReg() && "Only supports arguments in registers"); - SrcRegs[I] = getX86SubSuperRegister(Op->getReg(), 64); + assert(Op.isReg() && "Only supports arguments in registers"); + SrcRegs[I] = getX86SubSuperRegister(Op.getReg(), 64); assert(SrcRegs[I].isValid() && "Invalid operand"); if (SrcRegs[I] != DestRegs[I]) { UsedMask[I] = true; @@ -1354,8 +1355,8 @@ void X86AsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI, MCInst Ret; Ret.setOpcode(OpCode); for (auto &MO : drop_begin(MI.operands())) - if (auto MaybeOperand = MCIL.LowerMachineOperand(&MI, MO)) - Ret.addOperand(*MaybeOperand); + if (auto Op = MCIL.LowerMachineOperand(&MI, MO); Op.isValid()) + Ret.addOperand(Op); OutStreamer->emitInstruction(Ret, getSubtargetInfo()); emitX86Nops(*OutStreamer, 10, Subtarget); recordSled(CurSled, MI, SledKind::FUNCTION_EXIT, 2); @@ -1417,8 +1418,8 @@ void X86AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, // indeed a tail call. OutStreamer->AddComment("TAILCALL"); for (auto &MO : TCOperands) - if (auto MaybeOperand = MCIL.LowerMachineOperand(&MI, MO)) - TC.addOperand(*MaybeOperand); + if (auto Op = MCIL.LowerMachineOperand(&MI, MO); Op.isValid()) + TC.addOperand(Op); OutStreamer->emitInstruction(TC, getSubtargetInfo()); if (IsConditional) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 522c31f9e3e716..1ad637552eac69 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3933,6 +3933,52 @@ foldICmpUSubSatOrUAddSatWithConstant(ICmpInst::Predicate Pred, ConstantInt::get(Op1->getType(), EquivInt)); } +static Instruction * +foldICmpOfCmpIntrinsicWithConstant(ICmpInst::Predicate Pred, IntrinsicInst *I, + const APInt &C, + InstCombiner::BuilderTy &Builder) { + std::optional NewPredicate = std::nullopt; + switch (Pred) { + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_NE: + if (C.isZero()) + NewPredicate = Pred; + else if (C.isOne()) + NewPredicate = + Pred == ICmpInst::ICMP_EQ ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_ULE; + else if (C.isAllOnes()) + NewPredicate = + Pred == ICmpInst::ICMP_EQ ? ICmpInst::ICMP_ULT : ICmpInst::ICMP_UGE; + break; + + case ICmpInst::ICMP_SGT: + if (C.isAllOnes()) + NewPredicate = ICmpInst::ICMP_UGE; + else if (C.isZero()) + NewPredicate = ICmpInst::ICMP_UGT; + break; + + case ICmpInst::ICMP_SLT: + if (C.isZero()) + NewPredicate = ICmpInst::ICMP_ULT; + else if (C.isOne()) + NewPredicate = ICmpInst::ICMP_ULE; + break; + + default: + break; + } + + if (!NewPredicate) + return nullptr; + + if (I->getIntrinsicID() == Intrinsic::scmp) + NewPredicate = ICmpInst::getSignedPredicate(*NewPredicate); + Value *LHS = I->getOperand(0); + Value *RHS = I->getOperand(1); + return new ICmpInst(*NewPredicate, LHS, RHS); +} + /// Fold an icmp with LLVM intrinsic and constant operand: icmp Pred II, C. Instruction *InstCombinerImpl::foldICmpIntrinsicWithConstant(ICmpInst &Cmp, IntrinsicInst *II, @@ -3954,6 +4000,11 @@ Instruction *InstCombinerImpl::foldICmpIntrinsicWithConstant(ICmpInst &Cmp, if (Instruction *R = foldCtpopPow2Test(Cmp, II, C, Builder, Q)) return R; } break; + case Intrinsic::scmp: + case Intrinsic::ucmp: + if (auto *Folded = foldICmpOfCmpIntrinsicWithConstant(Pred, II, C, Builder)) + return Folded; + break; } if (Cmp.isEquality()) diff --git a/llvm/test/MC/MachO/pending-labels.s b/llvm/test/MC/MachO/pending-labels.s index a4644357ca4ee9..b210daace0e0a6 100644 --- a/llvm/test/MC/MachO/pending-labels.s +++ b/llvm/test/MC/MachO/pending-labels.s @@ -32,17 +32,17 @@ __data: .quad L8-. // CHECK: 0000000000000038 X86_64_RELOC_SUBTRACTOR _function1-__data // CHECK: 0000000000000038 X86_64_RELOC_UNSIGNED _function1 -// CHECK: 0000000000000030 X86_64_RELOC_SUBTRACTOR _function1-__data -// CHECK: 0000000000000030 X86_64_RELOC_UNSIGNED _function1 +// CHECK: 0000000000000030 X86_64_RELOC_SUBTRACTOR __text-__data +// CHECK: 0000000000000030 X86_64_RELOC_UNSIGNED __text // CHECK: 0000000000000028 X86_64_RELOC_SUBTRACTOR _function2-__data // CHECK: 0000000000000028 X86_64_RELOC_UNSIGNED _function2 // CHECK: 0000000000000020 X86_64_RELOC_SUBTRACTOR _function2-__data // CHECK: 0000000000000020 X86_64_RELOC_UNSIGNED _function2 -// CHECK: 0000000000000018 X86_64_RELOC_SUBTRACTOR _function2-__data -// CHECK: 0000000000000018 X86_64_RELOC_UNSIGNED _function2 -// CHECK: 0000000000000010 X86_64_RELOC_SUBTRACTOR _function1-__data -// CHECK: 0000000000000010 X86_64_RELOC_UNSIGNED _function1 -// CHECK: 0000000000000008 X86_64_RELOC_SUBTRACTOR _function2-__data -// CHECK: 0000000000000008 X86_64_RELOC_UNSIGNED _function2 -// CHECK: 0000000000000000 X86_64_RELOC_SUBTRACTOR _function1-__data -// CHECK: 0000000000000000 X86_64_RELOC_UNSIGNED _function1 +// CHECK: 0000000000000018 X86_64_RELOC_SUBTRACTOR __text_cold-__data +// CHECK: 0000000000000018 X86_64_RELOC_UNSIGNED __text_cold +// CHECK: 0000000000000010 X86_64_RELOC_SUBTRACTOR __text-__data +// CHECK: 0000000000000010 X86_64_RELOC_UNSIGNED __text +// CHECK: 0000000000000008 X86_64_RELOC_SUBTRACTOR __text_cold-__data +// CHECK: 0000000000000008 X86_64_RELOC_UNSIGNED __text_cold +// CHECK: 0000000000000000 X86_64_RELOC_SUBTRACTOR __text-__data +// CHECK: 0000000000000000 X86_64_RELOC_UNSIGNED __text diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll new file mode 100644 index 00000000000000..4f903a79afd5d4 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/scmp.ll @@ -0,0 +1,156 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i1 @scmp_eq_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_eq_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp eq i8 %1, 0 + ret i1 %2 +} + +define i1 @scmp_ne_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_ne_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp ne i8 %1, 0 + ret i1 %2 +} + +define i1 @scmp_eq_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_eq_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp eq i8 %1, 1 + ret i1 %2 +} + +define i1 @scmp_ne_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_ne_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp ne i8 %1, 1 + ret i1 %2 +} + +define i1 @scmp_eq_negative_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_eq_negative_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp eq i8 %1, -1 + ret i1 %2 +} + +define i1 @scmp_ne_negative_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_ne_negative_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp ne i8 %1, -1 + ret i1 %2 +} + +define i1 @scmp_sgt_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_sgt_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp sgt i8 %1, 0 + ret i1 %2 +} + +define i1 @scmp_sgt_neg_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_sgt_neg_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp sgt i8 %1, -1 + ret i1 %2 +} + +define i1 @scmp_sge_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_sge_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp sge i8 %1, 0 + ret i1 %2 +} + +define i1 @scmp_sge_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_sge_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp sge i8 %1, 1 + ret i1 %2 +} + +define i1 @scmp_slt_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_slt_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp slt i8 %1, 0 + ret i1 %2 +} + +define i1 @scmp_slt_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_slt_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp slt i8 %1, 1 + ret i1 %2 +} + +define i1 @scmp_sle_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_sle_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp sle i8 %1, 0 + ret i1 %2 +} + +define i1 @scmp_sle_neg_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @scmp_sle_neg_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.scmp(i32 %x, i32 %y) + %2 = icmp sle i8 %1, -1 + ret i1 %2 +} diff --git a/llvm/test/Transforms/InstCombine/ucmp.ll b/llvm/test/Transforms/InstCombine/ucmp.ll new file mode 100644 index 00000000000000..9ab67560c91173 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/ucmp.ll @@ -0,0 +1,156 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i1 @ucmp_eq_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_eq_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp eq i8 %1, 0 + ret i1 %2 +} + +define i1 @ucmp_ne_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_ne_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp ne i8 %1, 0 + ret i1 %2 +} + +define i1 @ucmp_eq_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_eq_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp eq i8 %1, 1 + ret i1 %2 +} + +define i1 @ucmp_ne_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_ne_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp ne i8 %1, 1 + ret i1 %2 +} + +define i1 @ucmp_eq_negative_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_eq_negative_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp eq i8 %1, -1 + ret i1 %2 +} + +define i1 @ucmp_ne_negative_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_ne_negative_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp ne i8 %1, -1 + ret i1 %2 +} + +define i1 @ucmp_sgt_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_sgt_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp sgt i8 %1, 0 + ret i1 %2 +} + +define i1 @ucmp_sgt_neg_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_sgt_neg_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp sgt i8 %1, -1 + ret i1 %2 +} + +define i1 @ucmp_sge_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_sge_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp sge i8 %1, 0 + ret i1 %2 +} + +define i1 @ucmp_sge_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_sge_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp sge i8 %1, 1 + ret i1 %2 +} + +define i1 @ucmp_slt_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_slt_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp slt i8 %1, 0 + ret i1 %2 +} + +define i1 @ucmp_slt_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_slt_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp slt i8 %1, 1 + ret i1 %2 +} + +define i1 @ucmp_sle_0(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_sle_0( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp sle i8 %1, 0 + ret i1 %2 +} + +define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @ucmp_sle_neg_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %1 = call i8 @llvm.ucmp(i32 %x, i32 %y) + %2 = icmp sle i8 %1, -1 + ret i1 %2 +} diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp index b52ab1ce6d2949..b08ae4cf64ab9f 100644 --- a/llvm/tools/dsymutil/MachOUtils.cpp +++ b/llvm/tools/dsymutil/MachOUtils.cpp @@ -381,7 +381,6 @@ bool generateDsymCompanion( auto &Writer = static_cast(MCAsm.getWriter()); // Layout but don't emit. - ObjectStreamer.flushPendingLabels(); MCAsmLayout Layout(MCAsm); MCAsm.layout(Layout); diff --git a/llvm/unittests/Target/SPIRV/SPIRVConvergenceRegionAnalysisTests.cpp b/llvm/unittests/Target/SPIRV/SPIRVConvergenceRegionAnalysisTests.cpp index e04fc85df4f93b..fc7c6e6ed762e1 100644 --- a/llvm/unittests/Target/SPIRV/SPIRVConvergenceRegionAnalysisTests.cpp +++ b/llvm/unittests/Target/SPIRV/SPIRVConvergenceRegionAnalysisTests.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/PassInstrumentation.h" #include "llvm/IR/Type.h" #include "llvm/IR/TypedPointerType.h" #include "llvm/Support/SourceMgr.h" diff --git a/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn index b44c5b67c50a9f..973c10d14766ef 100644 --- a/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn @@ -25,6 +25,7 @@ static_library("Expression") { "DWARFExpressionList.cpp", "DiagnosticManager.cpp", "Expression.cpp", + "ExpressionParser.cpp", "ExpressionTypeSystemHelper.cpp", "ExpressionVariable.cpp", "FunctionCaller.cpp",