mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-29 12:44:53 +01:00
Merge llvm-project release/17.x llvmorg-17.0.5-0-g98bfdac5ce82
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-17.0.5-0-g98bfdac5ce82. PR: 273753 MFC after: 1 month
This commit is contained in:
commit
b121cb0095
@ -69,7 +69,7 @@ def note_consteval_address_accessible : Note<
|
|||||||
"%select{pointer|reference}0 to a consteval declaration "
|
"%select{pointer|reference}0 to a consteval declaration "
|
||||||
"is not a constant expression">;
|
"is not a constant expression">;
|
||||||
def note_constexpr_uninitialized : Note<
|
def note_constexpr_uninitialized : Note<
|
||||||
"subobject %0 is not initialized">;
|
"subobject %select{of type |}0%1 is not initialized">;
|
||||||
def note_constexpr_uninitialized_base : Note<
|
def note_constexpr_uninitialized_base : Note<
|
||||||
"constructor of base class %0 is not called">;
|
"constructor of base class %0 is not called">;
|
||||||
def note_constexpr_static_local : Note<
|
def note_constexpr_static_local : Note<
|
||||||
|
@ -710,9 +710,13 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Saves the current floating-point pragma stack and clear it in this Sema.
|
||||||
class FpPragmaStackSaveRAII {
|
class FpPragmaStackSaveRAII {
|
||||||
public:
|
public:
|
||||||
FpPragmaStackSaveRAII(Sema &S) : S(S), SavedStack(S.FpPragmaStack) {}
|
FpPragmaStackSaveRAII(Sema &S)
|
||||||
|
: S(S), SavedStack(std::move(S.FpPragmaStack)) {
|
||||||
|
S.FpPragmaStack.Stack.clear();
|
||||||
|
}
|
||||||
~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); }
|
~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -722,7 +726,6 @@ public:
|
|||||||
|
|
||||||
void resetFPOptions(FPOptions FPO) {
|
void resetFPOptions(FPOptions FPO) {
|
||||||
CurFPFeatures = FPO;
|
CurFPFeatures = FPO;
|
||||||
FpPragmaStack.Stack.clear();
|
|
||||||
FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
|
FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2379,10 +2379,15 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
|
|||||||
const FieldDecl *SubobjectDecl,
|
const FieldDecl *SubobjectDecl,
|
||||||
CheckedTemporaries &CheckedTemps) {
|
CheckedTemporaries &CheckedTemps) {
|
||||||
if (!Value.hasValue()) {
|
if (!Value.hasValue()) {
|
||||||
assert(SubobjectDecl && "SubobjectDecl shall be non-null");
|
if (SubobjectDecl) {
|
||||||
Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) << SubobjectDecl;
|
Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized)
|
||||||
Info.Note(SubobjectDecl->getLocation(),
|
<< /*(name)*/ 1 << SubobjectDecl;
|
||||||
diag::note_constexpr_subobject_declared_here);
|
Info.Note(SubobjectDecl->getLocation(),
|
||||||
|
diag::note_constexpr_subobject_declared_here);
|
||||||
|
} else {
|
||||||
|
Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized)
|
||||||
|
<< /*of type*/ 0 << Type;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +382,8 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
|
|||||||
static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI,
|
static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI,
|
||||||
const FieldDecl *SubObjDecl) {
|
const FieldDecl *SubObjDecl) {
|
||||||
assert(SubObjDecl && "Subobject declaration does not exist");
|
assert(SubObjDecl && "Subobject declaration does not exist");
|
||||||
S.FFDiag(SI, diag::note_constexpr_uninitialized) << SubObjDecl;
|
S.FFDiag(SI, diag::note_constexpr_uninitialized)
|
||||||
|
<< /*(name)*/ 1 << SubObjDecl;
|
||||||
S.Note(SubObjDecl->getLocation(),
|
S.Note(SubObjDecl->getLocation(),
|
||||||
diag::note_constexpr_subobject_declared_here);
|
diag::note_constexpr_subobject_declared_here);
|
||||||
}
|
}
|
||||||
|
@ -1736,9 +1736,10 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E,
|
|||||||
QualType destType) {
|
QualType destType) {
|
||||||
assert(!destType->isVoidType() && "can't emit a void constant");
|
assert(!destType->isVoidType() && "can't emit a void constant");
|
||||||
|
|
||||||
if (llvm::Constant *C =
|
if (!destType->isReferenceType())
|
||||||
ConstExprEmitter(*this).Visit(const_cast<Expr *>(E), destType))
|
if (llvm::Constant *C =
|
||||||
return C;
|
ConstExprEmitter(*this).Visit(const_cast<Expr *>(E), destType))
|
||||||
|
return C;
|
||||||
|
|
||||||
Expr::EvalResult Result;
|
Expr::EvalResult Result;
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
const InputInfoList &Inputs,
|
const InputInfoList &Inputs,
|
||||||
const ArgList &Args,
|
const ArgList &Args,
|
||||||
const char *LinkingOutput) const {
|
const char *LinkingOutput) const {
|
||||||
|
const Driver &D = getToolChain().getDriver();
|
||||||
const bool IsPIE = getPIE(Args, getToolChain());
|
const bool IsPIE = getPIE(Args, getToolChain());
|
||||||
ArgStringList CmdArgs;
|
ArgStringList CmdArgs;
|
||||||
|
|
||||||
@ -152,8 +153,11 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
|
|
||||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
|
||||||
options::OPT_r)) {
|
options::OPT_r)) {
|
||||||
if (getToolChain().ShouldLinkCXXStdlib(Args))
|
if (D.CCCIsCXX()) {
|
||||||
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
|
if (getToolChain().ShouldLinkCXXStdlib(Args))
|
||||||
|
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
|
||||||
|
CmdArgs.push_back("-lm");
|
||||||
|
}
|
||||||
if (Args.hasArg(options::OPT_fstack_protector) ||
|
if (Args.hasArg(options::OPT_fstack_protector) ||
|
||||||
Args.hasArg(options::OPT_fstack_protector_strong) ||
|
Args.hasArg(options::OPT_fstack_protector_strong) ||
|
||||||
Args.hasArg(options::OPT_fstack_protector_all)) {
|
Args.hasArg(options::OPT_fstack_protector_all)) {
|
||||||
@ -172,7 +176,6 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
CmdArgs.push_back("-lc");
|
CmdArgs.push_back("-lc");
|
||||||
if (!Args.hasArg(options::OPT_shared)) {
|
if (!Args.hasArg(options::OPT_shared)) {
|
||||||
CmdArgs.push_back("-lgcc");
|
CmdArgs.push_back("-lgcc");
|
||||||
CmdArgs.push_back("-lm");
|
|
||||||
}
|
}
|
||||||
const SanitizerArgs &SA = getToolChain().getSanitizerArgs(Args);
|
const SanitizerArgs &SA = getToolChain().getSanitizerArgs(Args);
|
||||||
if (NeedsSanitizerDeps) {
|
if (NeedsSanitizerDeps) {
|
||||||
|
@ -3178,6 +3178,12 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
|
|||||||
!Previous->isOneOf(tok::kw_return, tok::kw_co_return)) {
|
!Previous->isOneOf(tok::kw_return, tok::kw_co_return)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (Previous->is(tok::r_paren) && Previous->is(TT_TypeDeclarationParen)) {
|
||||||
|
assert(Previous->MatchingParen);
|
||||||
|
assert(Previous->MatchingParen->is(tok::l_paren));
|
||||||
|
assert(Previous->MatchingParen->is(TT_TypeDeclarationParen));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!Previous->isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser))
|
if (!Previous->isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser))
|
||||||
return false;
|
return false;
|
||||||
Next = skipOperatorName(Next);
|
Next = skipOperatorName(Next);
|
||||||
|
@ -965,7 +965,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
|
|||||||
AlignTokens(
|
AlignTokens(
|
||||||
Style,
|
Style,
|
||||||
[](Change const &C) {
|
[](Change const &C) {
|
||||||
if (C.Tok->isOneOf(TT_FunctionDeclarationName, TT_FunctionTypeLParen))
|
if (C.Tok->is(TT_FunctionDeclarationName))
|
||||||
return true;
|
return true;
|
||||||
if (C.Tok->isNot(TT_StartOfName))
|
if (C.Tok->isNot(TT_StartOfName))
|
||||||
return false;
|
return false;
|
||||||
|
@ -3998,8 +3998,15 @@ void Parser::ParseDeclarationSpecifiers(
|
|||||||
case tok::kw_thread_local:
|
case tok::kw_thread_local:
|
||||||
if (getLangOpts().C2x)
|
if (getLangOpts().C2x)
|
||||||
Diag(Tok, diag::warn_c2x_compat_keyword) << Tok.getName();
|
Diag(Tok, diag::warn_c2x_compat_keyword) << Tok.getName();
|
||||||
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc,
|
// We map thread_local to _Thread_local in C23 mode so it retains the C
|
||||||
PrevSpec, DiagID);
|
// semantics rather than getting the C++ semantics.
|
||||||
|
// FIXME: diagnostics will show _Thread_local when the user wrote
|
||||||
|
// thread_local in source in C23 mode; we need some general way to
|
||||||
|
// identify which way the user spelled the keyword in source.
|
||||||
|
isInvalid = DS.SetStorageClassSpecThread(
|
||||||
|
getLangOpts().C2x ? DeclSpec::TSCS__Thread_local
|
||||||
|
: DeclSpec::TSCS_thread_local,
|
||||||
|
Loc, PrevSpec, DiagID);
|
||||||
isStorageClass = true;
|
isStorageClass = true;
|
||||||
break;
|
break;
|
||||||
case tok::kw__Thread_local:
|
case tok::kw__Thread_local:
|
||||||
|
@ -40,15 +40,11 @@
|
|||||||
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
|
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
|
||||||
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is
|
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is
|
||||||
// defined to XXYYZZ.
|
// defined to XXYYZZ.
|
||||||
# define _LIBCPP_VERSION 170003
|
# define _LIBCPP_VERSION 170005
|
||||||
|
|
||||||
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
|
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
|
||||||
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
|
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
|
||||||
|
|
||||||
// Valid C++ identifier that revs with every libc++ version. This can be used to
|
|
||||||
// generate identifiers that must be unique for every released libc++ version.
|
|
||||||
# define _LIBCPP_VERSIONED_IDENTIFIER _LIBCPP_CONCAT(v, _LIBCPP_VERSION)
|
|
||||||
|
|
||||||
# if __STDC_HOSTED__ == 0
|
# if __STDC_HOSTED__ == 0
|
||||||
# define _LIBCPP_FREESTANDING
|
# define _LIBCPP_FREESTANDING
|
||||||
# endif
|
# endif
|
||||||
@ -754,22 +750,54 @@ typedef __char32_t char32_t;
|
|||||||
# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION _LIBCPP_ALWAYS_INLINE
|
# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION _LIBCPP_ALWAYS_INLINE
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# if _LIBCPP_ENABLE_HARDENED_MODE
|
||||||
|
# define _LIBCPP_HARDENING_SIG h
|
||||||
|
# elif _LIBCPP_ENABLE_ASSERTIONS
|
||||||
|
# define _LIBCPP_HARDENING_SIG s
|
||||||
|
# elif _LIBCPP_ENABLE_DEBUG_MODE
|
||||||
|
# define _LIBCPP_HARDENING_SIG d
|
||||||
|
# else
|
||||||
|
# define _LIBCPP_HARDENING_SIG u // for unchecked
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
# define _LIBCPP_EXCEPTIONS_SIG n
|
||||||
|
# else
|
||||||
|
# define _LIBCPP_EXCEPTIONS_SIG e
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define _LIBCPP_ODR_SIGNATURE \
|
||||||
|
_LIBCPP_CONCAT(_LIBCPP_CONCAT(_LIBCPP_HARDENING_SIG, _LIBCPP_EXCEPTIONS_SIG), _LIBCPP_VERSION)
|
||||||
|
|
||||||
// This macro marks a symbol as being hidden from libc++'s ABI. This is achieved
|
// This macro marks a symbol as being hidden from libc++'s ABI. This is achieved
|
||||||
// on two levels:
|
// on two levels:
|
||||||
// 1. The symbol is given hidden visibility, which ensures that users won't start exporting
|
// 1. The symbol is given hidden visibility, which ensures that users won't start exporting
|
||||||
// symbols from their dynamic library by means of using the libc++ headers. This ensures
|
// symbols from their dynamic library by means of using the libc++ headers. This ensures
|
||||||
// that those symbols stay private to the dynamic library in which it is defined.
|
// that those symbols stay private to the dynamic library in which it is defined.
|
||||||
//
|
//
|
||||||
// 2. The symbol is given an ABI tag that changes with each version of libc++. This ensures
|
// 2. The symbol is given an ABI tag that encodes the ODR-relevant properties of the library.
|
||||||
// that no ODR violation can arise from mixing two TUs compiled with different versions
|
// This ensures that no ODR violation can arise from mixing two TUs compiled with different
|
||||||
// of libc++ where we would have changed the definition of a symbol. If the symbols shared
|
// versions or configurations of libc++ (such as exceptions vs no-exceptions). Indeed, if the
|
||||||
// the same name, the ODR would require that their definitions be token-by-token equivalent,
|
// program contains two definitions of a function, the ODR requires them to be token-by-token
|
||||||
// which basically prevents us from being able to make any change to any function in our
|
// equivalent, and the linker is allowed to pick either definition and discard the other one.
|
||||||
// headers. Using this ABI tag ensures that the symbol name is "bumped" artificially at
|
//
|
||||||
// each release, which lets us change the definition of these symbols at our leisure.
|
// For example, if a program contains a copy of `vector::at()` compiled with exceptions enabled
|
||||||
// Note that historically, this has been achieved in various ways, including force-inlining
|
// *and* a copy of `vector::at()` compiled with exceptions disabled (by means of having two TUs
|
||||||
// all functions or giving internal linkage to all functions. Both these (previous) solutions
|
// compiled with different settings), the two definitions are both visible by the linker and they
|
||||||
// suffer from drawbacks that lead notably to code bloat.
|
// have the same name, but they have a meaningfully different implementation (one throws an exception
|
||||||
|
// and the other aborts the program). This violates the ODR and makes the program ill-formed, and in
|
||||||
|
// practice what will happen is that the linker will pick one of the definitions at random and will
|
||||||
|
// discard the other one. This can quite clearly lead to incorrect program behavior.
|
||||||
|
//
|
||||||
|
// A similar reasoning holds for many other properties that are ODR-affecting. Essentially any
|
||||||
|
// property that causes the code of a function to differ from the code in another configuration
|
||||||
|
// can be considered ODR-affecting. In practice, we don't encode all such properties in the ABI
|
||||||
|
// tag, but we encode the ones that we think are most important: library version, exceptions, and
|
||||||
|
// hardening mode.
|
||||||
|
//
|
||||||
|
// Note that historically, solving this problem has been achieved in various ways, including
|
||||||
|
// force-inlining all functions or giving internal linkage to all functions. Both these previous
|
||||||
|
// solutions suffer from drawbacks that lead notably to code bloat.
|
||||||
//
|
//
|
||||||
// Note that we use _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION to ensure that we don't depend
|
// Note that we use _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION to ensure that we don't depend
|
||||||
// on _LIBCPP_HIDE_FROM_ABI methods of classes explicitly instantiated in the dynamic library.
|
// on _LIBCPP_HIDE_FROM_ABI methods of classes explicitly instantiated in the dynamic library.
|
||||||
@ -789,7 +817,7 @@ typedef __char32_t char32_t;
|
|||||||
# ifndef _LIBCPP_NO_ABI_TAG
|
# ifndef _LIBCPP_NO_ABI_TAG
|
||||||
# define _LIBCPP_HIDE_FROM_ABI \
|
# define _LIBCPP_HIDE_FROM_ABI \
|
||||||
_LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION \
|
_LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION \
|
||||||
__attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_VERSIONED_IDENTIFIER))))
|
__attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_ODR_SIGNATURE))))
|
||||||
# else
|
# else
|
||||||
# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
|
# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
|
||||||
# endif
|
# endif
|
||||||
|
@ -119,9 +119,7 @@ public:
|
|||||||
_LIBCPP_HIDE_FROM_ABI constexpr expected()
|
_LIBCPP_HIDE_FROM_ABI constexpr expected()
|
||||||
noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
|
noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
|
||||||
requires is_default_constructible_v<_Tp>
|
requires is_default_constructible_v<_Tp>
|
||||||
: __has_val_(true) {
|
: __union_(std::in_place), __has_val_(true) {}
|
||||||
std::construct_at(std::addressof(__union_.__val_));
|
|
||||||
}
|
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
|
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
|
||||||
|
|
||||||
@ -136,14 +134,7 @@ public:
|
|||||||
noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
|
noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
|
||||||
requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
|
requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
|
||||||
!(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
|
!(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
|
||||||
: __has_val_(__other.__has_val_) {
|
: __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) { }
|
||||||
if (__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_);
|
|
||||||
} else {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
|
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
|
||||||
requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
|
requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
|
||||||
@ -154,13 +145,7 @@ public:
|
|||||||
noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
|
noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
|
||||||
requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
|
requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
|
||||||
!(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
|
!(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
|
||||||
: __has_val_(__other.__has_val_) {
|
: __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) { }
|
||||||
if (__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_));
|
|
||||||
} else {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
|
template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
|
||||||
@ -198,36 +183,21 @@ public:
|
|||||||
expected(const expected<_Up, _OtherErr>& __other)
|
expected(const expected<_Up, _OtherErr>& __other)
|
||||||
noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
|
noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
|
||||||
is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||||
: __has_val_(__other.__has_val_) {
|
: __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {}
|
||||||
if (__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_);
|
|
||||||
} else {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Up, class _OtherErr>
|
template <class _Up, class _OtherErr>
|
||||||
requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
|
requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
|
||||||
expected(expected<_Up, _OtherErr>&& __other)
|
expected(expected<_Up, _OtherErr>&& __other)
|
||||||
noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||||
: __has_val_(__other.__has_val_) {
|
: __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {}
|
||||||
if (__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_));
|
|
||||||
} else {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Up = _Tp>
|
template <class _Up = _Tp>
|
||||||
requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
|
requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
|
||||||
!__is_std_unexpected<remove_cvref_t<_Up>>::value && is_constructible_v<_Tp, _Up>)
|
!__is_std_unexpected<remove_cvref_t<_Up>>::value && is_constructible_v<_Tp, _Up>)
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
|
||||||
expected(_Up&& __u)
|
expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
|
||||||
noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
|
: __union_(std::in_place, std::forward<_Up>(__u)), __has_val_(true) {}
|
||||||
: __has_val_(true) {
|
|
||||||
std::construct_at(std::addressof(__union_.__val_), std::forward<_Up>(__u));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class _OtherErr>
|
template <class _OtherErr>
|
||||||
@ -235,52 +205,40 @@ public:
|
|||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
||||||
expected(const unexpected<_OtherErr>& __unex)
|
expected(const unexpected<_OtherErr>& __unex)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, __unex.error()), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __unex.error());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _OtherErr>
|
template <class _OtherErr>
|
||||||
requires is_constructible_v<_Err, _OtherErr>
|
requires is_constructible_v<_Err, _OtherErr>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
||||||
expected(unexpected<_OtherErr>&& __unex)
|
expected(unexpected<_OtherErr>&& __unex)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... _Args>
|
template <class... _Args>
|
||||||
requires is_constructible_v<_Tp, _Args...>
|
requires is_constructible_v<_Tp, _Args...>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
|
||||||
noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
|
||||||
: __has_val_(true) {
|
: __union_(std::in_place, std::forward<_Args>(__args)...), __has_val_(true) {}
|
||||||
std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Up, class... _Args>
|
template <class _Up, class... _Args>
|
||||||
requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
|
requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit
|
||||||
expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
|
expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
|
||||||
noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
|
||||||
: __has_val_(true) {
|
: __union_(std::in_place, __il, std::forward<_Args>(__args)...), __has_val_(true) {}
|
||||||
std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... _Args>
|
template <class... _Args>
|
||||||
requires is_constructible_v<_Err, _Args...>
|
requires is_constructible_v<_Err, _Args...>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Up, class... _Args>
|
template <class _Up, class... _Args>
|
||||||
requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
|
requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit
|
||||||
expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
|
expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
// [expected.object.dtor], destructor
|
// [expected.object.dtor], destructor
|
||||||
|
|
||||||
@ -439,9 +397,10 @@ public:
|
|||||||
std::destroy_at(std::addressof(__union_.__val_));
|
std::destroy_at(std::addressof(__union_.__val_));
|
||||||
} else {
|
} else {
|
||||||
std::destroy_at(std::addressof(__union_.__unex_));
|
std::destroy_at(std::addressof(__union_.__unex_));
|
||||||
__has_val_ = true;
|
|
||||||
}
|
}
|
||||||
return *std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
|
std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
|
||||||
|
__has_val_ = true;
|
||||||
|
return __union_.__val_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Up, class... _Args>
|
template <class _Up, class... _Args>
|
||||||
@ -451,9 +410,10 @@ public:
|
|||||||
std::destroy_at(std::addressof(__union_.__val_));
|
std::destroy_at(std::addressof(__union_.__val_));
|
||||||
} else {
|
} else {
|
||||||
std::destroy_at(std::addressof(__union_.__unex_));
|
std::destroy_at(std::addressof(__union_.__unex_));
|
||||||
__has_val_ = true;
|
|
||||||
}
|
}
|
||||||
return *std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
|
std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
|
||||||
|
__has_val_ = true;
|
||||||
|
return __union_.__val_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -892,11 +852,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct __empty_t {};
|
|
||||||
|
|
||||||
template <class _ValueType, class _ErrorType>
|
template <class _ValueType, class _ErrorType>
|
||||||
union __union_t {
|
union __union_t {
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() {}
|
template <class... _Args>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
|
||||||
|
: __val_(std::forward<_Args>(__args)...) {}
|
||||||
|
|
||||||
|
template <class... _Args>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
||||||
|
: __unex_(std::forward<_Args>(__args)...) {}
|
||||||
|
|
||||||
template <class _Func, class... _Args>
|
template <class _Func, class... _Args>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
||||||
@ -908,6 +872,14 @@ private:
|
|||||||
std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
||||||
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
||||||
|
|
||||||
|
template <class _Union>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
|
||||||
|
if (__has_val)
|
||||||
|
std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_);
|
||||||
|
else
|
||||||
|
std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||||
requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
|
requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
|
||||||
= default;
|
= default;
|
||||||
@ -926,7 +898,16 @@ private:
|
|||||||
template <class _ValueType, class _ErrorType>
|
template <class _ValueType, class _ErrorType>
|
||||||
requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>)
|
requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>)
|
||||||
union __union_t<_ValueType, _ErrorType> {
|
union __union_t<_ValueType, _ErrorType> {
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
|
||||||
|
|
||||||
|
template <class... _Args>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
|
||||||
|
: __val_(std::forward<_Args>(__args)...) {}
|
||||||
|
|
||||||
|
template <class... _Args>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
||||||
|
: __unex_(std::forward<_Args>(__args)...) {}
|
||||||
|
|
||||||
template <class _Func, class... _Args>
|
template <class _Func, class... _Args>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
||||||
@ -938,6 +919,14 @@ private:
|
|||||||
std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
||||||
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
||||||
|
|
||||||
|
template <class _Union>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
|
||||||
|
if (__has_val)
|
||||||
|
std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_);
|
||||||
|
else
|
||||||
|
std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||||
requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
|
requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
|
||||||
= default;
|
= default;
|
||||||
@ -947,7 +936,6 @@ private:
|
|||||||
requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>)
|
requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
_LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
|
|
||||||
_LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_;
|
_LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_;
|
||||||
_LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
|
_LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
|
||||||
};
|
};
|
||||||
@ -995,11 +983,7 @@ public:
|
|||||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
|
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
|
||||||
noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
|
noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
|
||||||
requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
|
requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
|
||||||
: __has_val_(__rhs.__has_val_) {
|
: __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {}
|
||||||
if (!__rhs.__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
|
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
|
||||||
requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
|
requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
|
||||||
@ -1008,51 +992,35 @@ public:
|
|||||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
|
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
|
||||||
noexcept(is_nothrow_move_constructible_v<_Err>)
|
noexcept(is_nothrow_move_constructible_v<_Err>)
|
||||||
requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
|
requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
|
||||||
: __has_val_(__rhs.__has_val_) {
|
: __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {}
|
||||||
if (!__rhs.__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Up, class _OtherErr>
|
template <class _Up, class _OtherErr>
|
||||||
requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
|
requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
||||||
expected(const expected<_Up, _OtherErr>& __rhs)
|
expected(const expected<_Up, _OtherErr>& __rhs)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||||
: __has_val_(__rhs.__has_val_) {
|
: __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {}
|
||||||
if (!__rhs.__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Up, class _OtherErr>
|
template <class _Up, class _OtherErr>
|
||||||
requires __can_convert<_Up, _OtherErr, _OtherErr>::value
|
requires __can_convert<_Up, _OtherErr, _OtherErr>::value
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
||||||
expected(expected<_Up, _OtherErr>&& __rhs)
|
expected(expected<_Up, _OtherErr>&& __rhs)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||||
: __has_val_(__rhs.__has_val_) {
|
: __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {}
|
||||||
if (!__rhs.__has_val_) {
|
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _OtherErr>
|
template <class _OtherErr>
|
||||||
requires is_constructible_v<_Err, const _OtherErr&>
|
requires is_constructible_v<_Err, const _OtherErr&>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
||||||
expected(const unexpected<_OtherErr>& __unex)
|
expected(const unexpected<_OtherErr>& __unex)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, __unex.error()), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __unex.error());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _OtherErr>
|
template <class _OtherErr>
|
||||||
requires is_constructible_v<_Err, _OtherErr>
|
requires is_constructible_v<_Err, _OtherErr>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
||||||
expected(unexpected<_OtherErr>&& __unex)
|
expected(unexpected<_OtherErr>&& __unex)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
|
|
||||||
}
|
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {}
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {}
|
||||||
|
|
||||||
@ -1060,17 +1028,13 @@ public:
|
|||||||
requires is_constructible_v<_Err, _Args...>
|
requires is_constructible_v<_Err, _Args...>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Up, class... _Args>
|
template <class _Up, class... _Args>
|
||||||
requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
|
requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
|
||||||
noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
|
noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
|
||||||
: __has_val_(false) {
|
: __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {}
|
||||||
std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class _Func>
|
template <class _Func>
|
||||||
@ -1504,11 +1468,23 @@ private:
|
|||||||
union __union_t {
|
union __union_t {
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
||||||
|
|
||||||
|
template <class... _Args>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
||||||
|
: __unex_(std::forward<_Args>(__args)...) {}
|
||||||
|
|
||||||
template <class _Func, class... _Args>
|
template <class _Func, class... _Args>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
||||||
__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
||||||
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
||||||
|
|
||||||
|
template <class _Union>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
|
||||||
|
if (__has_val)
|
||||||
|
std::construct_at(std::addressof(__empty_));
|
||||||
|
else
|
||||||
|
std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||||
requires(is_trivially_destructible_v<_ErrorType>)
|
requires(is_trivially_destructible_v<_ErrorType>)
|
||||||
= default;
|
= default;
|
||||||
@ -1529,11 +1505,23 @@ private:
|
|||||||
union __union_t<_ErrorType> {
|
union __union_t<_ErrorType> {
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
||||||
|
|
||||||
|
template <class... _Args>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
|
||||||
|
: __unex_(std::forward<_Args>(__args)...) {}
|
||||||
|
|
||||||
template <class _Func, class... _Args>
|
template <class _Func, class... _Args>
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
|
||||||
__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
|
||||||
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
|
||||||
|
|
||||||
|
template <class _Union>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
|
||||||
|
if (__has_val)
|
||||||
|
std::construct_at(std::addressof(__empty_));
|
||||||
|
else
|
||||||
|
std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
|
||||||
|
}
|
||||||
|
|
||||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||||
requires(is_trivially_destructible_v<_ErrorType>)
|
requires(is_trivially_destructible_v<_ErrorType>)
|
||||||
= default;
|
= default;
|
||||||
|
@ -485,13 +485,7 @@ BranchFolder::MergePotentialsElt::operator<(const MergePotentialsElt &o) const {
|
|||||||
return true;
|
return true;
|
||||||
if (getBlock()->getNumber() > o.getBlock()->getNumber())
|
if (getBlock()->getNumber() > o.getBlock()->getNumber())
|
||||||
return false;
|
return false;
|
||||||
// _GLIBCXX_DEBUG checks strict weak ordering, which involves comparing
|
|
||||||
// an object with itself.
|
|
||||||
#ifndef _GLIBCXX_DEBUG
|
|
||||||
llvm_unreachable("Predecessor appears twice");
|
|
||||||
#else
|
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CountTerminators - Count the number of terminators in the given
|
/// CountTerminators - Count the number of terminators in the given
|
||||||
|
@ -1000,6 +1000,7 @@ private:
|
|||||||
SDValue WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N);
|
SDValue WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N);
|
||||||
SDValue WidenVecOp_INSERT_SUBVECTOR(SDNode *N);
|
SDValue WidenVecOp_INSERT_SUBVECTOR(SDNode *N);
|
||||||
SDValue WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N);
|
SDValue WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N);
|
||||||
|
SDValue WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N);
|
||||||
SDValue WidenVecOp_STORE(SDNode* N);
|
SDValue WidenVecOp_STORE(SDNode* N);
|
||||||
SDValue WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo);
|
SDValue WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo);
|
||||||
SDValue WidenVecOp_VP_STRIDED_STORE(SDNode *N, unsigned OpNo);
|
SDValue WidenVecOp_VP_STRIDED_STORE(SDNode *N, unsigned OpNo);
|
||||||
|
@ -5946,6 +5946,11 @@ bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
|
|||||||
case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
|
case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
|
||||||
Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
|
Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
|
||||||
break;
|
break;
|
||||||
|
case ISD::ANY_EXTEND_VECTOR_INREG:
|
||||||
|
case ISD::SIGN_EXTEND_VECTOR_INREG:
|
||||||
|
case ISD::ZERO_EXTEND_VECTOR_INREG:
|
||||||
|
Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
|
||||||
|
break;
|
||||||
case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
|
case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
|
||||||
case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
|
case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
|
||||||
case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
|
case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
|
||||||
@ -6338,6 +6343,11 @@ SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
|
|||||||
N->getValueType(0), InOp, N->getOperand(1));
|
N->getValueType(0), InOp, N->getOperand(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
|
||||||
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
||||||
|
return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), InOp);
|
||||||
|
}
|
||||||
|
|
||||||
SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
|
SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
|
||||||
// We have to widen the value, but we want only to store the original
|
// We have to widen the value, but we want only to store the original
|
||||||
// vector type.
|
// vector type.
|
||||||
|
@ -4764,7 +4764,7 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI,
|
|||||||
Offset = Remainder;
|
Offset = Remainder;
|
||||||
else {
|
else {
|
||||||
NewOffset = NewOffset < 0 ? MinOff : MaxOff;
|
NewOffset = NewOffset < 0 ? MinOff : MaxOff;
|
||||||
Offset = Offset - NewOffset * Scale + Remainder;
|
Offset = Offset - NewOffset * Scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EmittableOffset)
|
if (EmittableOffset)
|
||||||
|
@ -212,6 +212,30 @@ bool AArch64TTIImpl::areInlineCompatible(const Function *Caller,
|
|||||||
return (CallerBits & CalleeBits) == CalleeBits;
|
return (CallerBits & CalleeBits) == CalleeBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AArch64TTIImpl::areTypesABICompatible(
|
||||||
|
const Function *Caller, const Function *Callee,
|
||||||
|
const ArrayRef<Type *> &Types) const {
|
||||||
|
if (!BaseT::areTypesABICompatible(Caller, Callee, Types))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We need to ensure that argument promotion does not attempt to promote
|
||||||
|
// pointers to fixed-length vector types larger than 128 bits like
|
||||||
|
// <8 x float> (and pointers to aggregate types which have such fixed-length
|
||||||
|
// vector type members) into the values of the pointees. Such vector types
|
||||||
|
// are used for SVE VLS but there is no ABI for SVE VLS arguments and the
|
||||||
|
// backend cannot lower such value arguments. The 128-bit fixed-length SVE
|
||||||
|
// types can be safely treated as 128-bit NEON types and they cannot be
|
||||||
|
// distinguished in IR.
|
||||||
|
if (ST->useSVEForFixedLengthVectors() && llvm::any_of(Types, [](Type *Ty) {
|
||||||
|
auto FVTy = dyn_cast<FixedVectorType>(Ty);
|
||||||
|
return FVTy &&
|
||||||
|
FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
|
||||||
|
}))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool AArch64TTIImpl::shouldMaximizeVectorBandwidth(
|
bool AArch64TTIImpl::shouldMaximizeVectorBandwidth(
|
||||||
TargetTransformInfo::RegisterKind K) const {
|
TargetTransformInfo::RegisterKind K) const {
|
||||||
assert(K != TargetTransformInfo::RGK_Scalar);
|
assert(K != TargetTransformInfo::RGK_Scalar);
|
||||||
|
@ -77,6 +77,9 @@ public:
|
|||||||
bool areInlineCompatible(const Function *Caller,
|
bool areInlineCompatible(const Function *Caller,
|
||||||
const Function *Callee) const;
|
const Function *Callee) const;
|
||||||
|
|
||||||
|
bool areTypesABICompatible(const Function *Caller, const Function *Callee,
|
||||||
|
const ArrayRef<Type *> &Types) const;
|
||||||
|
|
||||||
/// \name Scalar TTI Implementations
|
/// \name Scalar TTI Implementations
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
@ -829,9 +829,9 @@ bool AArch64CallLowering::doCallerAndCalleePassArgsTheSameWay(
|
|||||||
|
|
||||||
bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable(
|
bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable(
|
||||||
CallLoweringInfo &Info, MachineFunction &MF,
|
CallLoweringInfo &Info, MachineFunction &MF,
|
||||||
SmallVectorImpl<ArgInfo> &OutArgs) const {
|
SmallVectorImpl<ArgInfo> &OrigOutArgs) const {
|
||||||
// If there are no outgoing arguments, then we are done.
|
// If there are no outgoing arguments, then we are done.
|
||||||
if (OutArgs.empty())
|
if (OrigOutArgs.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const Function &CallerF = MF.getFunction();
|
const Function &CallerF = MF.getFunction();
|
||||||
@ -851,6 +851,9 @@ bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable(
|
|||||||
|
|
||||||
AArch64OutgoingValueAssigner CalleeAssigner(AssignFnFixed, AssignFnVarArg,
|
AArch64OutgoingValueAssigner CalleeAssigner(AssignFnFixed, AssignFnVarArg,
|
||||||
Subtarget, /*IsReturn*/ false);
|
Subtarget, /*IsReturn*/ false);
|
||||||
|
// determineAssignments() may modify argument flags, so make a copy.
|
||||||
|
SmallVector<ArgInfo, 8> OutArgs;
|
||||||
|
append_range(OutArgs, OrigOutArgs);
|
||||||
if (!determineAssignments(CalleeAssigner, OutArgs, OutInfo)) {
|
if (!determineAssignments(CalleeAssigner, OutArgs, OutInfo)) {
|
||||||
LLVM_DEBUG(dbgs() << "... Could not analyze call operands.\n");
|
LLVM_DEBUG(dbgs() << "... Could not analyze call operands.\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -36,9 +36,11 @@ bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
|
|||||||
FunctionPass *createLoongArchExpandAtomicPseudoPass();
|
FunctionPass *createLoongArchExpandAtomicPseudoPass();
|
||||||
FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
|
FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
|
||||||
FunctionPass *createLoongArchPreRAExpandPseudoPass();
|
FunctionPass *createLoongArchPreRAExpandPseudoPass();
|
||||||
|
FunctionPass *createLoongArchExpandPseudoPass();
|
||||||
void initializeLoongArchDAGToDAGISelPass(PassRegistry &);
|
void initializeLoongArchDAGToDAGISelPass(PassRegistry &);
|
||||||
void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);
|
void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);
|
||||||
void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
|
void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
|
||||||
|
void initializeLoongArchExpandPseudoPass(PassRegistry &);
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H
|
#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H
|
||||||
|
@ -29,6 +29,8 @@ using namespace llvm;
|
|||||||
|
|
||||||
#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
|
#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
|
||||||
"LoongArch Pre-RA pseudo instruction expansion pass"
|
"LoongArch Pre-RA pseudo instruction expansion pass"
|
||||||
|
#define LOONGARCH_EXPAND_PSEUDO_NAME \
|
||||||
|
"LoongArch pseudo instruction expansion pass"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -513,15 +515,134 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LoongArchExpandPseudo : public MachineFunctionPass {
|
||||||
|
public:
|
||||||
|
const LoongArchInstrInfo *TII;
|
||||||
|
static char ID;
|
||||||
|
|
||||||
|
LoongArchExpandPseudo() : MachineFunctionPass(ID) {
|
||||||
|
initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
||||||
|
|
||||||
|
StringRef getPassName() const override {
|
||||||
|
return LOONGARCH_EXPAND_PSEUDO_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool expandMBB(MachineBasicBlock &MBB);
|
||||||
|
bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||||
|
MachineBasicBlock::iterator &NextMBBI);
|
||||||
|
bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||||
|
MachineBasicBlock::iterator &NextMBBI);
|
||||||
|
};
|
||||||
|
|
||||||
|
char LoongArchExpandPseudo::ID = 0;
|
||||||
|
|
||||||
|
bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
|
||||||
|
TII =
|
||||||
|
static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
|
||||||
|
|
||||||
|
bool Modified = false;
|
||||||
|
for (auto &MBB : MF)
|
||||||
|
Modified |= expandMBB(MBB);
|
||||||
|
|
||||||
|
return Modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
|
||||||
|
bool Modified = false;
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
|
||||||
|
while (MBBI != E) {
|
||||||
|
MachineBasicBlock::iterator NMBBI = std::next(MBBI);
|
||||||
|
Modified |= expandMI(MBB, MBBI, NMBBI);
|
||||||
|
MBBI = NMBBI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MBBI,
|
||||||
|
MachineBasicBlock::iterator &NextMBBI) {
|
||||||
|
switch (MBBI->getOpcode()) {
|
||||||
|
case LoongArch::PseudoCopyCFR:
|
||||||
|
return expandCopyCFR(MBB, MBBI, NextMBBI);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoongArchExpandPseudo::expandCopyCFR(
|
||||||
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||||
|
MachineBasicBlock::iterator &NextMBBI) {
|
||||||
|
MachineFunction *MF = MBB.getParent();
|
||||||
|
MachineInstr &MI = *MBBI;
|
||||||
|
DebugLoc DL = MI.getDebugLoc();
|
||||||
|
|
||||||
|
// Expand:
|
||||||
|
// MBB:
|
||||||
|
// fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)
|
||||||
|
// bceqz $src, SinkBB
|
||||||
|
// FalseBB:
|
||||||
|
// fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)
|
||||||
|
// SinkBB:
|
||||||
|
// fallthrough
|
||||||
|
|
||||||
|
const BasicBlock *LLVM_BB = MBB.getBasicBlock();
|
||||||
|
auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);
|
||||||
|
auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);
|
||||||
|
|
||||||
|
MF->insert(++MBB.getIterator(), FalseBB);
|
||||||
|
MF->insert(++FalseBB->getIterator(), SinkBB);
|
||||||
|
|
||||||
|
Register DestReg = MI.getOperand(0).getReg();
|
||||||
|
Register SrcReg = MI.getOperand(1).getReg();
|
||||||
|
// DestReg = 0
|
||||||
|
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);
|
||||||
|
// Insert branch instruction.
|
||||||
|
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))
|
||||||
|
.addReg(SrcReg)
|
||||||
|
.addMBB(SinkBB);
|
||||||
|
// DestReg = 1
|
||||||
|
BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);
|
||||||
|
|
||||||
|
FalseBB->addSuccessor(SinkBB);
|
||||||
|
|
||||||
|
SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());
|
||||||
|
SinkBB->transferSuccessors(&MBB);
|
||||||
|
|
||||||
|
MBB.addSuccessor(FalseBB);
|
||||||
|
MBB.addSuccessor(SinkBB);
|
||||||
|
|
||||||
|
NextMBBI = MBB.end();
|
||||||
|
MI.eraseFromParent();
|
||||||
|
|
||||||
|
// Make sure live-ins are correctly attached to this new basic block.
|
||||||
|
LivePhysRegs LiveRegs;
|
||||||
|
computeAndAddLiveIns(LiveRegs, *FalseBB);
|
||||||
|
computeAndAddLiveIns(LiveRegs, *SinkBB);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
|
INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
|
||||||
LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
|
LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
|
||||||
|
|
||||||
|
INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",
|
||||||
|
LOONGARCH_EXPAND_PSEUDO_NAME, false, false)
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
FunctionPass *createLoongArchPreRAExpandPseudoPass() {
|
FunctionPass *createLoongArchPreRAExpandPseudoPass() {
|
||||||
return new LoongArchPreRAExpandPseudo();
|
return new LoongArchPreRAExpandPseudo();
|
||||||
}
|
}
|
||||||
|
FunctionPass *createLoongArchExpandPseudoPass() {
|
||||||
|
return new LoongArchExpandPseudo();
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -126,6 +126,23 @@ def PseudoST_CFR : Pseudo<(outs),
|
|||||||
let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
|
let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
|
||||||
def PseudoLD_CFR : Pseudo<(outs CFR:$ccd),
|
def PseudoLD_CFR : Pseudo<(outs CFR:$ccd),
|
||||||
(ins GPR:$rj, grlenimm:$imm)>;
|
(ins GPR:$rj, grlenimm:$imm)>;
|
||||||
|
|
||||||
|
// SET_CFR_{FALSE,TRUE}
|
||||||
|
// These instructions are defined in order to avoid expensive check error if
|
||||||
|
// regular instruction patterns are used.
|
||||||
|
// fcmp.caf.s $dst, $fa0, $fa0
|
||||||
|
def SET_CFR_FALSE : SET_CFR<0x0c100000, "fcmp.caf.s">;
|
||||||
|
// fcmp.cueq.s $dst, $fa0, $fa0
|
||||||
|
def SET_CFR_TRUE : SET_CFR<0x0c160000, "fcmp.cueq.s">;
|
||||||
|
|
||||||
|
// Pseudo instruction for copying CFRs.
|
||||||
|
def PseudoCopyCFR : Pseudo<(outs CFR:$dst), (ins CFR:$src)> {
|
||||||
|
let mayLoad = 0;
|
||||||
|
let mayStore = 0;
|
||||||
|
let hasSideEffects = 0;
|
||||||
|
let Size = 12;
|
||||||
|
}
|
||||||
|
|
||||||
} // Predicates = [HasBasicF]
|
} // Predicates = [HasBasicF]
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -218,3 +218,15 @@ class FP_STORE_2RI12<bits<32> op, RegisterClass rc = FPR32>
|
|||||||
: FPFmt2RI12<op, (outs), (ins rc:$fd, GPR:$rj, simm12:$imm12),
|
: FPFmt2RI12<op, (outs), (ins rc:$fd, GPR:$rj, simm12:$imm12),
|
||||||
"$fd, $rj, $imm12">;
|
"$fd, $rj, $imm12">;
|
||||||
} // hasSideEffects = 0, mayLoad = 0, mayStore = 1
|
} // hasSideEffects = 0, mayLoad = 0, mayStore = 1
|
||||||
|
|
||||||
|
// This class is used to define `SET_CFR_{FALSE,TRUE}` instructions which are
|
||||||
|
// used to expand `PseudoCopyCFR`.
|
||||||
|
class SET_CFR<bits<32> op, string opcstr>
|
||||||
|
: FP_CMP<op> {
|
||||||
|
let isCodeGenOnly = 1;
|
||||||
|
let fj = 0; // fa0
|
||||||
|
let fk = 0; // fa0
|
||||||
|
let AsmString = opcstr # "\t$cd, $$fa0, $$fa0";
|
||||||
|
let OutOperandList = (outs CFR:$cd);
|
||||||
|
let InOperandList = (ins);
|
||||||
|
}
|
||||||
|
@ -61,6 +61,12 @@ void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|||||||
.addReg(SrcReg, getKillRegState(KillSrc));
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// CFR->CFR copy.
|
||||||
|
if (LoongArch::CFRRegClass.contains(DstReg, SrcReg)) {
|
||||||
|
BuildMI(MBB, MBBI, DL, get(LoongArch::PseudoCopyCFR), DstReg)
|
||||||
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// FPR->FPR copies.
|
// FPR->FPR copies.
|
||||||
unsigned Opc;
|
unsigned Opc;
|
||||||
|
@ -98,13 +98,6 @@ LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|||||||
if (TFI->hasBP(MF))
|
if (TFI->hasBP(MF))
|
||||||
markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp
|
markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp
|
||||||
|
|
||||||
// FIXME: To avoid generating COPY instructions between CFRs, only use $fcc0.
|
|
||||||
// This is required to work around the fact that COPY instruction between CFRs
|
|
||||||
// is not provided in LoongArch.
|
|
||||||
if (MF.getSubtarget<LoongArchSubtarget>().hasBasicF())
|
|
||||||
for (size_t Reg = LoongArch::FCC1; Reg <= LoongArch::FCC7; ++Reg)
|
|
||||||
markSuperRegs(Reserved, Reg);
|
|
||||||
|
|
||||||
assert(checkAllSuperRegsMarked(Reserved));
|
assert(checkAllSuperRegsMarked(Reserved));
|
||||||
return Reserved;
|
return Reserved;
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,7 @@ LoongArchTargetMachine::getTargetTransformInfo(const Function &F) const {
|
|||||||
void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
|
void LoongArchPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
|
||||||
|
|
||||||
void LoongArchPassConfig::addPreEmitPass2() {
|
void LoongArchPassConfig::addPreEmitPass2() {
|
||||||
|
addPass(createLoongArchExpandPseudoPass());
|
||||||
// Schedule the expansion of AtomicPseudos at the last possible moment,
|
// Schedule the expansion of AtomicPseudos at the last possible moment,
|
||||||
// avoiding the possibility for other passes to break the requirements for
|
// avoiding the possibility for other passes to break the requirements for
|
||||||
// forward progress in the LL/SC block.
|
// forward progress in the LL/SC block.
|
||||||
|
@ -2593,12 +2593,13 @@ SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op,
|
|||||||
SDValue Shamt = Op.getOperand(2);
|
SDValue Shamt = Op.getOperand(2);
|
||||||
// if shamt < (VT.bits):
|
// if shamt < (VT.bits):
|
||||||
// lo = (shl lo, shamt)
|
// lo = (shl lo, shamt)
|
||||||
// hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt))
|
// hi = (or (shl hi, shamt) (srl (srl lo, 1), (xor shamt, (VT.bits-1))))
|
||||||
// else:
|
// else:
|
||||||
// lo = 0
|
// lo = 0
|
||||||
// hi = (shl lo, shamt[4:0])
|
// hi = (shl lo, shamt[4:0])
|
||||||
SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt,
|
SDValue Not =
|
||||||
DAG.getConstant(-1, DL, MVT::i32));
|
DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt,
|
||||||
|
DAG.getConstant(VT.getSizeInBits() - 1, DL, MVT::i32));
|
||||||
SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo,
|
SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo,
|
||||||
DAG.getConstant(1, DL, VT));
|
DAG.getConstant(1, DL, VT));
|
||||||
SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not);
|
SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not);
|
||||||
@ -2623,7 +2624,7 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
|
|||||||
MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32;
|
MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32;
|
||||||
|
|
||||||
// if shamt < (VT.bits):
|
// if shamt < (VT.bits):
|
||||||
// lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt))
|
// lo = (or (shl (shl hi, 1), (xor shamt, (VT.bits-1))) (srl lo, shamt))
|
||||||
// if isSRA:
|
// if isSRA:
|
||||||
// hi = (sra hi, shamt)
|
// hi = (sra hi, shamt)
|
||||||
// else:
|
// else:
|
||||||
@ -2635,8 +2636,9 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
|
|||||||
// else:
|
// else:
|
||||||
// lo = (srl hi, shamt[4:0])
|
// lo = (srl hi, shamt[4:0])
|
||||||
// hi = 0
|
// hi = 0
|
||||||
SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt,
|
SDValue Not =
|
||||||
DAG.getConstant(-1, DL, MVT::i32));
|
DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt,
|
||||||
|
DAG.getConstant(VT.getSizeInBits() - 1, DL, MVT::i32));
|
||||||
SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi,
|
SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi,
|
||||||
DAG.getConstant(1, DL, VT));
|
DAG.getConstant(1, DL, VT));
|
||||||
SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not);
|
SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not);
|
||||||
|
@ -299,11 +299,6 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|||||||
MCRegister SrcReg, bool KillSrc) const {
|
MCRegister SrcReg, bool KillSrc) const {
|
||||||
const TargetRegisterInfo *TRI = STI.getRegisterInfo();
|
const TargetRegisterInfo *TRI = STI.getRegisterInfo();
|
||||||
|
|
||||||
if (RISCV::GPRPF64RegClass.contains(DstReg))
|
|
||||||
DstReg = TRI->getSubReg(DstReg, RISCV::sub_32);
|
|
||||||
if (RISCV::GPRPF64RegClass.contains(SrcReg))
|
|
||||||
SrcReg = TRI->getSubReg(SrcReg, RISCV::sub_32);
|
|
||||||
|
|
||||||
if (RISCV::GPRRegClass.contains(DstReg, SrcReg)) {
|
if (RISCV::GPRRegClass.contains(DstReg, SrcReg)) {
|
||||||
BuildMI(MBB, MBBI, DL, get(RISCV::ADDI), DstReg)
|
BuildMI(MBB, MBBI, DL, get(RISCV::ADDI), DstReg)
|
||||||
.addReg(SrcReg, getKillRegState(KillSrc))
|
.addReg(SrcReg, getKillRegState(KillSrc))
|
||||||
@ -311,6 +306,20 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RISCV::GPRPF64RegClass.contains(DstReg, SrcReg)) {
|
||||||
|
// Emit an ADDI for both parts of GPRPF64.
|
||||||
|
BuildMI(MBB, MBBI, DL, get(RISCV::ADDI),
|
||||||
|
TRI->getSubReg(DstReg, RISCV::sub_32))
|
||||||
|
.addReg(TRI->getSubReg(SrcReg, RISCV::sub_32), getKillRegState(KillSrc))
|
||||||
|
.addImm(0);
|
||||||
|
BuildMI(MBB, MBBI, DL, get(RISCV::ADDI),
|
||||||
|
TRI->getSubReg(DstReg, RISCV::sub_32_hi))
|
||||||
|
.addReg(TRI->getSubReg(SrcReg, RISCV::sub_32_hi),
|
||||||
|
getKillRegState(KillSrc))
|
||||||
|
.addImm(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle copy from csr
|
// Handle copy from csr
|
||||||
if (RISCV::VCSRRegClass.contains(SrcReg) &&
|
if (RISCV::VCSRRegClass.contains(SrcReg) &&
|
||||||
RISCV::GPRRegClass.contains(DstReg)) {
|
RISCV::GPRRegClass.contains(DstReg)) {
|
||||||
|
@ -1701,13 +1701,16 @@ static void RemoveAttribute(Function *F, Attribute::AttrKind A) {
|
|||||||
/// idea here is that we don't want to mess with the convention if the user
|
/// idea here is that we don't want to mess with the convention if the user
|
||||||
/// explicitly requested something with performance implications like coldcc,
|
/// explicitly requested something with performance implications like coldcc,
|
||||||
/// GHC, or anyregcc.
|
/// GHC, or anyregcc.
|
||||||
static bool hasChangeableCC(Function *F) {
|
static bool hasChangeableCCImpl(Function *F) {
|
||||||
CallingConv::ID CC = F->getCallingConv();
|
CallingConv::ID CC = F->getCallingConv();
|
||||||
|
|
||||||
// FIXME: Is it worth transforming x86_stdcallcc and x86_fastcallcc?
|
// FIXME: Is it worth transforming x86_stdcallcc and x86_fastcallcc?
|
||||||
if (CC != CallingConv::C && CC != CallingConv::X86_ThisCall)
|
if (CC != CallingConv::C && CC != CallingConv::X86_ThisCall)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (F->isVarArg())
|
||||||
|
return false;
|
||||||
|
|
||||||
// FIXME: Change CC for the whole chain of musttail calls when possible.
|
// FIXME: Change CC for the whole chain of musttail calls when possible.
|
||||||
//
|
//
|
||||||
// Can't change CC of the function that either has musttail calls, or is a
|
// Can't change CC of the function that either has musttail calls, or is a
|
||||||
@ -1727,7 +1730,16 @@ static bool hasChangeableCC(Function *F) {
|
|||||||
if (BB.getTerminatingMustTailCall())
|
if (BB.getTerminatingMustTailCall())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return !F->hasAddressTaken();
|
||||||
|
}
|
||||||
|
|
||||||
|
using ChangeableCCCacheTy = SmallDenseMap<Function *, bool, 8>;
|
||||||
|
static bool hasChangeableCC(Function *F,
|
||||||
|
ChangeableCCCacheTy &ChangeableCCCache) {
|
||||||
|
auto Res = ChangeableCCCache.try_emplace(F, false);
|
||||||
|
if (Res.second)
|
||||||
|
Res.first->second = hasChangeableCCImpl(F);
|
||||||
|
return Res.first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the block containing the call site has a BlockFrequency of
|
/// Return true if the block containing the call site has a BlockFrequency of
|
||||||
@ -1781,7 +1793,8 @@ static void changeCallSitesToColdCC(Function *F) {
|
|||||||
// coldcc calling convention.
|
// coldcc calling convention.
|
||||||
static bool
|
static bool
|
||||||
hasOnlyColdCalls(Function &F,
|
hasOnlyColdCalls(Function &F,
|
||||||
function_ref<BlockFrequencyInfo &(Function &)> GetBFI) {
|
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
|
||||||
|
ChangeableCCCacheTy &ChangeableCCCache) {
|
||||||
for (BasicBlock &BB : F) {
|
for (BasicBlock &BB : F) {
|
||||||
for (Instruction &I : BB) {
|
for (Instruction &I : BB) {
|
||||||
if (CallInst *CI = dyn_cast<CallInst>(&I)) {
|
if (CallInst *CI = dyn_cast<CallInst>(&I)) {
|
||||||
@ -1800,8 +1813,7 @@ hasOnlyColdCalls(Function &F,
|
|||||||
if (!CalledFn->hasLocalLinkage())
|
if (!CalledFn->hasLocalLinkage())
|
||||||
return false;
|
return false;
|
||||||
// Check if it's valid to use coldcc calling convention.
|
// Check if it's valid to use coldcc calling convention.
|
||||||
if (!hasChangeableCC(CalledFn) || CalledFn->isVarArg() ||
|
if (!hasChangeableCC(CalledFn, ChangeableCCCache))
|
||||||
CalledFn->hasAddressTaken())
|
|
||||||
return false;
|
return false;
|
||||||
BlockFrequencyInfo &CallerBFI = GetBFI(F);
|
BlockFrequencyInfo &CallerBFI = GetBFI(F);
|
||||||
if (!isColdCallSite(*CI, CallerBFI))
|
if (!isColdCallSite(*CI, CallerBFI))
|
||||||
@ -1931,9 +1943,10 @@ OptimizeFunctions(Module &M,
|
|||||||
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
|
ChangeableCCCacheTy ChangeableCCCache;
|
||||||
std::vector<Function *> AllCallsCold;
|
std::vector<Function *> AllCallsCold;
|
||||||
for (Function &F : llvm::make_early_inc_range(M))
|
for (Function &F : llvm::make_early_inc_range(M))
|
||||||
if (hasOnlyColdCalls(F, GetBFI))
|
if (hasOnlyColdCalls(F, GetBFI, ChangeableCCCache))
|
||||||
AllCallsCold.push_back(&F);
|
AllCallsCold.push_back(&F);
|
||||||
|
|
||||||
// Optimize functions.
|
// Optimize functions.
|
||||||
@ -1995,7 +2008,7 @@ OptimizeFunctions(Module &M,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasChangeableCC(&F) && !F.isVarArg() && !F.hasAddressTaken()) {
|
if (hasChangeableCC(&F, ChangeableCCCache)) {
|
||||||
NumInternalFunc++;
|
NumInternalFunc++;
|
||||||
TargetTransformInfo &TTI = GetTTI(F);
|
TargetTransformInfo &TTI = GetTTI(F);
|
||||||
// Change the calling convention to coldcc if either stress testing is
|
// Change the calling convention to coldcc if either stress testing is
|
||||||
@ -2005,6 +2018,7 @@ OptimizeFunctions(Module &M,
|
|||||||
if (EnableColdCCStressTest ||
|
if (EnableColdCCStressTest ||
|
||||||
(TTI.useColdCCForColdCall(F) &&
|
(TTI.useColdCCForColdCall(F) &&
|
||||||
isValidCandidateForColdCC(F, GetBFI, AllCallsCold))) {
|
isValidCandidateForColdCC(F, GetBFI, AllCallsCold))) {
|
||||||
|
ChangeableCCCache.erase(&F);
|
||||||
F.setCallingConv(CallingConv::Cold);
|
F.setCallingConv(CallingConv::Cold);
|
||||||
changeCallSitesToColdCC(&F);
|
changeCallSitesToColdCC(&F);
|
||||||
Changed = true;
|
Changed = true;
|
||||||
@ -2012,7 +2026,7 @@ OptimizeFunctions(Module &M,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasChangeableCC(&F) && !F.isVarArg() && !F.hasAddressTaken()) {
|
if (hasChangeableCC(&F, ChangeableCCCache)) {
|
||||||
// If this function has a calling convention worth changing, is not a
|
// If this function has a calling convention worth changing, is not a
|
||||||
// varargs function, and is only called directly, promote it to use the
|
// varargs function, and is only called directly, promote it to use the
|
||||||
// Fast calling convention.
|
// Fast calling convention.
|
||||||
|
@ -412,6 +412,19 @@ static Decomposition decompose(Value *V,
|
|||||||
return ResA;
|
return ResA;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Type *Ty = V->getType()->getScalarType();
|
||||||
|
if (Ty->isPointerTy() && !IsSigned) {
|
||||||
|
if (auto *GEP = dyn_cast<GEPOperator>(V))
|
||||||
|
return decomposeGEP(*GEP, Preconditions, IsSigned, DL);
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't handle integers > 64 bit. Our coefficients are 64-bit large, so
|
||||||
|
// coefficient add/mul may wrap, while the operation in the full bit width
|
||||||
|
// would not.
|
||||||
|
if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
|
||||||
|
return V;
|
||||||
|
|
||||||
// Decompose \p V used with a signed predicate.
|
// Decompose \p V used with a signed predicate.
|
||||||
if (IsSigned) {
|
if (IsSigned) {
|
||||||
if (auto *CI = dyn_cast<ConstantInt>(V)) {
|
if (auto *CI = dyn_cast<ConstantInt>(V)) {
|
||||||
@ -439,9 +452,6 @@ static Decomposition decompose(Value *V,
|
|||||||
return int64_t(CI->getZExtValue());
|
return int64_t(CI->getZExtValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto *GEP = dyn_cast<GEPOperator>(V))
|
|
||||||
return decomposeGEP(*GEP, Preconditions, IsSigned, DL);
|
|
||||||
|
|
||||||
Value *Op0;
|
Value *Op0;
|
||||||
bool IsKnownNonNegative = false;
|
bool IsKnownNonNegative = false;
|
||||||
if (match(V, m_ZExt(m_Value(Op0)))) {
|
if (match(V, m_ZExt(m_Value(Op0)))) {
|
||||||
|
@ -470,17 +470,17 @@ static bool processBinOp(BinaryOperator *BinOp, LazyValueInfo *LVI);
|
|||||||
// because it is negation-invariant.
|
// because it is negation-invariant.
|
||||||
static bool processAbsIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
|
static bool processAbsIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
|
||||||
Value *X = II->getArgOperand(0);
|
Value *X = II->getArgOperand(0);
|
||||||
bool IsIntMinPoison = cast<ConstantInt>(II->getArgOperand(1))->isOne();
|
|
||||||
|
|
||||||
Type *Ty = X->getType();
|
Type *Ty = X->getType();
|
||||||
Constant *IntMin =
|
if (!Ty->isIntegerTy())
|
||||||
ConstantInt::get(Ty, APInt::getSignedMinValue(Ty->getScalarSizeInBits()));
|
return false;
|
||||||
LazyValueInfo::Tristate Result;
|
|
||||||
|
bool IsIntMinPoison = cast<ConstantInt>(II->getArgOperand(1))->isOne();
|
||||||
|
APInt IntMin = APInt::getSignedMinValue(Ty->getScalarSizeInBits());
|
||||||
|
ConstantRange Range = LVI->getConstantRangeAtUse(
|
||||||
|
II->getOperandUse(0), /*UndefAllowed*/ IsIntMinPoison);
|
||||||
|
|
||||||
// Is X in [0, IntMin]? NOTE: INT_MIN is fine!
|
// Is X in [0, IntMin]? NOTE: INT_MIN is fine!
|
||||||
Result = LVI->getPredicateAt(CmpInst::Predicate::ICMP_ULE, X, IntMin, II,
|
if (Range.icmp(CmpInst::ICMP_ULE, IntMin)) {
|
||||||
/*UseBlockValue=*/true);
|
|
||||||
if (Result == LazyValueInfo::True) {
|
|
||||||
++NumAbs;
|
++NumAbs;
|
||||||
II->replaceAllUsesWith(X);
|
II->replaceAllUsesWith(X);
|
||||||
II->eraseFromParent();
|
II->eraseFromParent();
|
||||||
@ -488,40 +488,30 @@ static bool processAbsIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Is X in [IntMin, 0]? NOTE: INT_MIN is fine!
|
// Is X in [IntMin, 0]? NOTE: INT_MIN is fine!
|
||||||
Constant *Zero = ConstantInt::getNullValue(Ty);
|
if (Range.getSignedMax().isNonPositive()) {
|
||||||
Result = LVI->getPredicateAt(CmpInst::Predicate::ICMP_SLE, X, Zero, II,
|
IRBuilder<> B(II);
|
||||||
/*UseBlockValue=*/true);
|
Value *NegX = B.CreateNeg(X, II->getName(), /*HasNUW=*/false,
|
||||||
assert(Result != LazyValueInfo::False && "Should have been handled already.");
|
/*HasNSW=*/IsIntMinPoison);
|
||||||
|
++NumAbs;
|
||||||
|
II->replaceAllUsesWith(NegX);
|
||||||
|
II->eraseFromParent();
|
||||||
|
|
||||||
if (Result == LazyValueInfo::Unknown) {
|
// See if we can infer some no-wrap flags.
|
||||||
// Argument's range crosses zero.
|
if (auto *BO = dyn_cast<BinaryOperator>(NegX))
|
||||||
bool Changed = false;
|
processBinOp(BO, LVI);
|
||||||
if (!IsIntMinPoison) {
|
|
||||||
// Can we at least tell that the argument is never INT_MIN?
|
return true;
|
||||||
Result = LVI->getPredicateAt(CmpInst::Predicate::ICMP_NE, X, IntMin, II,
|
|
||||||
/*UseBlockValue=*/true);
|
|
||||||
if (Result == LazyValueInfo::True) {
|
|
||||||
++NumNSW;
|
|
||||||
++NumSubNSW;
|
|
||||||
II->setArgOperand(1, ConstantInt::getTrue(II->getContext()));
|
|
||||||
Changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Changed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IRBuilder<> B(II);
|
// Argument's range crosses zero.
|
||||||
Value *NegX = B.CreateNeg(X, II->getName(), /*HasNUW=*/false,
|
// Can we at least tell that the argument is never INT_MIN?
|
||||||
/*HasNSW=*/IsIntMinPoison);
|
if (!IsIntMinPoison && !Range.contains(IntMin)) {
|
||||||
++NumAbs;
|
++NumNSW;
|
||||||
II->replaceAllUsesWith(NegX);
|
++NumSubNSW;
|
||||||
II->eraseFromParent();
|
II->setArgOperand(1, ConstantInt::getTrue(II->getContext()));
|
||||||
|
return true;
|
||||||
// See if we can infer some no-wrap flags.
|
}
|
||||||
if (auto *BO = dyn_cast<BinaryOperator>(NegX))
|
return false;
|
||||||
processBinOp(BO, LVI);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if this min/max intrinsic always picks it's one specific operand.
|
// See if this min/max intrinsic always picks it's one specific operand.
|
||||||
|
@ -946,9 +946,14 @@ static void replaceValuesPerBlockEntry(
|
|||||||
SmallVectorImpl<AvailableValueInBlock> &ValuesPerBlock, Value *OldValue,
|
SmallVectorImpl<AvailableValueInBlock> &ValuesPerBlock, Value *OldValue,
|
||||||
Value *NewValue) {
|
Value *NewValue) {
|
||||||
for (AvailableValueInBlock &V : ValuesPerBlock) {
|
for (AvailableValueInBlock &V : ValuesPerBlock) {
|
||||||
if ((V.AV.isSimpleValue() && V.AV.getSimpleValue() == OldValue) ||
|
if (V.AV.Val == OldValue)
|
||||||
(V.AV.isCoercedLoadValue() && V.AV.getCoercedLoadValue() == OldValue))
|
V.AV.Val = NewValue;
|
||||||
V = AvailableValueInBlock::get(V.BB, NewValue);
|
if (V.AV.isSelectValue()) {
|
||||||
|
if (V.AV.V1 == OldValue)
|
||||||
|
V.AV.V1 = NewValue;
|
||||||
|
if (V.AV.V2 == OldValue)
|
||||||
|
V.AV.V2 = NewValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1603,6 +1603,7 @@ bool MemCpyOptPass::processByValArgument(CallBase &CB, unsigned ArgNo) {
|
|||||||
<< " " << CB << "\n");
|
<< " " << CB << "\n");
|
||||||
|
|
||||||
// Otherwise we're good! Update the byval argument.
|
// Otherwise we're good! Update the byval argument.
|
||||||
|
combineAAMetadata(&CB, MDep);
|
||||||
CB.setArgOperand(ArgNo, MDep->getSource());
|
CB.setArgOperand(ArgNo, MDep->getSource());
|
||||||
++NumMemCpyInstr;
|
++NumMemCpyInstr;
|
||||||
return true;
|
return true;
|
||||||
|
@ -10118,7 +10118,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (E->State == TreeEntry::NeedToGather) {
|
if (E->State == TreeEntry::NeedToGather) {
|
||||||
if (E->getMainOp() && E->Idx == 0)
|
// Set insert point for non-reduction initial nodes.
|
||||||
|
if (E->getMainOp() && E->Idx == 0 && !UserIgnoreList)
|
||||||
setInsertPointAfterBundle(E);
|
setInsertPointAfterBundle(E);
|
||||||
Value *Vec = createBuildVector(E);
|
Value *Vec = createBuildVector(E);
|
||||||
E->VectorizedValue = Vec;
|
E->VectorizedValue = Vec;
|
||||||
|
@ -8858,7 +8858,8 @@ __kmp_determine_reduction_method(
|
|||||||
|
|
||||||
#elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS
|
#elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS
|
||||||
|
|
||||||
#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_WINDOWS || KMP_OS_HURD
|
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
|
||||||
|
KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_HURD
|
||||||
|
|
||||||
// basic tuning
|
// basic tuning
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include <lwp.h>
|
#include <lwp.h>
|
||||||
#define __kmp_gettid() _lwp_self()
|
#define __kmp_gettid() _lwp_self()
|
||||||
#elif KMP_OS_OPENBSD
|
#elif KMP_OS_OPENBSD
|
||||||
#define __kmp_gettid() syscall(SYS_getthrid)
|
#define __kmp_gettid() getthrid()
|
||||||
#elif defined(SYS_gettid)
|
#elif defined(SYS_gettid)
|
||||||
// Hopefully other Unix systems define SYS_gettid syscall for getting os thread
|
// Hopefully other Unix systems define SYS_gettid syscall for getting os thread
|
||||||
// id
|
// id
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#define LLVM_REVISION "llvmorg-17.0.3-0-g888437e1b600"
|
#define LLVM_REVISION "llvmorg-17.0.5-0-g98bfdac5ce82"
|
||||||
#define LLVM_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
#define LLVM_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||||
|
|
||||||
#define CLANG_REVISION "llvmorg-17.0.3-0-g888437e1b600"
|
#define CLANG_REVISION "llvmorg-17.0.5-0-g98bfdac5ce82"
|
||||||
#define CLANG_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
#define CLANG_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||||
|
|
||||||
#define LLDB_REVISION "llvmorg-17.0.3-0-g888437e1b600"
|
#define LLDB_REVISION "llvmorg-17.0.5-0-g98bfdac5ce82"
|
||||||
#define LLDB_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
#define LLDB_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#define CLANG_VERSION 17.0.3
|
#define CLANG_VERSION 17.0.5
|
||||||
#define CLANG_VERSION_STRING "17.0.3"
|
#define CLANG_VERSION_STRING "17.0.5"
|
||||||
#define CLANG_VERSION_MAJOR 17
|
#define CLANG_VERSION_MAJOR 17
|
||||||
#define CLANG_VERSION_MAJOR_STRING "17"
|
#define CLANG_VERSION_MAJOR_STRING "17"
|
||||||
#define CLANG_VERSION_MINOR 0
|
#define CLANG_VERSION_MINOR 0
|
||||||
#define CLANG_VERSION_PATCHLEVEL 3
|
#define CLANG_VERSION_PATCHLEVEL 5
|
||||||
|
|
||||||
#define CLANG_VENDOR "FreeBSD "
|
#define CLANG_VENDOR "FreeBSD "
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Local identifier in __FreeBSD_version style
|
// Local identifier in __FreeBSD_version style
|
||||||
#define LLD_FREEBSD_VERSION 1500000
|
#define LLD_FREEBSD_VERSION 1500000
|
||||||
|
|
||||||
#define LLD_VERSION_STRING "17.0.3 (FreeBSD llvmorg-17.0.3-0-g888437e1b600-" __XSTRING(LLD_FREEBSD_VERSION) ")"
|
#define LLD_VERSION_STRING "17.0.5 (FreeBSD llvmorg-17.0.5-0-g98bfdac5ce82-" __XSTRING(LLD_FREEBSD_VERSION) ")"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#define LLDB_VERSION 17.0.3
|
#define LLDB_VERSION 17.0.5
|
||||||
#define LLDB_VERSION_STRING "17.0.3"
|
#define LLDB_VERSION_STRING "17.0.5"
|
||||||
#define LLDB_VERSION_MAJOR 17
|
#define LLDB_VERSION_MAJOR 17
|
||||||
#define LLDB_VERSION_MINOR 0
|
#define LLDB_VERSION_MINOR 0
|
||||||
#define LLDB_VERSION_PATCH 3
|
#define LLDB_VERSION_PATCH 5
|
||||||
/* #undef LLDB_FULL_VERSION_STRING */
|
/* #undef LLDB_FULL_VERSION_STRING */
|
||||||
|
@ -344,10 +344,10 @@
|
|||||||
#define PACKAGE_NAME "LLVM"
|
#define PACKAGE_NAME "LLVM"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* Define to the full name and version of this package. */
|
||||||
#define PACKAGE_STRING "LLVM 17.0.3"
|
#define PACKAGE_STRING "LLVM 17.0.5"
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "17.0.3"
|
#define PACKAGE_VERSION "17.0.5"
|
||||||
|
|
||||||
/* Define to the vendor of this package. */
|
/* Define to the vendor of this package. */
|
||||||
/* #undef PACKAGE_VENDOR */
|
/* #undef PACKAGE_VENDOR */
|
||||||
|
@ -73,10 +73,10 @@
|
|||||||
#define LLVM_VERSION_MINOR 0
|
#define LLVM_VERSION_MINOR 0
|
||||||
|
|
||||||
/* Patch version of the LLVM API */
|
/* Patch version of the LLVM API */
|
||||||
#define LLVM_VERSION_PATCH 3
|
#define LLVM_VERSION_PATCH 5
|
||||||
|
|
||||||
/* LLVM version string */
|
/* LLVM version string */
|
||||||
#define LLVM_VERSION_STRING "17.0.3"
|
#define LLVM_VERSION_STRING "17.0.5"
|
||||||
|
|
||||||
/* Whether LLVM records statistics for use with GetStatistics(),
|
/* Whether LLVM records statistics for use with GetStatistics(),
|
||||||
* PrintStatistics() or PrintStatisticsJSON()
|
* PrintStatistics() or PrintStatisticsJSON()
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#define LLVM_REVISION "llvmorg-17.0.3-0-g888437e1b600"
|
#define LLVM_REVISION "llvmorg-17.0.5-0-g98bfdac5ce82"
|
||||||
#define LLVM_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
#define LLVM_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||||
|
Loading…
Reference in New Issue
Block a user