Merge llvm-project release/14.x llvmorg-14.0.4-0-g29f1039a7285
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-14.0.4-0-g29f1039a7285, aka 14.0.4 release. PR: 261742 MFC after: 3 days
This commit is contained in:
commit
2a66634d1b
@ -3279,10 +3279,10 @@ OPT_LIST(V)
|
|||||||
/// Return a new OMPTraitInfo object owned by this context.
|
/// Return a new OMPTraitInfo object owned by this context.
|
||||||
OMPTraitInfo &getNewOMPTraitInfo();
|
OMPTraitInfo &getNewOMPTraitInfo();
|
||||||
|
|
||||||
/// Whether a C++ static variable may be externalized.
|
/// Whether a C++ static variable or CUDA/HIP kernel may be externalized.
|
||||||
bool mayExternalizeStaticVar(const Decl *D) const;
|
bool mayExternalizeStaticVar(const Decl *D) const;
|
||||||
|
|
||||||
/// Whether a C++ static variable should be externalized.
|
/// Whether a C++ static variable or CUDA/HIP kernel should be externalized.
|
||||||
bool shouldExternalizeStaticVar(const Decl *D) const;
|
bool shouldExternalizeStaticVar(const Decl *D) const;
|
||||||
|
|
||||||
StringRef getCUIDHash() const;
|
StringRef getCUIDHash() const;
|
||||||
|
@ -8551,12 +8551,11 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
|
|||||||
RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list");
|
RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list");
|
||||||
if (Context->getLangOpts().CPlusPlus) {
|
if (Context->getLangOpts().CPlusPlus) {
|
||||||
// namespace std { struct __va_list {
|
// namespace std { struct __va_list {
|
||||||
NamespaceDecl *NS;
|
auto *NS = NamespaceDecl::Create(
|
||||||
NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
|
const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(),
|
||||||
Context->getTranslationUnitDecl(),
|
/*Inline*/ false, SourceLocation(), SourceLocation(),
|
||||||
/*Inline*/ false, SourceLocation(),
|
&Context->Idents.get("std"),
|
||||||
SourceLocation(), &Context->Idents.get("std"),
|
/*PrevDecl*/ nullptr);
|
||||||
/*PrevDecl*/ nullptr);
|
|
||||||
NS->setImplicit();
|
NS->setImplicit();
|
||||||
VaListTagDecl->setDeclContext(NS);
|
VaListTagDecl->setDeclContext(NS);
|
||||||
}
|
}
|
||||||
@ -12264,14 +12263,18 @@ bool ASTContext::mayExternalizeStaticVar(const Decl *D) const {
|
|||||||
(D->hasAttr<CUDAConstantAttr>() &&
|
(D->hasAttr<CUDAConstantAttr>() &&
|
||||||
!D->getAttr<CUDAConstantAttr>()->isImplicit());
|
!D->getAttr<CUDAConstantAttr>()->isImplicit());
|
||||||
// CUDA/HIP: static managed variables need to be externalized since it is
|
// CUDA/HIP: static managed variables need to be externalized since it is
|
||||||
// a declaration in IR, therefore cannot have internal linkage.
|
// a declaration in IR, therefore cannot have internal linkage. Kernels in
|
||||||
return IsStaticVar &&
|
// anonymous name space needs to be externalized to avoid duplicate symbols.
|
||||||
(D->hasAttr<HIPManagedAttr>() || IsExplicitDeviceVar);
|
return (IsStaticVar &&
|
||||||
|
(D->hasAttr<HIPManagedAttr>() || IsExplicitDeviceVar)) ||
|
||||||
|
(D->hasAttr<CUDAGlobalAttr>() &&
|
||||||
|
basicGVALinkageForFunction(*this, cast<FunctionDecl>(D)) ==
|
||||||
|
GVA_Internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTContext::shouldExternalizeStaticVar(const Decl *D) const {
|
bool ASTContext::shouldExternalizeStaticVar(const Decl *D) const {
|
||||||
return mayExternalizeStaticVar(D) &&
|
return mayExternalizeStaticVar(D) &&
|
||||||
(D->hasAttr<HIPManagedAttr>() ||
|
(D->hasAttr<HIPManagedAttr>() || D->hasAttr<CUDAGlobalAttr>() ||
|
||||||
CUDADeviceVarODRUsedByHost.count(cast<VarDecl>(D)));
|
CUDADeviceVarODRUsedByHost.count(cast<VarDecl>(D)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,65 +40,10 @@ using namespace clang;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// Retrieve the declaration context that should be used when mangling the given
|
|
||||||
/// declaration.
|
|
||||||
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
|
|
||||||
// The ABI assumes that lambda closure types that occur within
|
|
||||||
// default arguments live in the context of the function. However, due to
|
|
||||||
// the way in which Clang parses and creates function declarations, this is
|
|
||||||
// not the case: the lambda closure type ends up living in the context
|
|
||||||
// where the function itself resides, because the function declaration itself
|
|
||||||
// had not yet been created. Fix the context here.
|
|
||||||
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
|
|
||||||
if (RD->isLambda())
|
|
||||||
if (ParmVarDecl *ContextParam
|
|
||||||
= dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
|
|
||||||
return ContextParam->getDeclContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the same check for block literals.
|
|
||||||
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
|
||||||
if (ParmVarDecl *ContextParam
|
|
||||||
= dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
|
|
||||||
return ContextParam->getDeclContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
const DeclContext *DC = D->getDeclContext();
|
|
||||||
if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) ||
|
|
||||||
isa<OMPDeclareMapperDecl>(DC)) {
|
|
||||||
return getEffectiveDeclContext(cast<Decl>(DC));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto *VD = dyn_cast<VarDecl>(D))
|
|
||||||
if (VD->isExternC())
|
|
||||||
return VD->getASTContext().getTranslationUnitDecl();
|
|
||||||
|
|
||||||
if (const auto *FD = dyn_cast<FunctionDecl>(D))
|
|
||||||
if (FD->isExternC())
|
|
||||||
return FD->getASTContext().getTranslationUnitDecl();
|
|
||||||
|
|
||||||
return DC->getRedeclContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
|
|
||||||
return getEffectiveDeclContext(cast<Decl>(DC));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isLocalContainerContext(const DeclContext *DC) {
|
static bool isLocalContainerContext(const DeclContext *DC) {
|
||||||
return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
|
return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const RecordDecl *GetLocalClassDecl(const Decl *D) {
|
|
||||||
const DeclContext *DC = getEffectiveDeclContext(D);
|
|
||||||
while (!DC->isNamespace() && !DC->isTranslationUnit()) {
|
|
||||||
if (isLocalContainerContext(DC))
|
|
||||||
return dyn_cast<RecordDecl>(D);
|
|
||||||
D = cast<Decl>(DC);
|
|
||||||
DC = getEffectiveDeclContext(D);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const FunctionDecl *getStructor(const FunctionDecl *fn) {
|
static const FunctionDecl *getStructor(const FunctionDecl *fn) {
|
||||||
if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
|
if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
|
||||||
return ftd->getTemplatedDecl();
|
return ftd->getTemplatedDecl();
|
||||||
@ -126,6 +71,7 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
|
|||||||
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
|
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
|
||||||
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
|
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
|
||||||
const DiscriminatorOverrideTy DiscriminatorOverride = nullptr;
|
const DiscriminatorOverrideTy DiscriminatorOverride = nullptr;
|
||||||
|
NamespaceDecl *StdNamespace = nullptr;
|
||||||
|
|
||||||
bool NeedsUniqueInternalLinkageNames = false;
|
bool NeedsUniqueInternalLinkageNames = false;
|
||||||
|
|
||||||
@ -249,6 +195,16 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
|
|||||||
return DiscriminatorOverride;
|
return DiscriminatorOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NamespaceDecl *getStdNamespace();
|
||||||
|
|
||||||
|
const DeclContext *getEffectiveDeclContext(const Decl *D);
|
||||||
|
const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
|
||||||
|
return getEffectiveDeclContext(cast<Decl>(DC));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInternalLinkageDecl(const NamedDecl *ND);
|
||||||
|
const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -427,6 +383,15 @@ class CXXNameMangler {
|
|||||||
|
|
||||||
ASTContext &getASTContext() const { return Context.getASTContext(); }
|
ASTContext &getASTContext() const { return Context.getASTContext(); }
|
||||||
|
|
||||||
|
bool isStd(const NamespaceDecl *NS);
|
||||||
|
bool isStdNamespace(const DeclContext *DC);
|
||||||
|
|
||||||
|
const RecordDecl *GetLocalClassDecl(const Decl *D);
|
||||||
|
const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC);
|
||||||
|
bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A);
|
||||||
|
bool isStdCharSpecialization(const ClassTemplateSpecializationDecl *SD,
|
||||||
|
llvm::StringRef Name, bool HasAllocator);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
|
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
|
||||||
const NamedDecl *D = nullptr, bool NullOut_ = false)
|
const NamedDecl *D = nullptr, bool NullOut_ = false)
|
||||||
@ -628,7 +593,71 @@ class CXXNameMangler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isInternalLinkageDecl(const NamedDecl *ND) {
|
NamespaceDecl *ItaniumMangleContextImpl::getStdNamespace() {
|
||||||
|
if (!StdNamespace) {
|
||||||
|
StdNamespace = NamespaceDecl::Create(
|
||||||
|
getASTContext(), getASTContext().getTranslationUnitDecl(),
|
||||||
|
/*Inline*/ false, SourceLocation(), SourceLocation(),
|
||||||
|
&getASTContext().Idents.get("std"),
|
||||||
|
/*PrevDecl*/ nullptr);
|
||||||
|
StdNamespace->setImplicit();
|
||||||
|
}
|
||||||
|
return StdNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the declaration context that should be used when mangling the given
|
||||||
|
/// declaration.
|
||||||
|
const DeclContext *
|
||||||
|
ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) {
|
||||||
|
// The ABI assumes that lambda closure types that occur within
|
||||||
|
// default arguments live in the context of the function. However, due to
|
||||||
|
// the way in which Clang parses and creates function declarations, this is
|
||||||
|
// not the case: the lambda closure type ends up living in the context
|
||||||
|
// where the function itself resides, because the function declaration itself
|
||||||
|
// had not yet been created. Fix the context here.
|
||||||
|
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
|
||||||
|
if (RD->isLambda())
|
||||||
|
if (ParmVarDecl *ContextParam =
|
||||||
|
dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
|
||||||
|
return ContextParam->getDeclContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the same check for block literals.
|
||||||
|
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
||||||
|
if (ParmVarDecl *ContextParam =
|
||||||
|
dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
|
||||||
|
return ContextParam->getDeclContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// On ARM and AArch64, the va_list tag is always mangled as if in the std
|
||||||
|
// namespace. We do not represent va_list as actually being in the std
|
||||||
|
// namespace in C because this would result in incorrect debug info in C,
|
||||||
|
// among other things. It is important for both languages to have the same
|
||||||
|
// mangling in order for -fsanitize=cfi-icall to work.
|
||||||
|
if (D == getASTContext().getVaListTagDecl()) {
|
||||||
|
const llvm::Triple &T = getASTContext().getTargetInfo().getTriple();
|
||||||
|
if (T.isARM() || T.isThumb() || T.isAArch64())
|
||||||
|
return getStdNamespace();
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeclContext *DC = D->getDeclContext();
|
||||||
|
if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) ||
|
||||||
|
isa<OMPDeclareMapperDecl>(DC)) {
|
||||||
|
return getEffectiveDeclContext(cast<Decl>(DC));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto *VD = dyn_cast<VarDecl>(D))
|
||||||
|
if (VD->isExternC())
|
||||||
|
return getASTContext().getTranslationUnitDecl();
|
||||||
|
|
||||||
|
if (const auto *FD = dyn_cast<FunctionDecl>(D))
|
||||||
|
if (FD->isExternC())
|
||||||
|
return getASTContext().getTranslationUnitDecl();
|
||||||
|
|
||||||
|
return DC->getRedeclContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) {
|
||||||
if (ND && ND->getFormalLinkage() == InternalLinkage &&
|
if (ND && ND->getFormalLinkage() == InternalLinkage &&
|
||||||
!ND->isExternallyVisible() &&
|
!ND->isExternallyVisible() &&
|
||||||
getEffectiveDeclContext(ND)->isFileContext() &&
|
getEffectiveDeclContext(ND)->isFileContext() &&
|
||||||
@ -862,18 +891,9 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) {
|
|||||||
MangleReturnType, FD);
|
MangleReturnType, FD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
|
|
||||||
while (isa<LinkageSpecDecl>(DC)) {
|
|
||||||
DC = getEffectiveParentContext(DC);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return whether a given namespace is the 'std' namespace.
|
/// Return whether a given namespace is the 'std' namespace.
|
||||||
static bool isStd(const NamespaceDecl *NS) {
|
bool CXXNameMangler::isStd(const NamespaceDecl *NS) {
|
||||||
if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
|
if (!Context.getEffectiveParentContext(NS)->isTranslationUnit())
|
||||||
->isTranslationUnit())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
|
const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
|
||||||
@ -882,7 +902,7 @@ static bool isStd(const NamespaceDecl *NS) {
|
|||||||
|
|
||||||
// isStdNamespace - Return whether a given decl context is a toplevel 'std'
|
// isStdNamespace - Return whether a given decl context is a toplevel 'std'
|
||||||
// namespace.
|
// namespace.
|
||||||
static bool isStdNamespace(const DeclContext *DC) {
|
bool CXXNameMangler::isStdNamespace(const DeclContext *DC) {
|
||||||
if (!DC->isNamespace())
|
if (!DC->isNamespace())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -956,6 +976,17 @@ void CXXNameMangler::mangleName(GlobalDecl GD) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RecordDecl *CXXNameMangler::GetLocalClassDecl(const Decl *D) {
|
||||||
|
const DeclContext *DC = Context.getEffectiveDeclContext(D);
|
||||||
|
while (!DC->isNamespace() && !DC->isTranslationUnit()) {
|
||||||
|
if (isLocalContainerContext(DC))
|
||||||
|
return dyn_cast<RecordDecl>(D);
|
||||||
|
D = cast<Decl>(DC);
|
||||||
|
DC = Context.getEffectiveDeclContext(D);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
|
void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
|
||||||
const AbiTagList *AdditionalAbiTags) {
|
const AbiTagList *AdditionalAbiTags) {
|
||||||
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
||||||
@ -964,7 +995,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
|
|||||||
// ::= [<module-name>] <unscoped-template-name> <template-args>
|
// ::= [<module-name>] <unscoped-template-name> <template-args>
|
||||||
// ::= <local-name>
|
// ::= <local-name>
|
||||||
//
|
//
|
||||||
const DeclContext *DC = getEffectiveDeclContext(ND);
|
const DeclContext *DC = Context.getEffectiveDeclContext(ND);
|
||||||
|
|
||||||
// If this is an extern variable declared locally, the relevant DeclContext
|
// If this is an extern variable declared locally, the relevant DeclContext
|
||||||
// is that of the containing namespace, or the translation unit.
|
// is that of the containing namespace, or the translation unit.
|
||||||
@ -972,13 +1003,13 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
|
|||||||
// a proper semantic declaration context!
|
// a proper semantic declaration context!
|
||||||
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
|
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
|
||||||
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
||||||
DC = getEffectiveParentContext(DC);
|
DC = Context.getEffectiveParentContext(DC);
|
||||||
else if (GetLocalClassDecl(ND)) {
|
else if (GetLocalClassDecl(ND)) {
|
||||||
mangleLocalName(GD, AdditionalAbiTags);
|
mangleLocalName(GD, AdditionalAbiTags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DC = IgnoreLinkageSpecDecls(DC);
|
assert(!isa<LinkageSpecDecl>(DC) && "context cannot be LinkageSpecDecl");
|
||||||
|
|
||||||
if (isLocalContainerContext(DC)) {
|
if (isLocalContainerContext(DC)) {
|
||||||
mangleLocalName(GD, AdditionalAbiTags);
|
mangleLocalName(GD, AdditionalAbiTags);
|
||||||
@ -1054,7 +1085,7 @@ void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) {
|
|||||||
void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
|
void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
|
||||||
const TemplateArgument *TemplateArgs,
|
const TemplateArgument *TemplateArgs,
|
||||||
unsigned NumTemplateArgs) {
|
unsigned NumTemplateArgs) {
|
||||||
const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));
|
const DeclContext *DC = Context.getEffectiveDeclContext(TD);
|
||||||
|
|
||||||
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
||||||
mangleUnscopedTemplateName(TD, nullptr);
|
mangleUnscopedTemplateName(TD, nullptr);
|
||||||
@ -1070,7 +1101,7 @@ void CXXNameMangler::mangleUnscopedName(GlobalDecl GD,
|
|||||||
// <unscoped-name> ::= <unqualified-name>
|
// <unscoped-name> ::= <unqualified-name>
|
||||||
// ::= St <unqualified-name> # ::std::
|
// ::= St <unqualified-name> # ::std::
|
||||||
|
|
||||||
if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND))))
|
if (isStdNamespace(Context.getEffectiveDeclContext(ND)))
|
||||||
Out << "St";
|
Out << "St";
|
||||||
|
|
||||||
mangleUnqualifiedName(GD, AdditionalAbiTags);
|
mangleUnqualifiedName(GD, AdditionalAbiTags);
|
||||||
@ -1430,7 +1461,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
|
|||||||
// 12_GLOBAL__N_1 mangling is quite sufficient there, and this better
|
// 12_GLOBAL__N_1 mangling is quite sufficient there, and this better
|
||||||
// matches GCC anyway, because GCC does not treat anonymous namespaces as
|
// matches GCC anyway, because GCC does not treat anonymous namespaces as
|
||||||
// implying internal linkage.
|
// implying internal linkage.
|
||||||
if (isInternalLinkageDecl(ND))
|
if (Context.isInternalLinkageDecl(ND))
|
||||||
Out << 'L';
|
Out << 'L';
|
||||||
|
|
||||||
auto *FD = dyn_cast<FunctionDecl>(ND);
|
auto *FD = dyn_cast<FunctionDecl>(ND);
|
||||||
@ -1745,7 +1776,7 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD,
|
|||||||
// <discriminator> := _ <non-negative number>
|
// <discriminator> := _ <non-negative number>
|
||||||
assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
|
assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
|
||||||
const RecordDecl *RD = GetLocalClassDecl(D);
|
const RecordDecl *RD = GetLocalClassDecl(D);
|
||||||
const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D);
|
const DeclContext *DC = Context.getEffectiveDeclContext(RD ? RD : D);
|
||||||
|
|
||||||
Out << 'Z';
|
Out << 'Z';
|
||||||
|
|
||||||
@ -1798,13 +1829,13 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD,
|
|||||||
if (const NamedDecl *PrefixND = getClosurePrefix(BD))
|
if (const NamedDecl *PrefixND = getClosurePrefix(BD))
|
||||||
mangleClosurePrefix(PrefixND, true /*NoFunction*/);
|
mangleClosurePrefix(PrefixND, true /*NoFunction*/);
|
||||||
else
|
else
|
||||||
manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
|
manglePrefix(Context.getEffectiveDeclContext(BD), true /*NoFunction*/);
|
||||||
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
|
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
|
||||||
mangleUnqualifiedBlock(BD);
|
mangleUnqualifiedBlock(BD);
|
||||||
} else {
|
} else {
|
||||||
const NamedDecl *ND = cast<NamedDecl>(D);
|
const NamedDecl *ND = cast<NamedDecl>(D);
|
||||||
mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags,
|
mangleNestedName(GD, Context.getEffectiveDeclContext(ND),
|
||||||
true /*NoFunction*/);
|
AdditionalAbiTags, true /*NoFunction*/);
|
||||||
}
|
}
|
||||||
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
||||||
// Mangle a block in a default parameter; see above explanation for
|
// Mangle a block in a default parameter; see above explanation for
|
||||||
@ -1843,7 +1874,7 @@ void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) {
|
|||||||
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
|
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const DeclContext *DC = getEffectiveDeclContext(Block);
|
const DeclContext *DC = Context.getEffectiveDeclContext(Block);
|
||||||
if (isLocalContainerContext(DC)) {
|
if (isLocalContainerContext(DC)) {
|
||||||
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
|
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
|
||||||
return;
|
return;
|
||||||
@ -2030,7 +2061,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
|||||||
// ::= # empty
|
// ::= # empty
|
||||||
// ::= <substitution>
|
// ::= <substitution>
|
||||||
|
|
||||||
DC = IgnoreLinkageSpecDecls(DC);
|
assert(!isa<LinkageSpecDecl>(DC) && "prefix cannot be LinkageSpecDecl");
|
||||||
|
|
||||||
if (DC->isTranslationUnit())
|
if (DC->isTranslationUnit())
|
||||||
return;
|
return;
|
||||||
@ -2053,7 +2084,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
|||||||
mangleClosurePrefix(PrefixND, NoFunction);
|
mangleClosurePrefix(PrefixND, NoFunction);
|
||||||
mangleUnqualifiedName(ND, nullptr);
|
mangleUnqualifiedName(ND, nullptr);
|
||||||
} else {
|
} else {
|
||||||
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
|
||||||
mangleUnqualifiedName(ND, nullptr);
|
mangleUnqualifiedName(ND, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2107,7 +2138,7 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD,
|
|||||||
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
|
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
|
||||||
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
|
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
|
||||||
} else {
|
} else {
|
||||||
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
|
||||||
if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND))
|
if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND))
|
||||||
mangleUnqualifiedName(GD, nullptr);
|
mangleUnqualifiedName(GD, nullptr);
|
||||||
else
|
else
|
||||||
@ -2152,7 +2183,7 @@ void CXXNameMangler::mangleClosurePrefix(const NamedDecl *ND, bool NoFunction) {
|
|||||||
mangleTemplatePrefix(TD, NoFunction);
|
mangleTemplatePrefix(TD, NoFunction);
|
||||||
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
|
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
|
||||||
} else {
|
} else {
|
||||||
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
|
||||||
mangleUnqualifiedName(ND, nullptr);
|
mangleUnqualifiedName(ND, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5969,56 +6000,61 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isCharType(QualType T) {
|
/// Returns whether S is a template specialization of std::Name with a single
|
||||||
if (T.isNull())
|
/// argument of type A.
|
||||||
|
bool CXXNameMangler::isSpecializedAs(QualType S, llvm::StringRef Name,
|
||||||
|
QualType A) {
|
||||||
|
if (S.isNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
|
const RecordType *RT = S->getAs<RecordType>();
|
||||||
T->isSpecificBuiltinType(BuiltinType::Char_U);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether a given type is a template specialization of a given name
|
|
||||||
/// with a single argument of type char.
|
|
||||||
static bool isCharSpecialization(QualType T, const char *Name) {
|
|
||||||
if (T.isNull())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const RecordType *RT = T->getAs<RecordType>();
|
|
||||||
if (!RT)
|
if (!RT)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const ClassTemplateSpecializationDecl *SD =
|
const ClassTemplateSpecializationDecl *SD =
|
||||||
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
|
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
|
||||||
if (!SD)
|
if (!SD || !SD->getIdentifier()->isStr(Name))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!isStdNamespace(getEffectiveDeclContext(SD)))
|
if (!isStdNamespace(Context.getEffectiveDeclContext(SD)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
||||||
if (TemplateArgs.size() != 1)
|
if (TemplateArgs.size() != 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!isCharType(TemplateArgs[0].getAsType()))
|
if (TemplateArgs[0].getAsType() != A)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return SD->getIdentifier()->getName() == Name;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t StrLen>
|
/// Returns whether SD is a template specialization std::Name<char,
|
||||||
static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,
|
/// std::char_traits<char> [, std::allocator<char>]>
|
||||||
const char (&Str)[StrLen]) {
|
/// HasAllocator controls whether the 3rd template argument is needed.
|
||||||
if (!SD->getIdentifier()->isStr(Str))
|
bool CXXNameMangler::isStdCharSpecialization(
|
||||||
|
const ClassTemplateSpecializationDecl *SD, llvm::StringRef Name,
|
||||||
|
bool HasAllocator) {
|
||||||
|
if (!SD->getIdentifier()->isStr(Name))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
||||||
if (TemplateArgs.size() != 2)
|
if (TemplateArgs.size() != (HasAllocator ? 3 : 2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!isCharType(TemplateArgs[0].getAsType()))
|
QualType A = TemplateArgs[0].getAsType();
|
||||||
|
if (A.isNull())
|
||||||
|
return false;
|
||||||
|
// Plain 'char' is named Char_S or Char_U depending on the target ABI.
|
||||||
|
if (!A->isSpecificBuiltinType(BuiltinType::Char_S) &&
|
||||||
|
!A->isSpecificBuiltinType(BuiltinType::Char_U))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
|
if (!isSpecializedAs(TemplateArgs[1].getAsType(), "char_traits", A))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (HasAllocator &&
|
||||||
|
!isSpecializedAs(TemplateArgs[2].getAsType(), "allocator", A))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -6031,10 +6067,11 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
|||||||
Out << "St";
|
Out << "St";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
|
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
|
||||||
if (!isStdNamespace(getEffectiveDeclContext(TD)))
|
if (!isStdNamespace(Context.getEffectiveDeclContext(TD)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// <substitution> ::= Sa # ::std::allocator
|
// <substitution> ::= Sa # ::std::allocator
|
||||||
@ -6048,56 +6085,45 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
|||||||
Out << "Sb";
|
Out << "Sb";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const ClassTemplateSpecializationDecl *SD =
|
if (const ClassTemplateSpecializationDecl *SD =
|
||||||
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
||||||
if (!isStdNamespace(getEffectiveDeclContext(SD)))
|
if (!isStdNamespace(Context.getEffectiveDeclContext(SD)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// <substitution> ::= Ss # ::std::basic_string<char,
|
// <substitution> ::= Ss # ::std::basic_string<char,
|
||||||
// ::std::char_traits<char>,
|
// ::std::char_traits<char>,
|
||||||
// ::std::allocator<char> >
|
// ::std::allocator<char> >
|
||||||
if (SD->getIdentifier()->isStr("basic_string")) {
|
if (isStdCharSpecialization(SD, "basic_string", /*HasAllocator=*/true)) {
|
||||||
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
|
||||||
|
|
||||||
if (TemplateArgs.size() != 3)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Out << "Ss";
|
Out << "Ss";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <substitution> ::= Si # ::std::basic_istream<char,
|
// <substitution> ::= Si # ::std::basic_istream<char,
|
||||||
// ::std::char_traits<char> >
|
// ::std::char_traits<char> >
|
||||||
if (isStreamCharSpecialization(SD, "basic_istream")) {
|
if (isStdCharSpecialization(SD, "basic_istream", /*HasAllocator=*/false)) {
|
||||||
Out << "Si";
|
Out << "Si";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <substitution> ::= So # ::std::basic_ostream<char,
|
// <substitution> ::= So # ::std::basic_ostream<char,
|
||||||
// ::std::char_traits<char> >
|
// ::std::char_traits<char> >
|
||||||
if (isStreamCharSpecialization(SD, "basic_ostream")) {
|
if (isStdCharSpecialization(SD, "basic_ostream", /*HasAllocator=*/false)) {
|
||||||
Out << "So";
|
Out << "So";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <substitution> ::= Sd # ::std::basic_iostream<char,
|
// <substitution> ::= Sd # ::std::basic_iostream<char,
|
||||||
// ::std::char_traits<char> >
|
// ::std::char_traits<char> >
|
||||||
if (isStreamCharSpecialization(SD, "basic_iostream")) {
|
if (isStdCharSpecialization(SD, "basic_iostream", /*HasAllocator=*/false)) {
|
||||||
Out << "Sd";
|
Out << "Sd";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1466,8 +1466,7 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
|
|||||||
if (!Policy.SuppressScope)
|
if (!Policy.SuppressScope)
|
||||||
AppendScope(TD->getDeclContext(), OS, TD->getDeclName());
|
AppendScope(TD->getDeclContext(), OS, TD->getDeclName());
|
||||||
|
|
||||||
IdentifierInfo *II = TD->getIdentifier();
|
OS << TD->getName();
|
||||||
OS << II->getName();
|
|
||||||
} else {
|
} else {
|
||||||
T->getTemplateName().print(OS, Policy);
|
T->getTemplateName().print(OS, Policy);
|
||||||
}
|
}
|
||||||
|
@ -69,11 +69,11 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
|
|||||||
// From the glibc documentation, on GNU systems, malloc guarantees 16-byte
|
// From the glibc documentation, on GNU systems, malloc guarantees 16-byte
|
||||||
// alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
|
// alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
|
||||||
// https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html.
|
// https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html.
|
||||||
// This alignment guarantee also applies to Windows and Android. On Darwin,
|
// This alignment guarantee also applies to Windows and Android. On Darwin
|
||||||
// the alignment is 16 bytes on both 64-bit and 32-bit systems.
|
// and OpenBSD, the alignment is 16 bytes on both 64-bit and 32-bit systems.
|
||||||
if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid())
|
if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid())
|
||||||
NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
|
NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
|
||||||
else if (T.isOSDarwin())
|
else if (T.isOSDarwin() || T.isOSOpenBSD())
|
||||||
NewAlign = 128;
|
NewAlign = 128;
|
||||||
else
|
else
|
||||||
NewAlign = 0; // Infer from basic type alignment.
|
NewAlign = 0; // Infer from basic type alignment.
|
||||||
|
@ -287,7 +287,7 @@ std::string CGNVCUDARuntime::getDeviceSideName(const NamedDecl *ND) {
|
|||||||
SmallString<256> Buffer;
|
SmallString<256> Buffer;
|
||||||
llvm::raw_svector_ostream Out(Buffer);
|
llvm::raw_svector_ostream Out(Buffer);
|
||||||
Out << DeviceSideName;
|
Out << DeviceSideName;
|
||||||
CGM.printPostfixForExternalizedStaticVar(Out);
|
CGM.printPostfixForExternalizedDecl(Out, ND);
|
||||||
DeviceSideName = std::string(Out.str());
|
DeviceSideName = std::string(Out.str());
|
||||||
}
|
}
|
||||||
return DeviceSideName;
|
return DeviceSideName;
|
||||||
|
@ -1572,7 +1572,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
|||||||
llvm::Value *allocSize =
|
llvm::Value *allocSize =
|
||||||
EmitCXXNewAllocSize(*this, E, minElements, numElements,
|
EmitCXXNewAllocSize(*this, E, minElements, numElements,
|
||||||
allocSizeWithoutCookie);
|
allocSizeWithoutCookie);
|
||||||
CharUnits allocAlign = getContext().getPreferredTypeAlignInChars(allocType);
|
CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
|
||||||
|
|
||||||
// Emit the allocation call. If the allocator is a global placement
|
// Emit the allocation call. If the allocator is a global placement
|
||||||
// operator, just "inline" it directly.
|
// operator, just "inline" it directly.
|
||||||
|
@ -1367,7 +1367,7 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
|
|||||||
if (CGM.getContext().shouldExternalizeStaticVar(ND) &&
|
if (CGM.getContext().shouldExternalizeStaticVar(ND) &&
|
||||||
CGM.getLangOpts().GPURelocatableDeviceCode &&
|
CGM.getLangOpts().GPURelocatableDeviceCode &&
|
||||||
CGM.getLangOpts().CUDAIsDevice && !CGM.getLangOpts().CUID.empty())
|
CGM.getLangOpts().CUDAIsDevice && !CGM.getLangOpts().CUID.empty())
|
||||||
CGM.printPostfixForExternalizedStaticVar(Out);
|
CGM.printPostfixForExternalizedDecl(Out, ND);
|
||||||
return std::string(Out.str());
|
return std::string(Out.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1455,7 +1455,7 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
|
|||||||
// directly between host- and device-compilations, the host- and
|
// directly between host- and device-compilations, the host- and
|
||||||
// device-mangling in host compilation could help catching certain ones.
|
// device-mangling in host compilation could help catching certain ones.
|
||||||
assert(!isa<FunctionDecl>(ND) || !ND->hasAttr<CUDAGlobalAttr>() ||
|
assert(!isa<FunctionDecl>(ND) || !ND->hasAttr<CUDAGlobalAttr>() ||
|
||||||
getLangOpts().CUDAIsDevice ||
|
getContext().shouldExternalizeStaticVar(ND) || getLangOpts().CUDAIsDevice ||
|
||||||
(getContext().getAuxTargetInfo() &&
|
(getContext().getAuxTargetInfo() &&
|
||||||
(getContext().getAuxTargetInfo()->getCXXABI() !=
|
(getContext().getAuxTargetInfo()->getCXXABI() !=
|
||||||
getContext().getTargetInfo().getCXXABI())) ||
|
getContext().getTargetInfo().getCXXABI())) ||
|
||||||
@ -6645,7 +6645,14 @@ bool CodeGenModule::stopAutoInit() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenModule::printPostfixForExternalizedStaticVar(
|
void CodeGenModule::printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
|
||||||
llvm::raw_ostream &OS) const {
|
const Decl *D) const {
|
||||||
OS << "__static__" << getContext().getCUIDHash();
|
StringRef Tag;
|
||||||
|
// ptxas does not allow '.' in symbol names. On the other hand, HIP prefers
|
||||||
|
// postfix beginning with '.' since the symbol name can be demangled.
|
||||||
|
if (LangOpts.HIP)
|
||||||
|
Tag = (isa<VarDecl>(D) ? ".static." : ".intern.");
|
||||||
|
else
|
||||||
|
Tag = (isa<VarDecl>(D) ? "__static__" : "__intern__");
|
||||||
|
OS << Tag << getContext().getCUIDHash();
|
||||||
}
|
}
|
||||||
|
@ -1447,9 +1447,10 @@ class CodeGenModule : public CodeGenTypeCache {
|
|||||||
TBAAAccessInfo *TBAAInfo = nullptr);
|
TBAAAccessInfo *TBAAInfo = nullptr);
|
||||||
bool stopAutoInit();
|
bool stopAutoInit();
|
||||||
|
|
||||||
/// Print the postfix for externalized static variable for single source
|
/// Print the postfix for externalized static variable or kernels for single
|
||||||
/// offloading languages CUDA and HIP.
|
/// source offloading languages CUDA and HIP.
|
||||||
void printPostfixForExternalizedStaticVar(llvm::raw_ostream &OS) const;
|
void printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
|
||||||
|
const Decl *D) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
llvm::Constant *GetOrCreateLLVMFunction(
|
llvm::Constant *GetOrCreateLLVMFunction(
|
||||||
|
@ -510,7 +510,7 @@ void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CC1Args.push_back("-internal-isystem");
|
CC1Args.push_back("-idirafter");
|
||||||
CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
|
CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
|
||||||
if (UsesRuntimeWrapper)
|
if (UsesRuntimeWrapper)
|
||||||
CC1Args.append({"-include", "__clang_hip_runtime_wrapper.h"});
|
CC1Args.append({"-include", "__clang_hip_runtime_wrapper.h"});
|
||||||
|
@ -85,7 +85,8 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
assert(Output.isNothing() && "Invalid output.");
|
assert(Output.isNothing() && "Invalid output.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
|
||||||
|
options::OPT_r)) {
|
||||||
if (!Args.hasArg(options::OPT_shared)) {
|
if (!Args.hasArg(options::OPT_shared)) {
|
||||||
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
|
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
|
||||||
}
|
}
|
||||||
@ -111,12 +112,15 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
|
|
||||||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
|
||||||
|
|
||||||
if (ToolChain.ShouldLinkCXXStdlib(Args))
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
|
||||||
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
|
options::OPT_r)) {
|
||||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
|
if (ToolChain.ShouldLinkCXXStdlib(Args))
|
||||||
|
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
|
||||||
CmdArgs.push_back("-lc");
|
CmdArgs.push_back("-lc");
|
||||||
|
}
|
||||||
|
|
||||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
|
||||||
|
options::OPT_r)) {
|
||||||
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
|
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
|
||||||
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
|
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
|
||||||
else
|
else
|
||||||
|
@ -661,6 +661,17 @@ void tools::addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
|
||||||
|
const ArgList &Args,
|
||||||
|
ArgStringList &CmdArgs) {
|
||||||
|
// Default to clang lib / lib64 folder, i.e. the same location as device
|
||||||
|
// runtime.
|
||||||
|
SmallString<256> DefaultLibPath =
|
||||||
|
llvm::sys::path::parent_path(TC.getDriver().Dir);
|
||||||
|
llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
|
||||||
|
CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
|
||||||
|
}
|
||||||
|
|
||||||
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
|
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
|
||||||
ArgStringList &CmdArgs) {
|
ArgStringList &CmdArgs) {
|
||||||
// Enable -frtlib-add-rpath by default for the case of VE.
|
// Enable -frtlib-add-rpath by default for the case of VE.
|
||||||
@ -720,6 +731,7 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
|
|||||||
|
|
||||||
if (RTKind == Driver::OMPRT_OMP)
|
if (RTKind == Driver::OMPRT_OMP)
|
||||||
addOpenMPRuntimeSpecificRPath(TC, Args, CmdArgs);
|
addOpenMPRuntimeSpecificRPath(TC, Args, CmdArgs);
|
||||||
|
addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,9 @@ void addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
|
|||||||
llvm::opt::ArgStringList &CmdArgs);
|
llvm::opt::ArgStringList &CmdArgs);
|
||||||
void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
|
void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
|
||||||
llvm::opt::ArgStringList &CmdArgs);
|
llvm::opt::ArgStringList &CmdArgs);
|
||||||
|
void addOpenMPRuntimeLibraryPath(const ToolChain &TC,
|
||||||
|
const llvm::opt::ArgList &Args,
|
||||||
|
llvm::opt::ArgStringList &CmdArgs);
|
||||||
/// Returns true, if an OpenMP runtime has been added.
|
/// Returns true, if an OpenMP runtime has been added.
|
||||||
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
|
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
|
||||||
const llvm::opt::ArgList &Args,
|
const llvm::opt::ArgList &Args,
|
||||||
|
@ -301,18 +301,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
|||||||
|
|
||||||
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
|
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
|
||||||
|
|
||||||
// Similar to the logic for GCC above, if we are currently running Clang
|
// The deprecated -DLLVM_ENABLE_PROJECTS=libcxx configuration installs
|
||||||
// inside of the requested system root, add its parent library path to those
|
// libc++.so in D.Dir+"/../lib/". Detect this path.
|
||||||
// searched.
|
// TODO Remove once LLVM_ENABLE_PROJECTS=libcxx is unsupported.
|
||||||
// FIXME: It's not clear whether we should use the driver's installed
|
if (StringRef(D.Dir).startswith(SysRoot) &&
|
||||||
// directory ('Dir' below) or the ResourceDir.
|
D.getVFS().exists(D.Dir + "/../lib/libc++.so"))
|
||||||
if (StringRef(D.Dir).startswith(SysRoot)) {
|
|
||||||
// Even if OSLibDir != "lib", this is needed for Clang in the build
|
|
||||||
// directory (not installed) to find libc++.
|
|
||||||
addPathIfExists(D, D.Dir + "/../lib", Paths);
|
addPathIfExists(D, D.Dir + "/../lib", Paths);
|
||||||
if (OSLibDir != "lib")
|
|
||||||
addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
addPathIfExists(D, SysRoot + "/lib", Paths);
|
addPathIfExists(D, SysRoot + "/lib", Paths);
|
||||||
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
|
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
|
||||||
|
@ -82,7 +82,8 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
assert(Output.isNothing() && "Invalid output.");
|
assert(Output.isNothing() && "Invalid output.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
|
||||||
|
options::OPT_r)) {
|
||||||
if (!Args.hasArg(options::OPT_shared))
|
if (!Args.hasArg(options::OPT_shared))
|
||||||
CmdArgs.push_back(
|
CmdArgs.push_back(
|
||||||
Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
|
Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
|
||||||
@ -122,7 +123,8 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
|
bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
|
||||||
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
|
||||||
|
|
||||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
|
||||||
|
options::OPT_r)) {
|
||||||
if (getToolChain().ShouldLinkCXXStdlib(Args))
|
if (getToolChain().ShouldLinkCXXStdlib(Args))
|
||||||
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
|
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
|
||||||
if (Args.hasArg(options::OPT_fstack_protector) ||
|
if (Args.hasArg(options::OPT_fstack_protector) ||
|
||||||
@ -149,11 +151,13 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
|
linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
|
||||||
|
options::OPT_r)) {
|
||||||
CmdArgs.push_back(
|
CmdArgs.push_back(
|
||||||
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
|
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
|
||||||
|
CmdArgs.push_back(
|
||||||
|
Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
|
||||||
}
|
}
|
||||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
|
|
||||||
|
|
||||||
getToolChain().addProfileRTLibs(Args, CmdArgs);
|
getToolChain().addProfileRTLibs(Args, CmdArgs);
|
||||||
|
|
||||||
|
@ -45,3 +45,5 @@ intercept setjmp, _ZN14__interception11real_setjmpE
|
|||||||
intercept _setjmp, _ZN14__interception12real__setjmpE
|
intercept _setjmp, _ZN14__interception12real__setjmpE
|
||||||
intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE
|
intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE
|
||||||
intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE
|
intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE
|
||||||
|
|
||||||
|
NO_EXEC_STACK_DIRECTIVE
|
||||||
|
@ -68,8 +68,6 @@ namespace ranges {
|
|||||||
template <range _Rp>
|
template <range _Rp>
|
||||||
using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>;
|
using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>;
|
||||||
|
|
||||||
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
|
||||||
|
|
||||||
// [range.sized]
|
// [range.sized]
|
||||||
template <class _Tp>
|
template <class _Tp>
|
||||||
concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
|
concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
|
||||||
@ -135,8 +133,6 @@ namespace ranges {
|
|||||||
(is_lvalue_reference_v<_Tp> ||
|
(is_lvalue_reference_v<_Tp> ||
|
||||||
(movable<remove_reference_t<_Tp>> && !__is_std_initializer_list<remove_cvref_t<_Tp>>))));
|
(movable<remove_reference_t<_Tp>> && !__is_std_initializer_list<remove_cvref_t<_Tp>>))));
|
||||||
|
|
||||||
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
|
||||||
|
|
||||||
} // namespace ranges
|
} // namespace ranges
|
||||||
|
|
||||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||||
|
|
||||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||||
|
|
||||||
// [range.prim.data]
|
// [range.prim.data]
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ inline namespace __cpo {
|
|||||||
} // namespace __cpo
|
} // namespace __cpo
|
||||||
} // namespace ranges
|
} // namespace ranges
|
||||||
|
|
||||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||||
|
|
||||||
_LIBCPP_END_NAMESPACE_STD
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||||
|
|
||||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||||
|
|
||||||
namespace ranges {
|
namespace ranges {
|
||||||
template<class>
|
template<class>
|
||||||
@ -128,7 +128,7 @@ inline namespace __cpo {
|
|||||||
} // namespace __cpo
|
} // namespace __cpo
|
||||||
} // namespace ranges
|
} // namespace ranges
|
||||||
|
|
||||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||||
|
|
||||||
_LIBCPP_END_NAMESPACE_STD
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
|
@ -256,9 +256,11 @@ void AArch64::writePlt(uint8_t *buf, const Symbol &sym,
|
|||||||
bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
|
bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
|
||||||
uint64_t branchAddr, const Symbol &s,
|
uint64_t branchAddr, const Symbol &s,
|
||||||
int64_t a) const {
|
int64_t a) const {
|
||||||
// If s is an undefined weak symbol and does not have a PLT entry then it
|
// If s is an undefined weak symbol and does not have a PLT entry then it will
|
||||||
// will be resolved as a branch to the next instruction.
|
// be resolved as a branch to the next instruction. If it is hidden, its
|
||||||
if (s.isUndefWeak() && !s.isInPlt())
|
// binding has been converted to local, so we just check isUndefined() here. A
|
||||||
|
// undefined non-weak symbol will have been errored.
|
||||||
|
if (s.isUndefined() && !s.isInPlt())
|
||||||
return false;
|
return false;
|
||||||
// ELF for the ARM 64-bit architecture, section Call and Jump relocations
|
// ELF for the ARM 64-bit architecture, section Call and Jump relocations
|
||||||
// only permits range extension thunks for R_AARCH64_CALL26 and
|
// only permits range extension thunks for R_AARCH64_CALL26 and
|
||||||
|
@ -296,9 +296,11 @@ void ARM::addPltSymbols(InputSection &isec, uint64_t off) const {
|
|||||||
bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
|
bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
|
||||||
uint64_t branchAddr, const Symbol &s,
|
uint64_t branchAddr, const Symbol &s,
|
||||||
int64_t a) const {
|
int64_t a) const {
|
||||||
// If S is an undefined weak symbol and does not have a PLT entry then it
|
// If s is an undefined weak symbol and does not have a PLT entry then it will
|
||||||
// will be resolved as a branch to the next instruction.
|
// be resolved as a branch to the next instruction. If it is hidden, its
|
||||||
if (s.isUndefWeak() && !s.isInPlt())
|
// binding has been converted to local, so we just check isUndefined() here. A
|
||||||
|
// undefined non-weak symbol will have been errored.
|
||||||
|
if (s.isUndefined() && !s.isInPlt())
|
||||||
return false;
|
return false;
|
||||||
// A state change from ARM to Thumb and vice versa must go through an
|
// A state change from ARM to Thumb and vice versa must go through an
|
||||||
// interworking thunk if the relocation type is not R_ARM_CALL or
|
// interworking thunk if the relocation type is not R_ARM_CALL or
|
||||||
|
@ -733,11 +733,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
|
|||||||
if (expr == R_ARM_PCA)
|
if (expr == R_ARM_PCA)
|
||||||
// Some PC relative ARM (Thumb) relocations align down the place.
|
// Some PC relative ARM (Thumb) relocations align down the place.
|
||||||
p = p & 0xfffffffc;
|
p = p & 0xfffffffc;
|
||||||
if (sym.isUndefWeak()) {
|
if (sym.isUndefined()) {
|
||||||
// On ARM and AArch64 a branch to an undefined weak resolves to the next
|
// On ARM and AArch64 a branch to an undefined weak resolves to the next
|
||||||
// instruction, otherwise the place. On RISCV, resolve an undefined weak
|
// instruction, otherwise the place. On RISCV, resolve an undefined weak
|
||||||
// to the same instruction to cause an infinite loop (making the user
|
// to the same instruction to cause an infinite loop (making the user
|
||||||
// aware of the issue) while ensuring no overflow.
|
// aware of the issue) while ensuring no overflow.
|
||||||
|
// Note: if the symbol is hidden, its binding has been converted to local,
|
||||||
|
// so we just check isUndefined() here.
|
||||||
if (config->emachine == EM_ARM)
|
if (config->emachine == EM_ARM)
|
||||||
dest = getARMUndefinedRelativeWeakVA(type, a, p);
|
dest = getARMUndefinedRelativeWeakVA(type, a, p);
|
||||||
else if (config->emachine == EM_AARCH64)
|
else if (config->emachine == EM_AARCH64)
|
||||||
|
@ -695,6 +695,7 @@ def plugin_opt_eq : J<"plugin-opt=">;
|
|||||||
def: F<"detect-odr-violations">;
|
def: F<"detect-odr-violations">;
|
||||||
def: Flag<["-"], "g">;
|
def: Flag<["-"], "g">;
|
||||||
def: F<"long-plt">;
|
def: F<"long-plt">;
|
||||||
|
def: FF<"no-add-needed">;
|
||||||
def: F<"no-copy-dt-needed-entries">;
|
def: F<"no-copy-dt-needed-entries">;
|
||||||
def: F<"no-ctors-in-init-array">;
|
def: F<"no-ctors-in-init-array">;
|
||||||
def: F<"no-keep-memory">;
|
def: F<"no-keep-memory">;
|
||||||
|
@ -290,6 +290,8 @@ AARCH64_CPU_NAME("a64fx", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
|||||||
(AArch64::AEK_FP16 | AArch64::AEK_SVE))
|
(AArch64::AEK_FP16 | AArch64::AEK_SVE))
|
||||||
AARCH64_CPU_NAME("carmel", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
AARCH64_CPU_NAME("carmel", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||||
AArch64::AEK_FP16)
|
AArch64::AEK_FP16)
|
||||||
|
AARCH64_CPU_NAME("ampere1", ARMV8_6A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||||
|
(AArch64::AEK_FP16 | AArch64::AEK_SB | AArch64::AEK_SSBS))
|
||||||
// Invalid CPU
|
// Invalid CPU
|
||||||
AARCH64_CPU_NAME("invalid", INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
|
AARCH64_CPU_NAME("invalid", INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
|
||||||
#undef AARCH64_CPU_NAME
|
#undef AARCH64_CPU_NAME
|
||||||
|
@ -3469,8 +3469,13 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!finalizeBasicBlock(*BB, MBB))
|
if (!finalizeBasicBlock(*BB, MBB)) {
|
||||||
|
OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
|
||||||
|
BB->getTerminator()->getDebugLoc(), BB);
|
||||||
|
R << "unable to translate basic block";
|
||||||
|
reportTranslationError(*MF, *TPC, *ORE, R);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
WrapperObserver.removeObserver(&Verifier);
|
WrapperObserver.removeObserver(&Verifier);
|
||||||
|
@ -549,9 +549,27 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
|
|||||||
uint64_t Size = 0;
|
uint64_t Size = 0;
|
||||||
|
|
||||||
const MCExpr *ESize = MSD.Symbol->getSize();
|
const MCExpr *ESize = MSD.Symbol->getSize();
|
||||||
if (!ESize && Base)
|
if (!ESize && Base) {
|
||||||
|
// For expressions like .set y, x+1, if y's size is unset, inherit from x.
|
||||||
ESize = Base->getSize();
|
ESize = Base->getSize();
|
||||||
|
|
||||||
|
// For `.size x, 2; y = x; .size y, 1; z = y; z1 = z; .symver y, y@v1`, z,
|
||||||
|
// z1, and y@v1's st_size equals y's. However, `Base` is `x` which will give
|
||||||
|
// us 2. Follow the MCSymbolRefExpr assignment chain, which covers most
|
||||||
|
// needs. MCBinaryExpr is not handled.
|
||||||
|
const MCSymbolELF *Sym = &Symbol;
|
||||||
|
while (Sym->isVariable()) {
|
||||||
|
if (auto *Expr =
|
||||||
|
dyn_cast<MCSymbolRefExpr>(Sym->getVariableValue(false))) {
|
||||||
|
Sym = cast<MCSymbolELF>(&Expr->getSymbol());
|
||||||
|
if (!Sym->getSize())
|
||||||
|
continue;
|
||||||
|
ESize = Sym->getSize();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ESize) {
|
if (ESize) {
|
||||||
int64_t Res;
|
int64_t Res;
|
||||||
if (!ESize->evaluateKnownAbsolute(Res, Layout))
|
if (!ESize->evaluateKnownAbsolute(Res, Layout))
|
||||||
|
@ -296,6 +296,12 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Implementer == "0xc0") { // Ampere Computing
|
||||||
|
return StringSwitch<const char *>(Part)
|
||||||
|
.Case("0xac3", "ampere1")
|
||||||
|
.Default("generic");
|
||||||
|
}
|
||||||
|
|
||||||
return "generic";
|
return "generic";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,6 +557,7 @@ include "AArch64Schedule.td"
|
|||||||
include "AArch64InstrInfo.td"
|
include "AArch64InstrInfo.td"
|
||||||
include "AArch64SchedPredicates.td"
|
include "AArch64SchedPredicates.td"
|
||||||
include "AArch64SchedPredExynos.td"
|
include "AArch64SchedPredExynos.td"
|
||||||
|
include "AArch64SchedPredAmpere.td"
|
||||||
include "AArch64Combine.td"
|
include "AArch64Combine.td"
|
||||||
|
|
||||||
def AArch64InstrInfo : InstrInfo;
|
def AArch64InstrInfo : InstrInfo;
|
||||||
@ -626,6 +627,7 @@ include "AArch64SchedThunderX2T99.td"
|
|||||||
include "AArch64SchedA64FX.td"
|
include "AArch64SchedA64FX.td"
|
||||||
include "AArch64SchedThunderX3T110.td"
|
include "AArch64SchedThunderX3T110.td"
|
||||||
include "AArch64SchedTSV110.td"
|
include "AArch64SchedTSV110.td"
|
||||||
|
include "AArch64SchedAmpere1.td"
|
||||||
|
|
||||||
def TuneA35 : SubtargetFeature<"a35", "ARMProcFamily", "CortexA35",
|
def TuneA35 : SubtargetFeature<"a35", "ARMProcFamily", "CortexA35",
|
||||||
"Cortex-A35 ARM processors">;
|
"Cortex-A35 ARM processors">;
|
||||||
@ -939,6 +941,16 @@ def TuneTSV110 : SubtargetFeature<"tsv110", "ARMProcFamily", "TSV110",
|
|||||||
FeatureFuseAES,
|
FeatureFuseAES,
|
||||||
FeaturePostRAScheduler]>;
|
FeaturePostRAScheduler]>;
|
||||||
|
|
||||||
|
def TuneAmpere1 : SubtargetFeature<"ampere1", "ARMProcFamily", "Ampere1",
|
||||||
|
"Ampere Computing Ampere-1 processors", [
|
||||||
|
FeaturePostRAScheduler,
|
||||||
|
FeatureFuseAES,
|
||||||
|
FeatureLSLFast,
|
||||||
|
FeatureAggressiveFMA,
|
||||||
|
FeatureArithmeticBccFusion,
|
||||||
|
FeatureCmpBccFusion,
|
||||||
|
FeatureFuseAddress,
|
||||||
|
FeatureFuseLiterals]>;
|
||||||
|
|
||||||
def ProcessorFeatures {
|
def ProcessorFeatures {
|
||||||
list<SubtargetFeature> A53 = [HasV8_0aOps, FeatureCRC, FeatureCrypto,
|
list<SubtargetFeature> A53 = [HasV8_0aOps, FeatureCRC, FeatureCrypto,
|
||||||
@ -1047,6 +1059,8 @@ def ProcessorFeatures {
|
|||||||
list<SubtargetFeature> TSV110 = [HasV8_2aOps, FeatureCrypto, FeatureFPARMv8,
|
list<SubtargetFeature> TSV110 = [HasV8_2aOps, FeatureCrypto, FeatureFPARMv8,
|
||||||
FeatureNEON, FeaturePerfMon, FeatureSPE,
|
FeatureNEON, FeaturePerfMon, FeatureSPE,
|
||||||
FeatureFullFP16, FeatureFP16FML, FeatureDotProd];
|
FeatureFullFP16, FeatureFP16FML, FeatureDotProd];
|
||||||
|
list<SubtargetFeature> Ampere1 = [HasV8_6aOps, FeatureNEON, FeaturePerfMon,
|
||||||
|
FeatureMTE, FeatureSSBS];
|
||||||
|
|
||||||
// ETE and TRBE are future architecture extensions. We temporarily enable them
|
// ETE and TRBE are future architecture extensions. We temporarily enable them
|
||||||
// by default for users targeting generic AArch64. The extensions do not
|
// by default for users targeting generic AArch64. The extensions do not
|
||||||
@ -1184,6 +1198,10 @@ def : ProcessorModel<"a64fx", A64FXModel, ProcessorFeatures.A64FX,
|
|||||||
def : ProcessorModel<"carmel", NoSchedModel, ProcessorFeatures.Carmel,
|
def : ProcessorModel<"carmel", NoSchedModel, ProcessorFeatures.Carmel,
|
||||||
[TuneCarmel]>;
|
[TuneCarmel]>;
|
||||||
|
|
||||||
|
// Ampere Computing
|
||||||
|
def : ProcessorModel<"ampere1", Ampere1Model, ProcessorFeatures.Ampere1,
|
||||||
|
[TuneAmpere1]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Assembly parser
|
// Assembly parser
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
1136
contrib/llvm-project/llvm/lib/Target/AArch64/AArch64SchedAmpere1.td
Normal file
1136
contrib/llvm-project/llvm/lib/Target/AArch64/AArch64SchedAmpere1.td
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@
|
|||||||
|
//===- AArch64SchedPredAmpere.td - AArch64 Sched Preds -----*- tablegen -*-===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file defines scheduling predicate definitions that are used by the
|
||||||
|
// AArch64 Ampere Computing processors.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Auxiliary predicates.
|
||||||
|
|
||||||
|
// Check for a LSL shift <= 4
|
||||||
|
def AmpereCheapLSL : MCSchedPredicate<
|
||||||
|
CheckAny<[CheckShiftBy0,
|
||||||
|
CheckAll<
|
||||||
|
[CheckShiftLSL,
|
||||||
|
CheckAny<
|
||||||
|
[CheckShiftBy1,
|
||||||
|
CheckShiftBy2,
|
||||||
|
CheckShiftBy3,
|
||||||
|
CheckShiftBy4]>]>]>>;
|
@ -53,7 +53,7 @@ let FunctionMapper = "AArch64_AM::getShiftType" in {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for shifting in arithmetic and logic instructions.
|
// Check for shifting in arithmetic and logic instructions.
|
||||||
foreach I = {0-3, 8} in {
|
foreach I = {0-4, 8} in {
|
||||||
let FunctionMapper = "AArch64_AM::getShiftValue" in
|
let FunctionMapper = "AArch64_AM::getShiftValue" in
|
||||||
def CheckShiftBy#I : CheckImmOperand<3, I>;
|
def CheckShiftBy#I : CheckImmOperand<3, I>;
|
||||||
}
|
}
|
||||||
|
@ -221,6 +221,12 @@ void AArch64Subtarget::initializeProperties() {
|
|||||||
// FIXME: remove this to enable 64-bit SLP if performance looks good.
|
// FIXME: remove this to enable 64-bit SLP if performance looks good.
|
||||||
MinVectorRegisterBitWidth = 128;
|
MinVectorRegisterBitWidth = 128;
|
||||||
break;
|
break;
|
||||||
|
case Ampere1:
|
||||||
|
CacheLineSize = 64;
|
||||||
|
PrefFunctionLogAlignment = 6;
|
||||||
|
PrefLoopLogAlignment = 6;
|
||||||
|
MaxInterleaveFactor = 4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
|
|||||||
enum ARMProcFamilyEnum : uint8_t {
|
enum ARMProcFamilyEnum : uint8_t {
|
||||||
Others,
|
Others,
|
||||||
A64FX,
|
A64FX,
|
||||||
|
Ampere1,
|
||||||
AppleA7,
|
AppleA7,
|
||||||
AppleA10,
|
AppleA10,
|
||||||
AppleA11,
|
AppleA11,
|
||||||
|
@ -27,6 +27,8 @@ def RetCC_AVR_BUILTIN : CallingConv<[
|
|||||||
|
|
||||||
// Calling convention for variadic functions.
|
// Calling convention for variadic functions.
|
||||||
def ArgCC_AVR_Vararg : CallingConv<[
|
def ArgCC_AVR_Vararg : CallingConv<[
|
||||||
|
// i8 are always passed through the stack with a byte slot and byte alignment.
|
||||||
|
CCIfType<[i8], CCAssignToStack<1, 1>>,
|
||||||
// i16 are always passed through the stack with an alignment of 1.
|
// i16 are always passed through the stack with an alignment of 1.
|
||||||
CCAssignToStack<2, 1>
|
CCAssignToStack<2, 1>
|
||||||
]>;
|
]>;
|
||||||
|
@ -194,6 +194,11 @@ def brtarget_13 : Operand<OtherVT> {
|
|||||||
let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
|
let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def rcalltarget_13 : Operand<i16> {
|
||||||
|
let PrintMethod = "printPCRelImm";
|
||||||
|
let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
|
||||||
|
}
|
||||||
|
|
||||||
// The target of a 22 or 16-bit call/jmp instruction.
|
// The target of a 22 or 16-bit call/jmp instruction.
|
||||||
def call_target : Operand<iPTR> {
|
def call_target : Operand<iPTR> {
|
||||||
let EncoderMethod = "encodeCallTarget";
|
let EncoderMethod = "encodeCallTarget";
|
||||||
@ -965,10 +970,8 @@ let isBarrier = 1, isBranch = 1, isTerminator = 1 in {
|
|||||||
let isCall = 1 in {
|
let isCall = 1 in {
|
||||||
// SP is marked as a use to prevent stack-pointer assignments that appear
|
// SP is marked as a use to prevent stack-pointer assignments that appear
|
||||||
// immediately before calls from potentially appearing dead.
|
// immediately before calls from potentially appearing dead.
|
||||||
let Uses = [SP] in def RCALLk : FBRk<1, (outs),
|
let Uses = [SP] in def RCALLk : FBRk<1, (outs), (ins rcalltarget_13:$k),
|
||||||
(ins brtarget_13
|
"rcall\t$k", [(AVRcall imm:$k)]>;
|
||||||
: $target),
|
|
||||||
"rcall\t$target", []>;
|
|
||||||
|
|
||||||
// SP is marked as a use to prevent stack-pointer assignments that appear
|
// SP is marked as a use to prevent stack-pointer assignments that appear
|
||||||
// immediately before calls from potentially appearing dead.
|
// immediately before calls from potentially appearing dead.
|
||||||
@ -985,13 +988,10 @@ let isCall = 1 in {
|
|||||||
// SP is marked as a use to prevent stack-pointer assignments that appear
|
// SP is marked as a use to prevent stack-pointer assignments that appear
|
||||||
// immediately before calls from potentially appearing dead.
|
// immediately before calls from potentially appearing dead.
|
||||||
//
|
//
|
||||||
//: TODO: the imm field can be either 16 or 22 bits in devices with more
|
// TODO: the imm field can be either 16 or 22 bits in devices with more
|
||||||
// than 64k of ROM, fix it once we support the largest devices.
|
// than 64k of ROM, fix it once we support the largest devices.
|
||||||
let Uses = [SP] in def CALLk : F32BRk<0b111, (outs),
|
let Uses = [SP] in def CALLk : F32BRk<0b111, (outs), (ins call_target:$k),
|
||||||
(ins call_target
|
"call\t$k", [(AVRcall imm:$k)]>,
|
||||||
: $k),
|
|
||||||
"call\t$k", [(AVRcall imm
|
|
||||||
: $k)]>,
|
|
||||||
Requires<[HasJMPCALL]>;
|
Requires<[HasJMPCALL]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2457,8 +2457,12 @@ def : Pat<(adde i8
|
|||||||
: $src2))>;
|
: $src2))>;
|
||||||
|
|
||||||
// Calls.
|
// Calls.
|
||||||
def : Pat<(AVRcall(i16 tglobaladdr : $dst)), (CALLk tglobaladdr : $dst)>;
|
let Predicates = [HasJMPCALL] in {
|
||||||
def : Pat<(AVRcall(i16 texternalsym : $dst)), (CALLk texternalsym : $dst)>;
|
def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (CALLk tglobaladdr:$dst)>;
|
||||||
|
def : Pat<(AVRcall(i16 texternalsym:$dst)), (CALLk texternalsym:$dst)>;
|
||||||
|
}
|
||||||
|
def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (RCALLk tglobaladdr:$dst)>;
|
||||||
|
def : Pat<(AVRcall(i16 texternalsym:$dst)), (RCALLk texternalsym:$dst)>;
|
||||||
|
|
||||||
// `anyext`
|
// `anyext`
|
||||||
def : Pat<(i16(anyext i8
|
def : Pat<(i16(anyext i8
|
||||||
|
@ -37,6 +37,8 @@ class SystemZMCCodeEmitter : public MCCodeEmitter {
|
|||||||
const MCInstrInfo &MCII;
|
const MCInstrInfo &MCII;
|
||||||
MCContext &Ctx;
|
MCContext &Ctx;
|
||||||
|
|
||||||
|
mutable unsigned MemOpsEmitted;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
|
SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
|
||||||
: MCII(mcii), Ctx(ctx) {
|
: MCII(mcii), Ctx(ctx) {
|
||||||
@ -165,6 +167,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||||||
verifyInstructionPredicates(MI,
|
verifyInstructionPredicates(MI,
|
||||||
computeAvailableFeatures(STI.getFeatureBits()));
|
computeAvailableFeatures(STI.getFeatureBits()));
|
||||||
|
|
||||||
|
MemOpsEmitted = 0;
|
||||||
uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
|
uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||||
unsigned Size = MCII.get(MI.getOpcode()).getSize();
|
unsigned Size = MCII.get(MI.getOpcode()).getSize();
|
||||||
// Big-endian insertion of Size bytes.
|
// Big-endian insertion of Size bytes.
|
||||||
@ -191,12 +194,14 @@ getDispOpValue(const MCInst &MI, unsigned OpNum,
|
|||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
SystemZ::FixupKind Kind) const {
|
SystemZ::FixupKind Kind) const {
|
||||||
const MCOperand &MO = MI.getOperand(OpNum);
|
const MCOperand &MO = MI.getOperand(OpNum);
|
||||||
if (MO.isImm())
|
if (MO.isImm()) {
|
||||||
|
++MemOpsEmitted;
|
||||||
return static_cast<uint64_t>(MO.getImm());
|
return static_cast<uint64_t>(MO.getImm());
|
||||||
|
}
|
||||||
if (MO.isExpr()) {
|
if (MO.isExpr()) {
|
||||||
// All instructions follow the pattern where the first displacement has a
|
// All instructions follow the pattern where the first displacement has a
|
||||||
// 2 bytes offset, and the second one 4 bytes.
|
// 2 bytes offset, and the second one 4 bytes.
|
||||||
unsigned ByteOffs = Fixups.size() == 0 ? 2 : 4;
|
unsigned ByteOffs = MemOpsEmitted++ == 0 ? 2 : 4;
|
||||||
Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind,
|
Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind,
|
||||||
MI.getLoc()));
|
MI.getLoc()));
|
||||||
assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
|
assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
|
||||||
|
@ -6442,22 +6442,26 @@ SDValue SystemZTargetLowering::combineINT_TO_FP(
|
|||||||
SDNode *N, DAGCombinerInfo &DCI) const {
|
SDNode *N, DAGCombinerInfo &DCI) const {
|
||||||
if (DCI.Level != BeforeLegalizeTypes)
|
if (DCI.Level != BeforeLegalizeTypes)
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
SelectionDAG &DAG = DCI.DAG;
|
||||||
|
LLVMContext &Ctx = *DAG.getContext();
|
||||||
unsigned Opcode = N->getOpcode();
|
unsigned Opcode = N->getOpcode();
|
||||||
EVT OutVT = N->getValueType(0);
|
EVT OutVT = N->getValueType(0);
|
||||||
SelectionDAG &DAG = DCI.DAG;
|
Type *OutLLVMTy = OutVT.getTypeForEVT(Ctx);
|
||||||
SDValue Op = N->getOperand(0);
|
SDValue Op = N->getOperand(0);
|
||||||
unsigned OutScalarBits = OutVT.getScalarSizeInBits();
|
unsigned OutScalarBits = OutLLVMTy->getScalarSizeInBits();
|
||||||
unsigned InScalarBits = Op->getValueType(0).getScalarSizeInBits();
|
unsigned InScalarBits = Op->getValueType(0).getScalarSizeInBits();
|
||||||
|
|
||||||
// Insert an extension before type-legalization to avoid scalarization, e.g.:
|
// Insert an extension before type-legalization to avoid scalarization, e.g.:
|
||||||
// v2f64 = uint_to_fp v2i16
|
// v2f64 = uint_to_fp v2i16
|
||||||
// =>
|
// =>
|
||||||
// v2f64 = uint_to_fp (v2i64 zero_extend v2i16)
|
// v2f64 = uint_to_fp (v2i64 zero_extend v2i16)
|
||||||
if (OutVT.isVector() && OutScalarBits > InScalarBits) {
|
if (OutLLVMTy->isVectorTy() && OutScalarBits > InScalarBits &&
|
||||||
MVT ExtVT = MVT::getVectorVT(MVT::getIntegerVT(OutVT.getScalarSizeInBits()),
|
OutScalarBits <= 64) {
|
||||||
OutVT.getVectorNumElements());
|
unsigned NumElts = cast<FixedVectorType>(OutLLVMTy)->getNumElements();
|
||||||
|
EVT ExtVT = EVT::getVectorVT(
|
||||||
|
Ctx, EVT::getIntegerVT(Ctx, OutLLVMTy->getScalarSizeInBits()), NumElts);
|
||||||
unsigned ExtOpcode =
|
unsigned ExtOpcode =
|
||||||
(Opcode == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND);
|
(Opcode == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND);
|
||||||
SDValue ExtOp = DAG.getNode(ExtOpcode, SDLoc(N), ExtVT, Op);
|
SDValue ExtOp = DAG.getNode(ExtOpcode, SDLoc(N), ExtVT, Op);
|
||||||
return DAG.getNode(Opcode, SDLoc(N), OutVT, ExtOp);
|
return DAG.getNode(Opcode, SDLoc(N), OutVT, ExtOp);
|
||||||
}
|
}
|
||||||
|
@ -2488,8 +2488,12 @@ Value *InstCombinerImpl::matchSelectFromAndOr(Value *A, Value *C, Value *B,
|
|||||||
// not create unnecessary casts if the types already match.
|
// not create unnecessary casts if the types already match.
|
||||||
Type *SelTy = A->getType();
|
Type *SelTy = A->getType();
|
||||||
if (auto *VecTy = dyn_cast<VectorType>(Cond->getType())) {
|
if (auto *VecTy = dyn_cast<VectorType>(Cond->getType())) {
|
||||||
|
// For a fixed or scalable vector get N from <{vscale x} N x iM>
|
||||||
unsigned Elts = VecTy->getElementCount().getKnownMinValue();
|
unsigned Elts = VecTy->getElementCount().getKnownMinValue();
|
||||||
Type *EltTy = Builder.getIntNTy(SelTy->getPrimitiveSizeInBits() / Elts);
|
// For a fixed or scalable vector, get the size in bits of N x iM; for a
|
||||||
|
// scalar this is just M.
|
||||||
|
unsigned SelEltSize = SelTy->getPrimitiveSizeInBits().getKnownMinSize();
|
||||||
|
Type *EltTy = Builder.getIntNTy(SelEltSize / Elts);
|
||||||
SelTy = VectorType::get(EltTy, VecTy->getElementCount());
|
SelTy = VectorType::get(EltTy, VecTy->getElementCount());
|
||||||
}
|
}
|
||||||
Value *BitcastC = Builder.CreateBitCast(C, SelTy);
|
Value *BitcastC = Builder.CreateBitCast(C, SelTy);
|
||||||
|
@ -342,7 +342,8 @@ static void findReturnsToZap(Function &F,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
|
static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
|
||||||
DomTreeUpdater &DTU) {
|
DomTreeUpdater &DTU,
|
||||||
|
BasicBlock *&NewUnreachableBB) {
|
||||||
SmallPtrSet<BasicBlock *, 8> FeasibleSuccessors;
|
SmallPtrSet<BasicBlock *, 8> FeasibleSuccessors;
|
||||||
bool HasNonFeasibleEdges = false;
|
bool HasNonFeasibleEdges = false;
|
||||||
for (BasicBlock *Succ : successors(BB)) {
|
for (BasicBlock *Succ : successors(BB)) {
|
||||||
@ -385,6 +386,23 @@ static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
|
|||||||
} else if (FeasibleSuccessors.size() > 1) {
|
} else if (FeasibleSuccessors.size() > 1) {
|
||||||
SwitchInstProfUpdateWrapper SI(*cast<SwitchInst>(TI));
|
SwitchInstProfUpdateWrapper SI(*cast<SwitchInst>(TI));
|
||||||
SmallVector<DominatorTree::UpdateType, 8> Updates;
|
SmallVector<DominatorTree::UpdateType, 8> Updates;
|
||||||
|
|
||||||
|
// If the default destination is unfeasible it will never be taken. Replace
|
||||||
|
// it with a new block with a single Unreachable instruction.
|
||||||
|
BasicBlock *DefaultDest = SI->getDefaultDest();
|
||||||
|
if (!FeasibleSuccessors.contains(DefaultDest)) {
|
||||||
|
if (!NewUnreachableBB) {
|
||||||
|
NewUnreachableBB =
|
||||||
|
BasicBlock::Create(DefaultDest->getContext(), "default.unreachable",
|
||||||
|
DefaultDest->getParent(), DefaultDest);
|
||||||
|
new UnreachableInst(DefaultDest->getContext(), NewUnreachableBB);
|
||||||
|
}
|
||||||
|
|
||||||
|
SI->setDefaultDest(NewUnreachableBB);
|
||||||
|
Updates.push_back({DominatorTree::Delete, BB, DefaultDest});
|
||||||
|
Updates.push_back({DominatorTree::Insert, BB, NewUnreachableBB});
|
||||||
|
}
|
||||||
|
|
||||||
for (auto CI = SI->case_begin(); CI != SI->case_end();) {
|
for (auto CI = SI->case_begin(); CI != SI->case_end();) {
|
||||||
if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) {
|
if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) {
|
||||||
++CI;
|
++CI;
|
||||||
@ -532,8 +550,9 @@ bool llvm::runIPSCCP(
|
|||||||
NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHI(),
|
NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHI(),
|
||||||
/*PreserveLCSSA=*/false, &DTU);
|
/*PreserveLCSSA=*/false, &DTU);
|
||||||
|
|
||||||
|
BasicBlock *NewUnreachableBB = nullptr;
|
||||||
for (BasicBlock &BB : F)
|
for (BasicBlock &BB : F)
|
||||||
MadeChanges |= removeNonFeasibleEdges(Solver, &BB, DTU);
|
MadeChanges |= removeNonFeasibleEdges(Solver, &BB, DTU, NewUnreachableBB);
|
||||||
|
|
||||||
for (BasicBlock *DeadBB : BlocksToErase)
|
for (BasicBlock *DeadBB : BlocksToErase)
|
||||||
DTU.deleteBB(DeadBB);
|
DTU.deleteBB(DeadBB);
|
||||||
|
Loading…
Reference in New Issue
Block a user