mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-18 02:19:39 +00:00
Vendor import of llvm-project branch release/19.x llvmorg-19.1.1-0-gd401987fe349, a.k.a. 19.1.1 release.
This commit is contained in:
parent
1de139fdd5
commit
0370629593
@ -680,6 +680,9 @@ class alignas(8) Decl {
|
|||||||
/// Whether this declaration comes from explicit global module.
|
/// Whether this declaration comes from explicit global module.
|
||||||
bool isFromExplicitGlobalModule() const;
|
bool isFromExplicitGlobalModule() const;
|
||||||
|
|
||||||
|
/// Whether this declaration comes from global module.
|
||||||
|
bool isFromGlobalModule() const;
|
||||||
|
|
||||||
/// Whether this declaration comes from a named module.
|
/// Whether this declaration comes from a named module.
|
||||||
bool isInNamedModule() const;
|
bool isInNamedModule() const;
|
||||||
|
|
||||||
|
@ -234,6 +234,12 @@ std::unique_ptr<CompilationDatabase>
|
|||||||
std::unique_ptr<CompilationDatabase>
|
std::unique_ptr<CompilationDatabase>
|
||||||
inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base);
|
inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base);
|
||||||
|
|
||||||
|
/// Returns a wrapped CompilationDatabase that will transform argv[0] to an
|
||||||
|
/// absolute path, if it currently is a plain tool name, looking it up in
|
||||||
|
/// PATH.
|
||||||
|
std::unique_ptr<CompilationDatabase>
|
||||||
|
inferToolLocation(std::unique_ptr<CompilationDatabase> Base);
|
||||||
|
|
||||||
/// Returns a wrapped CompilationDatabase that will expand all rsp(response)
|
/// Returns a wrapped CompilationDatabase that will expand all rsp(response)
|
||||||
/// files on commandline returned by underlying database.
|
/// files on commandline returned by underlying database.
|
||||||
std::unique_ptr<CompilationDatabase>
|
std::unique_ptr<CompilationDatabase>
|
||||||
|
@ -1161,6 +1161,10 @@ bool Decl::isFromExplicitGlobalModule() const {
|
|||||||
return getOwningModule() && getOwningModule()->isExplicitGlobalModule();
|
return getOwningModule() && getOwningModule()->isExplicitGlobalModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Decl::isFromGlobalModule() const {
|
||||||
|
return getOwningModule() && getOwningModule()->isGlobalModule();
|
||||||
|
}
|
||||||
|
|
||||||
bool Decl::isInNamedModule() const {
|
bool Decl::isInNamedModule() const {
|
||||||
return getOwningModule() && getOwningModule()->isNamedModule();
|
return getOwningModule() && getOwningModule()->isNamedModule();
|
||||||
}
|
}
|
||||||
|
@ -2833,18 +2833,22 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
|||||||
llvm::AtomicOrdering::SequentiallyConsistent);
|
llvm::AtomicOrdering::SequentiallyConsistent);
|
||||||
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
|
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
|
||||||
}
|
}
|
||||||
// Special case for atomic increment/decrement on floats
|
// Special case for atomic increment/decrement on floats.
|
||||||
|
// Bail out non-power-of-2-sized floating point types (e.g., x86_fp80).
|
||||||
if (type->isFloatingType()) {
|
if (type->isFloatingType()) {
|
||||||
llvm::AtomicRMWInst::BinOp aop =
|
llvm::Type *Ty = ConvertType(type);
|
||||||
isInc ? llvm::AtomicRMWInst::FAdd : llvm::AtomicRMWInst::FSub;
|
if (llvm::has_single_bit(Ty->getScalarSizeInBits())) {
|
||||||
llvm::Instruction::BinaryOps op =
|
llvm::AtomicRMWInst::BinOp aop =
|
||||||
isInc ? llvm::Instruction::FAdd : llvm::Instruction::FSub;
|
isInc ? llvm::AtomicRMWInst::FAdd : llvm::AtomicRMWInst::FSub;
|
||||||
llvm::Value *amt = llvm::ConstantFP::get(
|
llvm::Instruction::BinaryOps op =
|
||||||
VMContext, llvm::APFloat(static_cast<float>(1.0)));
|
isInc ? llvm::Instruction::FAdd : llvm::Instruction::FSub;
|
||||||
llvm::Value *old =
|
llvm::Value *amt = llvm::ConstantFP::get(Ty, 1.0);
|
||||||
Builder.CreateAtomicRMW(aop, LV.getAddress(), amt,
|
llvm::AtomicRMWInst *old = Builder.CreateAtomicRMW(
|
||||||
llvm::AtomicOrdering::SequentiallyConsistent);
|
aop, LV.getAddress(), amt,
|
||||||
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
|
llvm::AtomicOrdering::SequentiallyConsistent);
|
||||||
|
|
||||||
|
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
value = EmitLoadOfLValue(LV, E->getExprLoc());
|
value = EmitLoadOfLValue(LV, E->getExprLoc());
|
||||||
input = value;
|
input = value;
|
||||||
|
@ -8561,6 +8561,32 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
WantDebug = !A->getOption().matches(options::OPT_g0) &&
|
WantDebug = !A->getOption().matches(options::OPT_g0) &&
|
||||||
!A->getOption().matches(options::OPT_ggdb0);
|
!A->getOption().matches(options::OPT_ggdb0);
|
||||||
|
|
||||||
|
// If a -gdwarf argument appeared, remember it.
|
||||||
|
bool EmitDwarf = false;
|
||||||
|
if (const Arg *A = getDwarfNArg(Args))
|
||||||
|
EmitDwarf = checkDebugInfoOption(A, Args, D, getToolChain());
|
||||||
|
|
||||||
|
bool EmitCodeView = false;
|
||||||
|
if (const Arg *A = Args.getLastArg(options::OPT_gcodeview))
|
||||||
|
EmitCodeView = checkDebugInfoOption(A, Args, D, getToolChain());
|
||||||
|
|
||||||
|
// If the user asked for debug info but did not explicitly specify -gcodeview
|
||||||
|
// or -gdwarf, ask the toolchain for the default format.
|
||||||
|
if (!EmitCodeView && !EmitDwarf && WantDebug) {
|
||||||
|
switch (getToolChain().getDefaultDebugFormat()) {
|
||||||
|
case llvm::codegenoptions::DIF_CodeView:
|
||||||
|
EmitCodeView = true;
|
||||||
|
break;
|
||||||
|
case llvm::codegenoptions::DIF_DWARF:
|
||||||
|
EmitDwarf = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the arguments don't imply DWARF, don't emit any debug info here.
|
||||||
|
if (!EmitDwarf)
|
||||||
|
WantDebug = false;
|
||||||
|
|
||||||
llvm::codegenoptions::DebugInfoKind DebugInfoKind =
|
llvm::codegenoptions::DebugInfoKind DebugInfoKind =
|
||||||
llvm::codegenoptions::NoDebugInfo;
|
llvm::codegenoptions::NoDebugInfo;
|
||||||
|
|
||||||
|
@ -100,6 +100,13 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
|
|||||||
if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
|
if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
|
||||||
FirstInLineIndex = Tokens.size() - 1;
|
FirstInLineIndex = Tokens.size() - 1;
|
||||||
} while (Tokens.back()->isNot(tok::eof));
|
} while (Tokens.back()->isNot(tok::eof));
|
||||||
|
if (Style.InsertNewlineAtEOF) {
|
||||||
|
auto &TokEOF = *Tokens.back();
|
||||||
|
if (TokEOF.NewlinesBefore == 0) {
|
||||||
|
TokEOF.NewlinesBefore = 1;
|
||||||
|
TokEOF.OriginalColumn = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Tokens;
|
return Tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3680,11 +3680,6 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
|
|||||||
auto *First = Line.First;
|
auto *First = Line.First;
|
||||||
First->SpacesRequiredBefore = 1;
|
First->SpacesRequiredBefore = 1;
|
||||||
First->CanBreakBefore = First->MustBreakBefore;
|
First->CanBreakBefore = First->MustBreakBefore;
|
||||||
|
|
||||||
if (First->is(tok::eof) && First->NewlinesBefore == 0 &&
|
|
||||||
Style.InsertNewlineAtEOF) {
|
|
||||||
First->NewlinesBefore = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function heuristically determines whether 'Current' starts the name of a
|
// This function heuristically determines whether 'Current' starts the name of a
|
||||||
|
@ -969,8 +969,30 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
|
|||||||
// equivalence.
|
// equivalence.
|
||||||
LocalInstantiationScope ScopeForParameters(S);
|
LocalInstantiationScope ScopeForParameters(S);
|
||||||
if (auto *FD = DeclInfo.getDecl()->getAsFunction())
|
if (auto *FD = DeclInfo.getDecl()->getAsFunction())
|
||||||
for (auto *PVD : FD->parameters())
|
for (auto *PVD : FD->parameters()) {
|
||||||
ScopeForParameters.InstantiatedLocal(PVD, PVD);
|
if (!PVD->isParameterPack()) {
|
||||||
|
ScopeForParameters.InstantiatedLocal(PVD, PVD);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// This is hacky: we're mapping the parameter pack to a size-of-1 argument
|
||||||
|
// to avoid building SubstTemplateTypeParmPackTypes for
|
||||||
|
// PackExpansionTypes. The SubstTemplateTypeParmPackType node would
|
||||||
|
// otherwise reference the AssociatedDecl of the template arguments, which
|
||||||
|
// is, in this case, the template declaration.
|
||||||
|
//
|
||||||
|
// However, as we are in the process of comparing potential
|
||||||
|
// re-declarations, the canonical declaration is the declaration itself at
|
||||||
|
// this point. So if we didn't expand these packs, we would end up with an
|
||||||
|
// incorrect profile difference because we will be profiling the
|
||||||
|
// canonical types!
|
||||||
|
//
|
||||||
|
// FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
|
||||||
|
// that we can eliminate the Scope in the cases where the declarations are
|
||||||
|
// not necessarily instantiated. It would also benefit the noexcept
|
||||||
|
// specifier comparison.
|
||||||
|
ScopeForParameters.MakeInstantiatedLocalArgPack(PVD);
|
||||||
|
ScopeForParameters.InstantiatedLocalPackArg(PVD, PVD);
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<Sema::CXXThisScopeRAII> ThisScope;
|
std::optional<Sema::CXXThisScopeRAII> ThisScope;
|
||||||
|
|
||||||
|
@ -9732,8 +9732,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||||||
// the function decl is created above).
|
// the function decl is created above).
|
||||||
// FIXME: We need a better way to separate C++ standard and clang modules.
|
// FIXME: We need a better way to separate C++ standard and clang modules.
|
||||||
bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules ||
|
bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules ||
|
||||||
|
NewFD->isConstexpr() || NewFD->isConsteval() ||
|
||||||
!NewFD->getOwningModule() ||
|
!NewFD->getOwningModule() ||
|
||||||
NewFD->isFromExplicitGlobalModule() ||
|
NewFD->isFromGlobalModule() ||
|
||||||
NewFD->getOwningModule()->isHeaderLikeModule();
|
NewFD->getOwningModule()->isHeaderLikeModule();
|
||||||
bool isInline = D.getDeclSpec().isInlineSpecified();
|
bool isInline = D.getDeclSpec().isInlineSpecified();
|
||||||
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
|
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
|
||||||
|
71
clang/lib/Tooling/LocateToolCompilationDatabase.cpp
Normal file
71
clang/lib/Tooling/LocateToolCompilationDatabase.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
//===- GuessTargetAndModeCompilationDatabase.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 "clang/Tooling/CompilationDatabase.h"
|
||||||
|
#include "clang/Tooling/Tooling.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
#include "llvm/Support/Program.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
namespace tooling {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class LocationAdderDatabase : public CompilationDatabase {
|
||||||
|
public:
|
||||||
|
LocationAdderDatabase(std::unique_ptr<CompilationDatabase> Base)
|
||||||
|
: Base(std::move(Base)) {
|
||||||
|
assert(this->Base != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> getAllFiles() const override {
|
||||||
|
return Base->getAllFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CompileCommand> getAllCompileCommands() const override {
|
||||||
|
return addLocation(Base->getAllCompileCommands());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CompileCommand>
|
||||||
|
getCompileCommands(StringRef FilePath) const override {
|
||||||
|
return addLocation(Base->getCompileCommands(FilePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<CompileCommand>
|
||||||
|
addLocation(std::vector<CompileCommand> Cmds) const {
|
||||||
|
for (auto &Cmd : Cmds) {
|
||||||
|
if (Cmd.CommandLine.empty())
|
||||||
|
continue;
|
||||||
|
std::string &Driver = Cmd.CommandLine.front();
|
||||||
|
// If the driver name already is absolute, we don't need to do anything.
|
||||||
|
if (llvm::sys::path::is_absolute(Driver))
|
||||||
|
continue;
|
||||||
|
// If the name is a relative path, like bin/clang, we assume it's
|
||||||
|
// possible to resolve it and don't do anything about it either.
|
||||||
|
if (llvm::any_of(Driver,
|
||||||
|
[](char C) { return llvm::sys::path::is_separator(C); }))
|
||||||
|
continue;
|
||||||
|
auto Absolute = llvm::sys::findProgramByName(Driver);
|
||||||
|
// If we found it in path, update the entry in Cmd.CommandLine
|
||||||
|
if (Absolute && llvm::sys::path::is_absolute(*Absolute))
|
||||||
|
Driver = std::move(*Absolute);
|
||||||
|
}
|
||||||
|
return Cmds;
|
||||||
|
}
|
||||||
|
std::unique_ptr<CompilationDatabase> Base;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<CompilationDatabase>
|
||||||
|
inferToolLocation(std::unique_ptr<CompilationDatabase> Base) {
|
||||||
|
return std::make_unique<LocationAdderDatabase>(std::move(Base));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tooling
|
||||||
|
} // namespace clang
|
@ -2014,6 +2014,18 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
|||||||
return Unknown;
|
return Unknown;
|
||||||
return esr & ESR_ELx_WNR ? Write : Read;
|
return esr & ESR_ELx_WNR ? Write : Read;
|
||||||
# elif defined(__loongarch__)
|
# elif defined(__loongarch__)
|
||||||
|
// In the musl environment, the Linux kernel uapi sigcontext.h is not
|
||||||
|
// included in signal.h. To avoid missing the SC_ADDRERR_{RD,WR} macros,
|
||||||
|
// copy them here. The LoongArch Linux kernel uapi is already stable,
|
||||||
|
// so there's no need to worry about the value changing.
|
||||||
|
# ifndef SC_ADDRERR_RD
|
||||||
|
// Address error was due to memory load
|
||||||
|
# define SC_ADDRERR_RD (1 << 30)
|
||||||
|
# endif
|
||||||
|
# ifndef SC_ADDRERR_WR
|
||||||
|
// Address error was due to memory store
|
||||||
|
# define SC_ADDRERR_WR (1 << 31)
|
||||||
|
# endif
|
||||||
u32 flags = ucontext->uc_mcontext.__flags;
|
u32 flags = ucontext->uc_mcontext.__flags;
|
||||||
if (flags & SC_ADDRERR_RD)
|
if (flags & SC_ADDRERR_RD)
|
||||||
return SignalContext::Read;
|
return SignalContext::Read;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
// _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 190100
|
# define _LIBCPP_VERSION 190101
|
||||||
|
|
||||||
# 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)
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
# if __has_builtin(__builtin_verbose_trap)
|
# if __has_builtin(__builtin_verbose_trap)
|
||||||
// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream
|
// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream
|
||||||
// version before upstream Clang actually got the builtin.
|
// version before upstream Clang actually got the builtin.
|
||||||
# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 17000
|
// TODO: Remove once AppleClang supports the two-arguments version of the builtin.
|
||||||
|
# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1700
|
||||||
# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap(message)
|
# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap(message)
|
||||||
# else
|
# else
|
||||||
# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap("libc++", message)
|
# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap("libc++", message)
|
||||||
|
@ -324,7 +324,7 @@ bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
|
|||||||
|
|
||||||
const RelsOrRelas<ELFT> ra = a->template relsOrRelas<ELFT>();
|
const RelsOrRelas<ELFT> ra = a->template relsOrRelas<ELFT>();
|
||||||
const RelsOrRelas<ELFT> rb = b->template relsOrRelas<ELFT>();
|
const RelsOrRelas<ELFT> rb = b->template relsOrRelas<ELFT>();
|
||||||
if (ra.areRelocsCrel())
|
if (ra.areRelocsCrel() || rb.areRelocsCrel())
|
||||||
return constantEq(a, ra.crels, b, rb.crels);
|
return constantEq(a, ra.crels, b, rb.crels);
|
||||||
return ra.areRelocsRel() || rb.areRelocsRel()
|
return ra.areRelocsRel() || rb.areRelocsRel()
|
||||||
? constantEq(a, ra.rels, b, rb.rels)
|
? constantEq(a, ra.rels, b, rb.rels)
|
||||||
@ -376,7 +376,7 @@ template <class ELFT>
|
|||||||
bool ICF<ELFT>::equalsVariable(const InputSection *a, const InputSection *b) {
|
bool ICF<ELFT>::equalsVariable(const InputSection *a, const InputSection *b) {
|
||||||
const RelsOrRelas<ELFT> ra = a->template relsOrRelas<ELFT>();
|
const RelsOrRelas<ELFT> ra = a->template relsOrRelas<ELFT>();
|
||||||
const RelsOrRelas<ELFT> rb = b->template relsOrRelas<ELFT>();
|
const RelsOrRelas<ELFT> rb = b->template relsOrRelas<ELFT>();
|
||||||
if (ra.areRelocsCrel())
|
if (ra.areRelocsCrel() || rb.areRelocsCrel())
|
||||||
return variableEq(a, ra.crels, b, rb.crels);
|
return variableEq(a, ra.crels, b, rb.crels);
|
||||||
return ra.areRelocsRel() || rb.areRelocsRel()
|
return ra.areRelocsRel() || rb.areRelocsRel()
|
||||||
? variableEq(a, ra.rels, b, rb.rels)
|
? variableEq(a, ra.rels, b, rb.rels)
|
||||||
|
@ -150,12 +150,12 @@ RelsOrRelas<ELFT> InputSectionBase::relsOrRelas(bool supportsCrel) const {
|
|||||||
InputSectionBase *const &relSec = f->getSections()[relSecIdx];
|
InputSectionBase *const &relSec = f->getSections()[relSecIdx];
|
||||||
// Otherwise, allocate a buffer to hold the decoded RELA relocations. When
|
// Otherwise, allocate a buffer to hold the decoded RELA relocations. When
|
||||||
// called for the first time, relSec is null (without --emit-relocs) or an
|
// called for the first time, relSec is null (without --emit-relocs) or an
|
||||||
// InputSection with zero eqClass[0].
|
// InputSection with false decodedCrel.
|
||||||
if (!relSec || !cast<InputSection>(relSec)->eqClass[0]) {
|
if (!relSec || !cast<InputSection>(relSec)->decodedCrel) {
|
||||||
auto *sec = makeThreadLocal<InputSection>(*f, shdr, name);
|
auto *sec = makeThreadLocal<InputSection>(*f, shdr, name);
|
||||||
f->cacheDecodedCrel(relSecIdx, sec);
|
f->cacheDecodedCrel(relSecIdx, sec);
|
||||||
sec->type = SHT_RELA;
|
sec->type = SHT_RELA;
|
||||||
sec->eqClass[0] = SHT_RELA;
|
sec->decodedCrel = true;
|
||||||
|
|
||||||
RelocsCrel<ELFT::Is64Bits> entries(sec->content_);
|
RelocsCrel<ELFT::Is64Bits> entries(sec->content_);
|
||||||
sec->size = entries.size() * sizeof(typename ELFT::Rela);
|
sec->size = entries.size() * sizeof(typename ELFT::Rela);
|
||||||
|
@ -176,6 +176,10 @@ class InputSectionBase : public SectionBase {
|
|||||||
|
|
||||||
mutable bool compressed = false;
|
mutable bool compressed = false;
|
||||||
|
|
||||||
|
// Whether this section is SHT_CREL and has been decoded to RELA by
|
||||||
|
// relsOrRelas.
|
||||||
|
bool decodedCrel = false;
|
||||||
|
|
||||||
// Whether the section needs to be padded with a NOP filler due to
|
// Whether the section needs to be padded with a NOP filler due to
|
||||||
// deleteFallThruJmpInsn.
|
// deleteFallThruJmpInsn.
|
||||||
bool nopFiller = false;
|
bool nopFiller = false;
|
||||||
|
@ -320,7 +320,7 @@ class AAResults {
|
|||||||
public:
|
public:
|
||||||
// Make these results default constructable and movable. We have to spell
|
// Make these results default constructable and movable. We have to spell
|
||||||
// these out because MSVC won't synthesize them.
|
// these out because MSVC won't synthesize them.
|
||||||
AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {}
|
AAResults(const TargetLibraryInfo &TLI);
|
||||||
AAResults(AAResults &&Arg);
|
AAResults(AAResults &&Arg);
|
||||||
~AAResults();
|
~AAResults();
|
||||||
|
|
||||||
|
@ -73,6 +73,8 @@ static cl::opt<bool> EnableAATrace("aa-trace", cl::Hidden, cl::init(false));
|
|||||||
static const bool EnableAATrace = false;
|
static const bool EnableAATrace = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
AAResults::AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {}
|
||||||
|
|
||||||
AAResults::AAResults(AAResults &&Arg)
|
AAResults::AAResults(AAResults &&Arg)
|
||||||
: TLI(Arg.TLI), AAs(std::move(Arg.AAs)), AADeps(std::move(Arg.AADeps)) {}
|
: TLI(Arg.TLI), AAs(std::move(Arg.AAs)), AADeps(std::move(Arg.AADeps)) {}
|
||||||
|
|
||||||
|
@ -272,6 +272,7 @@ bool InitUndef::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
for (auto *DeadMI : DeadInsts)
|
for (auto *DeadMI : DeadInsts)
|
||||||
DeadMI->eraseFromParent();
|
DeadMI->eraseFromParent();
|
||||||
DeadInsts.clear();
|
DeadInsts.clear();
|
||||||
|
NewRegs.clear();
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
@ -191,6 +191,11 @@ namespace {
|
|||||||
// AA - Used for DAG load/store alias analysis.
|
// AA - Used for DAG load/store alias analysis.
|
||||||
AliasAnalysis *AA;
|
AliasAnalysis *AA;
|
||||||
|
|
||||||
|
/// This caches all chains that have already been processed in
|
||||||
|
/// DAGCombiner::getStoreMergeCandidates() and found to have no mergeable
|
||||||
|
/// stores candidates.
|
||||||
|
SmallPtrSet<SDNode *, 4> ChainsWithoutMergeableStores;
|
||||||
|
|
||||||
/// When an instruction is simplified, add all users of the instruction to
|
/// When an instruction is simplified, add all users of the instruction to
|
||||||
/// the work lists because they might get more simplified now.
|
/// the work lists because they might get more simplified now.
|
||||||
void AddUsersToWorklist(SDNode *N) {
|
void AddUsersToWorklist(SDNode *N) {
|
||||||
@ -776,11 +781,10 @@ namespace {
|
|||||||
bool UseTrunc);
|
bool UseTrunc);
|
||||||
|
|
||||||
/// This is a helper function for mergeConsecutiveStores. Stores that
|
/// This is a helper function for mergeConsecutiveStores. Stores that
|
||||||
/// potentially may be merged with St are placed in StoreNodes. RootNode is
|
/// potentially may be merged with St are placed in StoreNodes. On success,
|
||||||
/// a chain predecessor to all store candidates.
|
/// returns a chain predecessor to all store candidates.
|
||||||
void getStoreMergeCandidates(StoreSDNode *St,
|
SDNode *getStoreMergeCandidates(StoreSDNode *St,
|
||||||
SmallVectorImpl<MemOpLink> &StoreNodes,
|
SmallVectorImpl<MemOpLink> &StoreNodes);
|
||||||
SDNode *&Root);
|
|
||||||
|
|
||||||
/// Helper function for mergeConsecutiveStores. Checks if candidate stores
|
/// Helper function for mergeConsecutiveStores. Checks if candidate stores
|
||||||
/// have indirect dependency through their operands. RootNode is the
|
/// have indirect dependency through their operands. RootNode is the
|
||||||
@ -1782,6 +1786,9 @@ void DAGCombiner::Run(CombineLevel AtLevel) {
|
|||||||
|
|
||||||
++NodesCombined;
|
++NodesCombined;
|
||||||
|
|
||||||
|
// Invalidate cached info.
|
||||||
|
ChainsWithoutMergeableStores.clear();
|
||||||
|
|
||||||
// If we get back the same node we passed in, rather than a new node or
|
// If we get back the same node we passed in, rather than a new node or
|
||||||
// zero, we know that the node must have defined multiple values and
|
// zero, we know that the node must have defined multiple values and
|
||||||
// CombineTo was used. Since CombineTo takes care of the worklist
|
// CombineTo was used. Since CombineTo takes care of the worklist
|
||||||
@ -20372,15 +20379,15 @@ bool DAGCombiner::mergeStoresOfConstantsOrVecElts(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAGCombiner::getStoreMergeCandidates(
|
SDNode *
|
||||||
StoreSDNode *St, SmallVectorImpl<MemOpLink> &StoreNodes,
|
DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
|
||||||
SDNode *&RootNode) {
|
SmallVectorImpl<MemOpLink> &StoreNodes) {
|
||||||
// This holds the base pointer, index, and the offset in bytes from the base
|
// This holds the base pointer, index, and the offset in bytes from the base
|
||||||
// pointer. We must have a base and an offset. Do not handle stores to undef
|
// pointer. We must have a base and an offset. Do not handle stores to undef
|
||||||
// base pointers.
|
// base pointers.
|
||||||
BaseIndexOffset BasePtr = BaseIndexOffset::match(St, DAG);
|
BaseIndexOffset BasePtr = BaseIndexOffset::match(St, DAG);
|
||||||
if (!BasePtr.getBase().getNode() || BasePtr.getBase().isUndef())
|
if (!BasePtr.getBase().getNode() || BasePtr.getBase().isUndef())
|
||||||
return;
|
return nullptr;
|
||||||
|
|
||||||
SDValue Val = peekThroughBitcasts(St->getValue());
|
SDValue Val = peekThroughBitcasts(St->getValue());
|
||||||
StoreSource StoreSrc = getStoreSource(Val);
|
StoreSource StoreSrc = getStoreSource(Val);
|
||||||
@ -20396,14 +20403,14 @@ void DAGCombiner::getStoreMergeCandidates(
|
|||||||
LoadVT = Ld->getMemoryVT();
|
LoadVT = Ld->getMemoryVT();
|
||||||
// Load and store should be the same type.
|
// Load and store should be the same type.
|
||||||
if (MemVT != LoadVT)
|
if (MemVT != LoadVT)
|
||||||
return;
|
return nullptr;
|
||||||
// Loads must only have one use.
|
// Loads must only have one use.
|
||||||
if (!Ld->hasNUsesOfValue(1, 0))
|
if (!Ld->hasNUsesOfValue(1, 0))
|
||||||
return;
|
return nullptr;
|
||||||
// The memory operands must not be volatile/indexed/atomic.
|
// The memory operands must not be volatile/indexed/atomic.
|
||||||
// TODO: May be able to relax for unordered atomics (see D66309)
|
// TODO: May be able to relax for unordered atomics (see D66309)
|
||||||
if (!Ld->isSimple() || Ld->isIndexed())
|
if (!Ld->isSimple() || Ld->isIndexed())
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto CandidateMatch = [&](StoreSDNode *Other, BaseIndexOffset &Ptr,
|
auto CandidateMatch = [&](StoreSDNode *Other, BaseIndexOffset &Ptr,
|
||||||
int64_t &Offset) -> bool {
|
int64_t &Offset) -> bool {
|
||||||
@ -20471,6 +20478,27 @@ void DAGCombiner::getStoreMergeCandidates(
|
|||||||
return (BasePtr.equalBaseIndex(Ptr, DAG, Offset));
|
return (BasePtr.equalBaseIndex(Ptr, DAG, Offset));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We are looking for a root node which is an ancestor to all mergable
|
||||||
|
// stores. We search up through a load, to our root and then down
|
||||||
|
// through all children. For instance we will find Store{1,2,3} if
|
||||||
|
// St is Store1, Store2. or Store3 where the root is not a load
|
||||||
|
// which always true for nonvolatile ops. TODO: Expand
|
||||||
|
// the search to find all valid candidates through multiple layers of loads.
|
||||||
|
//
|
||||||
|
// Root
|
||||||
|
// |-------|-------|
|
||||||
|
// Load Load Store3
|
||||||
|
// | |
|
||||||
|
// Store1 Store2
|
||||||
|
//
|
||||||
|
// FIXME: We should be able to climb and
|
||||||
|
// descend TokenFactors to find candidates as well.
|
||||||
|
|
||||||
|
SDNode *RootNode = St->getChain().getNode();
|
||||||
|
// Bail out if we already analyzed this root node and found nothing.
|
||||||
|
if (ChainsWithoutMergeableStores.contains(RootNode))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// Check if the pair of StoreNode and the RootNode already bail out many
|
// Check if the pair of StoreNode and the RootNode already bail out many
|
||||||
// times which is over the limit in dependence check.
|
// times which is over the limit in dependence check.
|
||||||
auto OverLimitInDependenceCheck = [&](SDNode *StoreNode,
|
auto OverLimitInDependenceCheck = [&](SDNode *StoreNode,
|
||||||
@ -20494,28 +20522,13 @@ void DAGCombiner::getStoreMergeCandidates(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// We looking for a root node which is an ancestor to all mergable
|
|
||||||
// stores. We search up through a load, to our root and then down
|
|
||||||
// through all children. For instance we will find Store{1,2,3} if
|
|
||||||
// St is Store1, Store2. or Store3 where the root is not a load
|
|
||||||
// which always true for nonvolatile ops. TODO: Expand
|
|
||||||
// the search to find all valid candidates through multiple layers of loads.
|
|
||||||
//
|
|
||||||
// Root
|
|
||||||
// |-------|-------|
|
|
||||||
// Load Load Store3
|
|
||||||
// | |
|
|
||||||
// Store1 Store2
|
|
||||||
//
|
|
||||||
// FIXME: We should be able to climb and
|
|
||||||
// descend TokenFactors to find candidates as well.
|
|
||||||
|
|
||||||
RootNode = St->getChain().getNode();
|
|
||||||
|
|
||||||
unsigned NumNodesExplored = 0;
|
unsigned NumNodesExplored = 0;
|
||||||
const unsigned MaxSearchNodes = 1024;
|
const unsigned MaxSearchNodes = 1024;
|
||||||
if (auto *Ldn = dyn_cast<LoadSDNode>(RootNode)) {
|
if (auto *Ldn = dyn_cast<LoadSDNode>(RootNode)) {
|
||||||
RootNode = Ldn->getChain().getNode();
|
RootNode = Ldn->getChain().getNode();
|
||||||
|
// Bail out if we already analyzed this root node and found nothing.
|
||||||
|
if (ChainsWithoutMergeableStores.contains(RootNode))
|
||||||
|
return nullptr;
|
||||||
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
|
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
|
||||||
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored) {
|
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored) {
|
||||||
if (I.getOperandNo() == 0 && isa<LoadSDNode>(*I)) { // walk down chain
|
if (I.getOperandNo() == 0 && isa<LoadSDNode>(*I)) { // walk down chain
|
||||||
@ -20532,6 +20545,8 @@ void DAGCombiner::getStoreMergeCandidates(
|
|||||||
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored)
|
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored)
|
||||||
TryToAddCandidate(I);
|
TryToAddCandidate(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return RootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to check that merging these stores does not cause a loop in the
|
// We need to check that merging these stores does not cause a loop in the
|
||||||
@ -21162,9 +21177,8 @@ bool DAGCombiner::mergeConsecutiveStores(StoreSDNode *St) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
SmallVector<MemOpLink, 8> StoreNodes;
|
SmallVector<MemOpLink, 8> StoreNodes;
|
||||||
SDNode *RootNode;
|
|
||||||
// Find potential store merge candidates by searching through chain sub-DAG
|
// Find potential store merge candidates by searching through chain sub-DAG
|
||||||
getStoreMergeCandidates(St, StoreNodes, RootNode);
|
SDNode *RootNode = getStoreMergeCandidates(St, StoreNodes);
|
||||||
|
|
||||||
// Check if there is anything to merge.
|
// Check if there is anything to merge.
|
||||||
if (StoreNodes.size() < 2)
|
if (StoreNodes.size() < 2)
|
||||||
@ -21220,6 +21234,11 @@ bool DAGCombiner::mergeConsecutiveStores(StoreSDNode *St) {
|
|||||||
llvm_unreachable("Unhandled store source type");
|
llvm_unreachable("Unhandled store source type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remember if we failed to optimize, to save compile time.
|
||||||
|
if (!MadeChange)
|
||||||
|
ChainsWithoutMergeableStores.insert(RootNode);
|
||||||
|
|
||||||
return MadeChange;
|
return MadeChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2190,7 +2190,8 @@ void SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node,
|
|||||||
Results.push_back(Tmp.first);
|
Results.push_back(Tmp.first);
|
||||||
Results.push_back(Tmp.second);
|
Results.push_back(Tmp.second);
|
||||||
} else {
|
} else {
|
||||||
SDValue Tmp = ExpandLibCall(LC, Node, false).first;
|
bool IsSignedArgument = Node->getOpcode() == ISD::FLDEXP;
|
||||||
|
SDValue Tmp = ExpandLibCall(LC, Node, IsSignedArgument).first;
|
||||||
Results.push_back(Tmp);
|
Results.push_back(Tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3592,6 +3592,21 @@ ExecutionSession::IL_failSymbols(JITDylib &JD,
|
|||||||
assert(MI.DefiningEDU->Symbols.count(NonOwningSymbolStringPtr(Name)) &&
|
assert(MI.DefiningEDU->Symbols.count(NonOwningSymbolStringPtr(Name)) &&
|
||||||
"Symbol does not appear in its DefiningEDU");
|
"Symbol does not appear in its DefiningEDU");
|
||||||
MI.DefiningEDU->Symbols.erase(NonOwningSymbolStringPtr(Name));
|
MI.DefiningEDU->Symbols.erase(NonOwningSymbolStringPtr(Name));
|
||||||
|
|
||||||
|
// Remove this EDU from the dependants lists of its dependencies.
|
||||||
|
for (auto &[DepJD, DepSyms] : MI.DefiningEDU->Dependencies) {
|
||||||
|
for (auto DepSym : DepSyms) {
|
||||||
|
assert(DepJD->Symbols.count(SymbolStringPtr(DepSym)) &&
|
||||||
|
"DepSym not in DepJD");
|
||||||
|
assert(DepJD->MaterializingInfos.count(SymbolStringPtr(DepSym)) &&
|
||||||
|
"DepSym has not MaterializingInfo");
|
||||||
|
auto &SymMI = DepJD->MaterializingInfos[SymbolStringPtr(DepSym)];
|
||||||
|
assert(SymMI.DependantEDUs.count(MI.DefiningEDU.get()) &&
|
||||||
|
"DefiningEDU missing from DependantEDUs list of dependency");
|
||||||
|
SymMI.DependantEDUs.erase(MI.DefiningEDU.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MI.DefiningEDU = nullptr;
|
MI.DefiningEDU = nullptr;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise if there are any EDUs waiting on this symbol then move
|
// Otherwise if there are any EDUs waiting on this symbol then move
|
||||||
|
@ -1911,7 +1911,7 @@ bool AMDGPUDAGToDAGISel::SelectScratchSAddr(SDNode *Parent, SDValue Addr,
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Offset = CurDAG->getTargetConstant(COffsetVal, DL, MVT::i16);
|
Offset = CurDAG->getTargetConstant(COffsetVal, DL, MVT::i32);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1967,7 +1967,7 @@ bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(SDNode *N, SDValue Addr,
|
|||||||
return false;
|
return false;
|
||||||
if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
|
if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
|
||||||
return false;
|
return false;
|
||||||
Offset = CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i16);
|
Offset = CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2000,7 +2000,7 @@ bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(SDNode *N, SDValue Addr,
|
|||||||
if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
|
if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
|
||||||
return false;
|
return false;
|
||||||
SAddr = SelectSAddrFI(CurDAG, SAddr);
|
SAddr = SelectSAddrFI(CurDAG, SAddr);
|
||||||
Offset = CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i16);
|
Offset = CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i32);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,8 +122,13 @@ bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
|
|||||||
// offset allowed.
|
// offset allowed.
|
||||||
MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
|
MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
|
||||||
|
|
||||||
// We only accept offsets that fit in 6 bits (unsigned).
|
// We only accept offsets that fit in 6 bits (unsigned), with the exception
|
||||||
if (isUInt<6>(RHSC) && (VT == MVT::i8 || VT == MVT::i16)) {
|
// of 16-bit loads - those can only go up to 62, because we desugar them
|
||||||
|
// into a pair of 8-bit loads like `ldd rx, RHSC` + `ldd ry, RHSC + 1`.
|
||||||
|
bool OkI8 = VT == MVT::i8 && RHSC <= 63;
|
||||||
|
bool OkI16 = VT == MVT::i16 && RHSC <= 62;
|
||||||
|
|
||||||
|
if (OkI8 || OkI16) {
|
||||||
Base = N.getOperand(0);
|
Base = N.getOperand(0);
|
||||||
Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
|
Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
|
||||||
|
|
||||||
|
@ -295,6 +295,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
|
|||||||
setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
|
setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
|
||||||
setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
|
setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
|
||||||
setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
|
setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
|
||||||
|
setOperationAction(ISD::CONCAT_VECTORS, VT, Legal);
|
||||||
|
|
||||||
setOperationAction(ISD::SETCC, VT, Legal);
|
setOperationAction(ISD::SETCC, VT, Legal);
|
||||||
setOperationAction(ISD::VSELECT, VT, Legal);
|
setOperationAction(ISD::VSELECT, VT, Legal);
|
||||||
@ -5600,8 +5601,9 @@ bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
|
|||||||
|
|
||||||
// On LA64, atomic store operations with IntegerBitWidth of 32 and 64 do not
|
// On LA64, atomic store operations with IntegerBitWidth of 32 and 64 do not
|
||||||
// require fences beacuse we can use amswap_db.[w/d].
|
// require fences beacuse we can use amswap_db.[w/d].
|
||||||
if (isa<StoreInst>(I)) {
|
Type *Ty = I->getOperand(0)->getType();
|
||||||
unsigned Size = I->getOperand(0)->getType()->getIntegerBitWidth();
|
if (isa<StoreInst>(I) && Ty->isIntegerTy()) {
|
||||||
|
unsigned Size = Ty->getIntegerBitWidth();
|
||||||
return (Size == 8 || Size == 16);
|
return (Size == 8 || Size == 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1065,10 +1065,13 @@ def RDTIME_D : RDTIME_2R<0x00006800>;
|
|||||||
|
|
||||||
/// Generic pattern classes
|
/// Generic pattern classes
|
||||||
|
|
||||||
|
def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{
|
||||||
|
return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);
|
||||||
|
}]>;
|
||||||
class PatGprGpr<SDPatternOperator OpNode, LAInst Inst>
|
class PatGprGpr<SDPatternOperator OpNode, LAInst Inst>
|
||||||
: Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>;
|
: Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>;
|
||||||
class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst>
|
class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst>
|
||||||
: Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>;
|
: Pat<(sext_inreg (OpNode (assertsexti32 GPR:$rj), (assertsexti32 GPR:$rk)), i32), (Inst GPR:$rj, GPR:$rk)>;
|
||||||
class PatGpr<SDPatternOperator OpNode, LAInst Inst>
|
class PatGpr<SDPatternOperator OpNode, LAInst Inst>
|
||||||
: Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>;
|
: Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>;
|
||||||
|
|
||||||
|
@ -1789,6 +1789,12 @@ def : Pat<(v4i32 (fp_to_uint (v4f64 LASX256:$vj))),
|
|||||||
v4f64:$vj)),
|
v4f64:$vj)),
|
||||||
sub_128)>;
|
sub_128)>;
|
||||||
|
|
||||||
|
// XVPERMI_Q
|
||||||
|
foreach vt = [v32i8, v16i16, v8i32, v4i64, v8f32, v4f64] in
|
||||||
|
def : Pat<(vt (concat_vectors LSX128:$vd, LSX128:$vj)),
|
||||||
|
(XVPERMI_Q (SUBREG_TO_REG (i64 0), LSX128:$vd, sub_128),
|
||||||
|
(SUBREG_TO_REG (i64 0), LSX128:$vj, sub_128), 2)>;
|
||||||
|
|
||||||
} // Predicates = [HasExtLASX]
|
} // Predicates = [HasExtLASX]
|
||||||
|
|
||||||
/// Intrinsic pattern
|
/// Intrinsic pattern
|
||||||
|
@ -637,6 +637,19 @@ static bool isSignExtendedW(Register SrcReg, const LoongArchSubtarget &ST,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
// If all incoming values are sign-extended and all users only use
|
||||||
|
// the lower 32 bits, then convert them to W versions.
|
||||||
|
case LoongArch::DIV_D: {
|
||||||
|
if (!AddRegToWorkList(MI->getOperand(1).getReg()))
|
||||||
|
return false;
|
||||||
|
if (!AddRegToWorkList(MI->getOperand(2).getReg()))
|
||||||
|
return false;
|
||||||
|
if (hasAllWUsers(*MI, ST, MRI)) {
|
||||||
|
FixableDef.insert(MI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,6 +664,8 @@ static unsigned getWOp(unsigned Opcode) {
|
|||||||
return LoongArch::ADDI_W;
|
return LoongArch::ADDI_W;
|
||||||
case LoongArch::ADD_D:
|
case LoongArch::ADD_D:
|
||||||
return LoongArch::ADD_W;
|
return LoongArch::ADD_W;
|
||||||
|
case LoongArch::DIV_D:
|
||||||
|
return LoongArch::DIV_W;
|
||||||
case LoongArch::LD_D:
|
case LoongArch::LD_D:
|
||||||
case LoongArch::LD_WU:
|
case LoongArch::LD_WU:
|
||||||
return LoongArch::LD_W;
|
return LoongArch::LD_W;
|
||||||
|
@ -2707,7 +2707,8 @@ bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {
|
|||||||
bool MaybeDirectBranchDest = true;
|
bool MaybeDirectBranchDest = true;
|
||||||
|
|
||||||
if (Parser.isParsingMasm()) {
|
if (Parser.isParsingMasm()) {
|
||||||
if (is64BitMode() && SM.getElementSize() > 0) {
|
if (is64BitMode() &&
|
||||||
|
((PtrInOperand && !IndexReg) || SM.getElementSize() > 0)) {
|
||||||
DefaultBaseReg = X86::RIP;
|
DefaultBaseReg = X86::RIP;
|
||||||
}
|
}
|
||||||
if (IsUnconditionalBranch) {
|
if (IsUnconditionalBranch) {
|
||||||
|
@ -3415,7 +3415,7 @@ unsigned X86TargetLowering::preferedOpcodeForCmpEqPiecesOfOperand(
|
|||||||
|
|
||||||
// We prefer rotate for vectors of if we won't get a zext mask with SRL
|
// We prefer rotate for vectors of if we won't get a zext mask with SRL
|
||||||
// (PreferRotate will be set in the latter case).
|
// (PreferRotate will be set in the latter case).
|
||||||
if (PreferRotate || VT.isVector())
|
if (PreferRotate || !MayTransformRotate || VT.isVector())
|
||||||
return ShiftOpc;
|
return ShiftOpc;
|
||||||
|
|
||||||
// Non-vector type and we have a zext mask with SRL.
|
// Non-vector type and we have a zext mask with SRL.
|
||||||
|
@ -2625,11 +2625,11 @@ multiclass avx512_mask_mov<bits<8> opc_kk, bits<8> opc_km, bits<8> opc_mk,
|
|||||||
def km#Suffix : I<opc_km, MRMSrcMem, (outs KRC:$dst), (ins x86memop:$src),
|
def km#Suffix : I<opc_km, MRMSrcMem, (outs KRC:$dst), (ins x86memop:$src),
|
||||||
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
||||||
[(set KRC:$dst, (vvt (load addr:$src)))]>,
|
[(set KRC:$dst, (vvt (load addr:$src)))]>,
|
||||||
Sched<[WriteLoad]>;
|
Sched<[WriteLoad]>, NoCD8;
|
||||||
def mk#Suffix : I<opc_mk, MRMDestMem, (outs), (ins x86memop:$dst, KRC:$src),
|
def mk#Suffix : I<opc_mk, MRMDestMem, (outs), (ins x86memop:$dst, KRC:$src),
|
||||||
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
||||||
[(store KRC:$src, addr:$dst)]>,
|
[(store KRC:$src, addr:$dst)]>,
|
||||||
Sched<[WriteStore]>;
|
Sched<[WriteStore]>, NoCD8;
|
||||||
}
|
}
|
||||||
|
|
||||||
multiclass avx512_mask_mov_gpr<bits<8> opc_kr, bits<8> opc_rk,
|
multiclass avx512_mask_mov_gpr<bits<8> opc_kr, bits<8> opc_rk,
|
||||||
|
@ -1349,7 +1349,8 @@ static bool MayContainThrowingOrExitingCallAfterCB(CallBase *Begin,
|
|||||||
// Add attributes from CB params and Fn attributes that can always be propagated
|
// Add attributes from CB params and Fn attributes that can always be propagated
|
||||||
// to the corresponding argument / inner callbases.
|
// to the corresponding argument / inner callbases.
|
||||||
static void AddParamAndFnBasicAttributes(const CallBase &CB,
|
static void AddParamAndFnBasicAttributes(const CallBase &CB,
|
||||||
ValueToValueMapTy &VMap) {
|
ValueToValueMapTy &VMap,
|
||||||
|
ClonedCodeInfo &InlinedFunctionInfo) {
|
||||||
auto *CalledFunction = CB.getCalledFunction();
|
auto *CalledFunction = CB.getCalledFunction();
|
||||||
auto &Context = CalledFunction->getContext();
|
auto &Context = CalledFunction->getContext();
|
||||||
|
|
||||||
@ -1380,6 +1381,11 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
|
|||||||
auto *NewInnerCB = dyn_cast_or_null<CallBase>(VMap.lookup(InnerCB));
|
auto *NewInnerCB = dyn_cast_or_null<CallBase>(VMap.lookup(InnerCB));
|
||||||
if (!NewInnerCB)
|
if (!NewInnerCB)
|
||||||
continue;
|
continue;
|
||||||
|
// The InnerCB might have be simplified during the inlining
|
||||||
|
// process which can make propagation incorrect.
|
||||||
|
if (InlinedFunctionInfo.isSimplified(InnerCB, NewInnerCB))
|
||||||
|
continue;
|
||||||
|
|
||||||
AttributeList AL = NewInnerCB->getAttributes();
|
AttributeList AL = NewInnerCB->getAttributes();
|
||||||
for (unsigned I = 0, E = InnerCB->arg_size(); I < E; ++I) {
|
for (unsigned I = 0, E = InnerCB->arg_size(); I < E; ++I) {
|
||||||
// Check if the underlying value for the parameter is an argument.
|
// Check if the underlying value for the parameter is an argument.
|
||||||
@ -1455,7 +1461,8 @@ static AttrBuilder IdentifyValidPoisonGeneratingAttributes(CallBase &CB) {
|
|||||||
return Valid;
|
return Valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap) {
|
static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap,
|
||||||
|
ClonedCodeInfo &InlinedFunctionInfo) {
|
||||||
AttrBuilder ValidUB = IdentifyValidUBGeneratingAttributes(CB);
|
AttrBuilder ValidUB = IdentifyValidUBGeneratingAttributes(CB);
|
||||||
AttrBuilder ValidPG = IdentifyValidPoisonGeneratingAttributes(CB);
|
AttrBuilder ValidPG = IdentifyValidPoisonGeneratingAttributes(CB);
|
||||||
if (!ValidUB.hasAttributes() && !ValidPG.hasAttributes())
|
if (!ValidUB.hasAttributes() && !ValidPG.hasAttributes())
|
||||||
@ -1474,6 +1481,11 @@ static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap) {
|
|||||||
auto *NewRetVal = dyn_cast_or_null<CallBase>(VMap.lookup(RetVal));
|
auto *NewRetVal = dyn_cast_or_null<CallBase>(VMap.lookup(RetVal));
|
||||||
if (!NewRetVal)
|
if (!NewRetVal)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// The RetVal might have be simplified during the inlining
|
||||||
|
// process which can make propagation incorrect.
|
||||||
|
if (InlinedFunctionInfo.isSimplified(RetVal, NewRetVal))
|
||||||
|
continue;
|
||||||
// Backward propagation of attributes to the returned value may be incorrect
|
// Backward propagation of attributes to the returned value may be incorrect
|
||||||
// if it is control flow dependent.
|
// if it is control flow dependent.
|
||||||
// Consider:
|
// Consider:
|
||||||
@ -2456,11 +2468,11 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
|
|||||||
|
|
||||||
// Clone return attributes on the callsite into the calls within the inlined
|
// Clone return attributes on the callsite into the calls within the inlined
|
||||||
// function which feed into its return value.
|
// function which feed into its return value.
|
||||||
AddReturnAttributes(CB, VMap);
|
AddReturnAttributes(CB, VMap, InlinedFunctionInfo);
|
||||||
|
|
||||||
// Clone attributes on the params of the callsite to calls within the
|
// Clone attributes on the params of the callsite to calls within the
|
||||||
// inlined function which use the same param.
|
// inlined function which use the same param.
|
||||||
AddParamAndFnBasicAttributes(CB, VMap);
|
AddParamAndFnBasicAttributes(CB, VMap, InlinedFunctionInfo);
|
||||||
|
|
||||||
propagateMemProfMetadata(CalledFunc, CB,
|
propagateMemProfMetadata(CalledFunc, CB,
|
||||||
InlinedFunctionInfo.ContainsMemProfMetadata, VMap);
|
InlinedFunctionInfo.ContainsMemProfMetadata, VMap);
|
||||||
|
@ -859,7 +859,7 @@ static void cloneLoopBlocks(
|
|||||||
if (LatchInst && L->contains(LatchInst))
|
if (LatchInst && L->contains(LatchInst))
|
||||||
LatchVal = VMap[LatchVal];
|
LatchVal = VMap[LatchVal];
|
||||||
PHI.addIncoming(LatchVal, cast<BasicBlock>(VMap[Edge.first]));
|
PHI.addIncoming(LatchVal, cast<BasicBlock>(VMap[Edge.first]));
|
||||||
SE.forgetValue(&PHI);
|
SE.forgetLcssaPhiWithNewPredecessor(L, &PHI);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastValueMap is updated with the values for the current loop
|
// LastValueMap is updated with the values for the current loop
|
||||||
|
Loading…
Reference in New Issue
Block a user