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.
|
||||
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;
|
||||
|
||||
/// 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;
|
||||
|
||||
StringRef getCUIDHash() const;
|
||||
|
@ -8551,11 +8551,10 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
|
||||
RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list");
|
||||
if (Context->getLangOpts().CPlusPlus) {
|
||||
// namespace std { struct __va_list {
|
||||
NamespaceDecl *NS;
|
||||
NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
|
||||
Context->getTranslationUnitDecl(),
|
||||
/*Inline*/ false, SourceLocation(),
|
||||
SourceLocation(), &Context->Idents.get("std"),
|
||||
auto *NS = NamespaceDecl::Create(
|
||||
const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(),
|
||||
/*Inline*/ false, SourceLocation(), SourceLocation(),
|
||||
&Context->Idents.get("std"),
|
||||
/*PrevDecl*/ nullptr);
|
||||
NS->setImplicit();
|
||||
VaListTagDecl->setDeclContext(NS);
|
||||
@ -12264,14 +12263,18 @@ bool ASTContext::mayExternalizeStaticVar(const Decl *D) const {
|
||||
(D->hasAttr<CUDAConstantAttr>() &&
|
||||
!D->getAttr<CUDAConstantAttr>()->isImplicit());
|
||||
// CUDA/HIP: static managed variables need to be externalized since it is
|
||||
// a declaration in IR, therefore cannot have internal linkage.
|
||||
return IsStaticVar &&
|
||||
(D->hasAttr<HIPManagedAttr>() || IsExplicitDeviceVar);
|
||||
// a declaration in IR, therefore cannot have internal linkage. Kernels in
|
||||
// anonymous name space needs to be externalized to avoid duplicate symbols.
|
||||
return (IsStaticVar &&
|
||||
(D->hasAttr<HIPManagedAttr>() || IsExplicitDeviceVar)) ||
|
||||
(D->hasAttr<CUDAGlobalAttr>() &&
|
||||
basicGVALinkageForFunction(*this, cast<FunctionDecl>(D)) ==
|
||||
GVA_Internal);
|
||||
}
|
||||
|
||||
bool ASTContext::shouldExternalizeStaticVar(const Decl *D) const {
|
||||
return mayExternalizeStaticVar(D) &&
|
||||
(D->hasAttr<HIPManagedAttr>() ||
|
||||
(D->hasAttr<HIPManagedAttr>() || D->hasAttr<CUDAGlobalAttr>() ||
|
||||
CUDADeviceVarODRUsedByHost.count(cast<VarDecl>(D)));
|
||||
}
|
||||
|
||||
|
@ -40,65 +40,10 @@ using namespace clang;
|
||||
|
||||
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) {
|
||||
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) {
|
||||
if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
|
||||
return ftd->getTemplatedDecl();
|
||||
@ -126,6 +71,7 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
|
||||
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
|
||||
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
|
||||
const DiscriminatorOverrideTy DiscriminatorOverride = nullptr;
|
||||
NamespaceDecl *StdNamespace = nullptr;
|
||||
|
||||
bool NeedsUniqueInternalLinkageNames = false;
|
||||
|
||||
@ -249,6 +195,16 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
|
||||
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(); }
|
||||
|
||||
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:
|
||||
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
|
||||
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 &&
|
||||
!ND->isExternallyVisible() &&
|
||||
getEffectiveDeclContext(ND)->isFileContext() &&
|
||||
@ -862,18 +891,9 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *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.
|
||||
static bool isStd(const NamespaceDecl *NS) {
|
||||
if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
|
||||
->isTranslationUnit())
|
||||
bool CXXNameMangler::isStd(const NamespaceDecl *NS) {
|
||||
if (!Context.getEffectiveParentContext(NS)->isTranslationUnit())
|
||||
return false;
|
||||
|
||||
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'
|
||||
// namespace.
|
||||
static bool isStdNamespace(const DeclContext *DC) {
|
||||
bool CXXNameMangler::isStdNamespace(const DeclContext *DC) {
|
||||
if (!DC->isNamespace())
|
||||
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,
|
||||
const AbiTagList *AdditionalAbiTags) {
|
||||
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
||||
@ -964,7 +995,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
|
||||
// ::= [<module-name>] <unscoped-template-name> <template-args>
|
||||
// ::= <local-name>
|
||||
//
|
||||
const DeclContext *DC = getEffectiveDeclContext(ND);
|
||||
const DeclContext *DC = Context.getEffectiveDeclContext(ND);
|
||||
|
||||
// If this is an extern variable declared locally, the relevant DeclContext
|
||||
// is that of the containing namespace, or the translation unit.
|
||||
@ -972,13 +1003,13 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
|
||||
// a proper semantic declaration context!
|
||||
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
|
||||
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
||||
DC = getEffectiveParentContext(DC);
|
||||
DC = Context.getEffectiveParentContext(DC);
|
||||
else if (GetLocalClassDecl(ND)) {
|
||||
mangleLocalName(GD, AdditionalAbiTags);
|
||||
return;
|
||||
}
|
||||
|
||||
DC = IgnoreLinkageSpecDecls(DC);
|
||||
assert(!isa<LinkageSpecDecl>(DC) && "context cannot be LinkageSpecDecl");
|
||||
|
||||
if (isLocalContainerContext(DC)) {
|
||||
mangleLocalName(GD, AdditionalAbiTags);
|
||||
@ -1054,7 +1085,7 @@ void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) {
|
||||
void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs) {
|
||||
const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));
|
||||
const DeclContext *DC = Context.getEffectiveDeclContext(TD);
|
||||
|
||||
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
||||
mangleUnscopedTemplateName(TD, nullptr);
|
||||
@ -1070,7 +1101,7 @@ void CXXNameMangler::mangleUnscopedName(GlobalDecl GD,
|
||||
// <unscoped-name> ::= <unqualified-name>
|
||||
// ::= St <unqualified-name> # ::std::
|
||||
|
||||
if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND))))
|
||||
if (isStdNamespace(Context.getEffectiveDeclContext(ND)))
|
||||
Out << "St";
|
||||
|
||||
mangleUnqualifiedName(GD, AdditionalAbiTags);
|
||||
@ -1430,7 +1461,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
|
||||
// 12_GLOBAL__N_1 mangling is quite sufficient there, and this better
|
||||
// matches GCC anyway, because GCC does not treat anonymous namespaces as
|
||||
// implying internal linkage.
|
||||
if (isInternalLinkageDecl(ND))
|
||||
if (Context.isInternalLinkageDecl(ND))
|
||||
Out << 'L';
|
||||
|
||||
auto *FD = dyn_cast<FunctionDecl>(ND);
|
||||
@ -1745,7 +1776,7 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD,
|
||||
// <discriminator> := _ <non-negative number>
|
||||
assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
|
||||
const RecordDecl *RD = GetLocalClassDecl(D);
|
||||
const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D);
|
||||
const DeclContext *DC = Context.getEffectiveDeclContext(RD ? RD : D);
|
||||
|
||||
Out << 'Z';
|
||||
|
||||
@ -1798,13 +1829,13 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD,
|
||||
if (const NamedDecl *PrefixND = getClosurePrefix(BD))
|
||||
mangleClosurePrefix(PrefixND, true /*NoFunction*/);
|
||||
else
|
||||
manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
|
||||
manglePrefix(Context.getEffectiveDeclContext(BD), true /*NoFunction*/);
|
||||
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
|
||||
mangleUnqualifiedBlock(BD);
|
||||
} else {
|
||||
const NamedDecl *ND = cast<NamedDecl>(D);
|
||||
mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags,
|
||||
true /*NoFunction*/);
|
||||
mangleNestedName(GD, Context.getEffectiveDeclContext(ND),
|
||||
AdditionalAbiTags, true /*NoFunction*/);
|
||||
}
|
||||
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
const DeclContext *DC = getEffectiveDeclContext(Block);
|
||||
const DeclContext *DC = Context.getEffectiveDeclContext(Block);
|
||||
if (isLocalContainerContext(DC)) {
|
||||
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
|
||||
return;
|
||||
@ -2030,7 +2061,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
||||
// ::= # empty
|
||||
// ::= <substitution>
|
||||
|
||||
DC = IgnoreLinkageSpecDecls(DC);
|
||||
assert(!isa<LinkageSpecDecl>(DC) && "prefix cannot be LinkageSpecDecl");
|
||||
|
||||
if (DC->isTranslationUnit())
|
||||
return;
|
||||
@ -2053,7 +2084,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
||||
mangleClosurePrefix(PrefixND, NoFunction);
|
||||
mangleUnqualifiedName(ND, nullptr);
|
||||
} else {
|
||||
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
||||
manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
|
||||
mangleUnqualifiedName(ND, nullptr);
|
||||
}
|
||||
|
||||
@ -2107,7 +2138,7 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD,
|
||||
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
|
||||
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
|
||||
} else {
|
||||
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
||||
manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
|
||||
if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND))
|
||||
mangleUnqualifiedName(GD, nullptr);
|
||||
else
|
||||
@ -2152,7 +2183,7 @@ void CXXNameMangler::mangleClosurePrefix(const NamedDecl *ND, bool NoFunction) {
|
||||
mangleTemplatePrefix(TD, NoFunction);
|
||||
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
|
||||
} else {
|
||||
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
||||
manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
|
||||
mangleUnqualifiedName(ND, nullptr);
|
||||
}
|
||||
|
||||
@ -5969,56 +6000,61 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isCharType(QualType T) {
|
||||
if (T.isNull())
|
||||
/// Returns whether S is a template specialization of std::Name with a single
|
||||
/// argument of type A.
|
||||
bool CXXNameMangler::isSpecializedAs(QualType S, llvm::StringRef Name,
|
||||
QualType A) {
|
||||
if (S.isNull())
|
||||
return false;
|
||||
|
||||
return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
|
||||
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>();
|
||||
const RecordType *RT = S->getAs<RecordType>();
|
||||
if (!RT)
|
||||
return false;
|
||||
|
||||
const ClassTemplateSpecializationDecl *SD =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
|
||||
if (!SD)
|
||||
if (!SD || !SD->getIdentifier()->isStr(Name))
|
||||
return false;
|
||||
|
||||
if (!isStdNamespace(getEffectiveDeclContext(SD)))
|
||||
if (!isStdNamespace(Context.getEffectiveDeclContext(SD)))
|
||||
return false;
|
||||
|
||||
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
||||
if (TemplateArgs.size() != 1)
|
||||
return false;
|
||||
|
||||
if (!isCharType(TemplateArgs[0].getAsType()))
|
||||
if (TemplateArgs[0].getAsType() != A)
|
||||
return false;
|
||||
|
||||
return SD->getIdentifier()->getName() == Name;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <std::size_t StrLen>
|
||||
static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,
|
||||
const char (&Str)[StrLen]) {
|
||||
if (!SD->getIdentifier()->isStr(Str))
|
||||
/// Returns whether SD is a template specialization std::Name<char,
|
||||
/// std::char_traits<char> [, std::allocator<char>]>
|
||||
/// HasAllocator controls whether the 3rd template argument is needed.
|
||||
bool CXXNameMangler::isStdCharSpecialization(
|
||||
const ClassTemplateSpecializationDecl *SD, llvm::StringRef Name,
|
||||
bool HasAllocator) {
|
||||
if (!SD->getIdentifier()->isStr(Name))
|
||||
return false;
|
||||
|
||||
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
||||
if (TemplateArgs.size() != 2)
|
||||
if (TemplateArgs.size() != (HasAllocator ? 3 : 2))
|
||||
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;
|
||||
|
||||
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 true;
|
||||
@ -6031,10 +6067,11 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
||||
Out << "St";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
|
||||
if (!isStdNamespace(getEffectiveDeclContext(TD)))
|
||||
if (!isStdNamespace(Context.getEffectiveDeclContext(TD)))
|
||||
return false;
|
||||
|
||||
// <substitution> ::= Sa # ::std::allocator
|
||||
@ -6048,56 +6085,45 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
||||
Out << "Sb";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const ClassTemplateSpecializationDecl *SD =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
||||
if (!isStdNamespace(getEffectiveDeclContext(SD)))
|
||||
if (!isStdNamespace(Context.getEffectiveDeclContext(SD)))
|
||||
return false;
|
||||
|
||||
// <substitution> ::= Ss # ::std::basic_string<char,
|
||||
// ::std::char_traits<char>,
|
||||
// ::std::allocator<char> >
|
||||
if (SD->getIdentifier()->isStr("basic_string")) {
|
||||
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;
|
||||
|
||||
if (isStdCharSpecialization(SD, "basic_string", /*HasAllocator=*/true)) {
|
||||
Out << "Ss";
|
||||
return true;
|
||||
}
|
||||
|
||||
// <substitution> ::= Si # ::std::basic_istream<char,
|
||||
// ::std::char_traits<char> >
|
||||
if (isStreamCharSpecialization(SD, "basic_istream")) {
|
||||
if (isStdCharSpecialization(SD, "basic_istream", /*HasAllocator=*/false)) {
|
||||
Out << "Si";
|
||||
return true;
|
||||
}
|
||||
|
||||
// <substitution> ::= So # ::std::basic_ostream<char,
|
||||
// ::std::char_traits<char> >
|
||||
if (isStreamCharSpecialization(SD, "basic_ostream")) {
|
||||
if (isStdCharSpecialization(SD, "basic_ostream", /*HasAllocator=*/false)) {
|
||||
Out << "So";
|
||||
return true;
|
||||
}
|
||||
|
||||
// <substitution> ::= Sd # ::std::basic_iostream<char,
|
||||
// ::std::char_traits<char> >
|
||||
if (isStreamCharSpecialization(SD, "basic_iostream")) {
|
||||
if (isStdCharSpecialization(SD, "basic_iostream", /*HasAllocator=*/false)) {
|
||||
Out << "Sd";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1466,8 +1466,7 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
|
||||
if (!Policy.SuppressScope)
|
||||
AppendScope(TD->getDeclContext(), OS, TD->getDeclName());
|
||||
|
||||
IdentifierInfo *II = TD->getIdentifier();
|
||||
OS << II->getName();
|
||||
OS << TD->getName();
|
||||
} else {
|
||||
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
|
||||
// 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.
|
||||
// This alignment guarantee also applies to Windows and Android. On Darwin,
|
||||
// the alignment is 16 bytes on both 64-bit and 32-bit systems.
|
||||
// This alignment guarantee also applies to Windows and Android. On Darwin
|
||||
// and OpenBSD, the alignment is 16 bytes on both 64-bit and 32-bit systems.
|
||||
if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid())
|
||||
NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
|
||||
else if (T.isOSDarwin())
|
||||
else if (T.isOSDarwin() || T.isOSOpenBSD())
|
||||
NewAlign = 128;
|
||||
else
|
||||
NewAlign = 0; // Infer from basic type alignment.
|
||||
|
@ -287,7 +287,7 @@ std::string CGNVCUDARuntime::getDeviceSideName(const NamedDecl *ND) {
|
||||
SmallString<256> Buffer;
|
||||
llvm::raw_svector_ostream Out(Buffer);
|
||||
Out << DeviceSideName;
|
||||
CGM.printPostfixForExternalizedStaticVar(Out);
|
||||
CGM.printPostfixForExternalizedDecl(Out, ND);
|
||||
DeviceSideName = std::string(Out.str());
|
||||
}
|
||||
return DeviceSideName;
|
||||
|
@ -1572,7 +1572,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
||||
llvm::Value *allocSize =
|
||||
EmitCXXNewAllocSize(*this, E, minElements, numElements,
|
||||
allocSizeWithoutCookie);
|
||||
CharUnits allocAlign = getContext().getPreferredTypeAlignInChars(allocType);
|
||||
CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
|
||||
|
||||
// Emit the allocation call. If the allocator is a global placement
|
||||
// operator, just "inline" it directly.
|
||||
|
@ -1367,7 +1367,7 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
|
||||
if (CGM.getContext().shouldExternalizeStaticVar(ND) &&
|
||||
CGM.getLangOpts().GPURelocatableDeviceCode &&
|
||||
CGM.getLangOpts().CUDAIsDevice && !CGM.getLangOpts().CUID.empty())
|
||||
CGM.printPostfixForExternalizedStaticVar(Out);
|
||||
CGM.printPostfixForExternalizedDecl(Out, ND);
|
||||
return std::string(Out.str());
|
||||
}
|
||||
|
||||
@ -1455,7 +1455,7 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
|
||||
// directly between host- and device-compilations, the host- and
|
||||
// device-mangling in host compilation could help catching certain ones.
|
||||
assert(!isa<FunctionDecl>(ND) || !ND->hasAttr<CUDAGlobalAttr>() ||
|
||||
getLangOpts().CUDAIsDevice ||
|
||||
getContext().shouldExternalizeStaticVar(ND) || getLangOpts().CUDAIsDevice ||
|
||||
(getContext().getAuxTargetInfo() &&
|
||||
(getContext().getAuxTargetInfo()->getCXXABI() !=
|
||||
getContext().getTargetInfo().getCXXABI())) ||
|
||||
@ -6645,7 +6645,14 @@ bool CodeGenModule::stopAutoInit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CodeGenModule::printPostfixForExternalizedStaticVar(
|
||||
llvm::raw_ostream &OS) const {
|
||||
OS << "__static__" << getContext().getCUIDHash();
|
||||
void CodeGenModule::printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
|
||||
const Decl *D) const {
|
||||
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);
|
||||
bool stopAutoInit();
|
||||
|
||||
/// Print the postfix for externalized static variable for single source
|
||||
/// offloading languages CUDA and HIP.
|
||||
void printPostfixForExternalizedStaticVar(llvm::raw_ostream &OS) const;
|
||||
/// Print the postfix for externalized static variable or kernels for single
|
||||
/// source offloading languages CUDA and HIP.
|
||||
void printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
|
||||
const Decl *D) const;
|
||||
|
||||
private:
|
||||
llvm::Constant *GetOrCreateLLVMFunction(
|
||||
|
@ -510,7 +510,7 @@ void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs,
|
||||
return;
|
||||
}
|
||||
|
||||
CC1Args.push_back("-internal-isystem");
|
||||
CC1Args.push_back("-idirafter");
|
||||
CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
|
||||
if (UsesRuntimeWrapper)
|
||||
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.");
|
||||
}
|
||||
|
||||
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)) {
|
||||
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);
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
|
||||
options::OPT_r)) {
|
||||
if (ToolChain.ShouldLinkCXXStdlib(Args))
|
||||
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
|
||||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
|
||||
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))
|
||||
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
|
||||
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,
|
||||
ArgStringList &CmdArgs) {
|
||||
// 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)
|
||||
addOpenMPRuntimeSpecificRPath(TC, Args, CmdArgs);
|
||||
addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -111,6 +111,9 @@ void addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
|
||||
llvm::opt::ArgStringList &CmdArgs);
|
||||
void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
|
||||
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.
|
||||
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
|
||||
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);
|
||||
|
||||
// Similar to the logic for GCC above, if we are currently running Clang
|
||||
// inside of the requested system root, add its parent library path to those
|
||||
// searched.
|
||||
// FIXME: It's not clear whether we should use the driver's installed
|
||||
// directory ('Dir' below) or the ResourceDir.
|
||||
if (StringRef(D.Dir).startswith(SysRoot)) {
|
||||
// Even if OSLibDir != "lib", this is needed for Clang in the build
|
||||
// directory (not installed) to find libc++.
|
||||
// The deprecated -DLLVM_ENABLE_PROJECTS=libcxx configuration installs
|
||||
// libc++.so in D.Dir+"/../lib/". Detect this path.
|
||||
// TODO Remove once LLVM_ENABLE_PROJECTS=libcxx is unsupported.
|
||||
if (StringRef(D.Dir).startswith(SysRoot) &&
|
||||
D.getVFS().exists(D.Dir + "/../lib/libc++.so"))
|
||||
addPathIfExists(D, D.Dir + "/../lib", Paths);
|
||||
if (OSLibDir != "lib")
|
||||
addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
|
||||
}
|
||||
|
||||
addPathIfExists(D, SysRoot + "/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.");
|
||||
}
|
||||
|
||||
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))
|
||||
CmdArgs.push_back(
|
||||
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);
|
||||
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))
|
||||
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
|
||||
if (Args.hasArg(options::OPT_fstack_protector) ||
|
||||
@ -149,11 +151,13 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
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(
|
||||
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);
|
||||
|
||||
|
@ -45,3 +45,5 @@ intercept setjmp, _ZN14__interception11real_setjmpE
|
||||
intercept _setjmp, _ZN14__interception12real__setjmpE
|
||||
intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE
|
||||
intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE
|
||||
|
||||
NO_EXEC_STACK_DIRECTIVE
|
||||
|
@ -68,8 +68,6 @@ namespace ranges {
|
||||
template <range _Rp>
|
||||
using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>;
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
||||
|
||||
// [range.sized]
|
||||
template <class _Tp>
|
||||
concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
|
||||
@ -135,8 +133,6 @@ namespace ranges {
|
||||
(is_lvalue_reference_v<_Tp> ||
|
||||
(movable<remove_reference_t<_Tp>> && !__is_std_initializer_list<remove_cvref_t<_Tp>>))));
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
||||
|
||||
} // namespace ranges
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
_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]
|
||||
|
||||
@ -99,7 +99,7 @@ inline namespace __cpo {
|
||||
} // namespace __cpo
|
||||
} // namespace ranges
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
||||
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
namespace ranges {
|
||||
template<class>
|
||||
@ -128,7 +128,7 @@ inline namespace __cpo {
|
||||
} // namespace __cpo
|
||||
} // namespace ranges
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
|
||||
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
_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,
|
||||
uint64_t branchAddr, const Symbol &s,
|
||||
int64_t a) const {
|
||||
// If s is an undefined weak symbol and does not have a PLT entry then it
|
||||
// will be resolved as a branch to the next instruction.
|
||||
if (s.isUndefWeak() && !s.isInPlt())
|
||||
// If s is an undefined weak symbol and does not have a PLT entry then it will
|
||||
// be resolved as a branch to the next instruction. If it is hidden, its
|
||||
// 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;
|
||||
// ELF for the ARM 64-bit architecture, section Call and Jump relocations
|
||||
// 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,
|
||||
uint64_t branchAddr, const Symbol &s,
|
||||
int64_t a) const {
|
||||
// If S is an undefined weak symbol and does not have a PLT entry then it
|
||||
// will be resolved as a branch to the next instruction.
|
||||
if (s.isUndefWeak() && !s.isInPlt())
|
||||
// If s is an undefined weak symbol and does not have a PLT entry then it will
|
||||
// be resolved as a branch to the next instruction. If it is hidden, its
|
||||
// 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;
|
||||
// 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
|
||||
|
@ -733,11 +733,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
|
||||
if (expr == R_ARM_PCA)
|
||||
// Some PC relative ARM (Thumb) relocations align down the place.
|
||||
p = p & 0xfffffffc;
|
||||
if (sym.isUndefWeak()) {
|
||||
if (sym.isUndefined()) {
|
||||
// On ARM and AArch64 a branch to an undefined weak resolves to the next
|
||||
// instruction, otherwise the place. On RISCV, resolve an undefined weak
|
||||
// to the same instruction to cause an infinite loop (making the user
|
||||
// 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)
|
||||
dest = getARMUndefinedRelativeWeakVA(type, a, p);
|
||||
else if (config->emachine == EM_AARCH64)
|
||||
|
@ -695,6 +695,7 @@ def plugin_opt_eq : J<"plugin-opt=">;
|
||||
def: F<"detect-odr-violations">;
|
||||
def: Flag<["-"], "g">;
|
||||
def: F<"long-plt">;
|
||||
def: FF<"no-add-needed">;
|
||||
def: F<"no-copy-dt-needed-entries">;
|
||||
def: F<"no-ctors-in-init-array">;
|
||||
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_CPU_NAME("carmel", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
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
|
||||
AARCH64_CPU_NAME("invalid", INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
|
||||
#undef AARCH64_CPU_NAME
|
||||
|
@ -3469,9 +3469,14 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
WrapperObserver.removeObserver(&Verifier);
|
||||
#endif
|
||||
|
@ -549,9 +549,27 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
|
||||
uint64_t Size = 0;
|
||||
|
||||
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();
|
||||
|
||||
// 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) {
|
||||
int64_t Res;
|
||||
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";
|
||||
}
|
||||
|
||||
|
@ -557,6 +557,7 @@ include "AArch64Schedule.td"
|
||||
include "AArch64InstrInfo.td"
|
||||
include "AArch64SchedPredicates.td"
|
||||
include "AArch64SchedPredExynos.td"
|
||||
include "AArch64SchedPredAmpere.td"
|
||||
include "AArch64Combine.td"
|
||||
|
||||
def AArch64InstrInfo : InstrInfo;
|
||||
@ -626,6 +627,7 @@ include "AArch64SchedThunderX2T99.td"
|
||||
include "AArch64SchedA64FX.td"
|
||||
include "AArch64SchedThunderX3T110.td"
|
||||
include "AArch64SchedTSV110.td"
|
||||
include "AArch64SchedAmpere1.td"
|
||||
|
||||
def TuneA35 : SubtargetFeature<"a35", "ARMProcFamily", "CortexA35",
|
||||
"Cortex-A35 ARM processors">;
|
||||
@ -939,6 +941,16 @@ def TuneTSV110 : SubtargetFeature<"tsv110", "ARMProcFamily", "TSV110",
|
||||
FeatureFuseAES,
|
||||
FeaturePostRAScheduler]>;
|
||||
|
||||
def TuneAmpere1 : SubtargetFeature<"ampere1", "ARMProcFamily", "Ampere1",
|
||||
"Ampere Computing Ampere-1 processors", [
|
||||
FeaturePostRAScheduler,
|
||||
FeatureFuseAES,
|
||||
FeatureLSLFast,
|
||||
FeatureAggressiveFMA,
|
||||
FeatureArithmeticBccFusion,
|
||||
FeatureCmpBccFusion,
|
||||
FeatureFuseAddress,
|
||||
FeatureFuseLiterals]>;
|
||||
|
||||
def ProcessorFeatures {
|
||||
list<SubtargetFeature> A53 = [HasV8_0aOps, FeatureCRC, FeatureCrypto,
|
||||
@ -1047,6 +1059,8 @@ def ProcessorFeatures {
|
||||
list<SubtargetFeature> TSV110 = [HasV8_2aOps, FeatureCrypto, FeatureFPARMv8,
|
||||
FeatureNEON, FeaturePerfMon, FeatureSPE,
|
||||
FeatureFullFP16, FeatureFP16FML, FeatureDotProd];
|
||||
list<SubtargetFeature> Ampere1 = [HasV8_6aOps, FeatureNEON, FeaturePerfMon,
|
||||
FeatureMTE, FeatureSSBS];
|
||||
|
||||
// ETE and TRBE are future architecture extensions. We temporarily enable them
|
||||
// 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,
|
||||
[TuneCarmel]>;
|
||||
|
||||
// Ampere Computing
|
||||
def : ProcessorModel<"ampere1", Ampere1Model, ProcessorFeatures.Ampere1,
|
||||
[TuneAmpere1]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
foreach I = {0-3, 8} in {
|
||||
foreach I = {0-4, 8} in {
|
||||
let FunctionMapper = "AArch64_AM::getShiftValue" in
|
||||
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.
|
||||
MinVectorRegisterBitWidth = 128;
|
||||
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 {
|
||||
Others,
|
||||
A64FX,
|
||||
Ampere1,
|
||||
AppleA7,
|
||||
AppleA10,
|
||||
AppleA11,
|
||||
|
@ -27,6 +27,8 @@ def RetCC_AVR_BUILTIN : CallingConv<[
|
||||
|
||||
// Calling convention for variadic functions.
|
||||
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.
|
||||
CCAssignToStack<2, 1>
|
||||
]>;
|
||||
|
@ -194,6 +194,11 @@ def brtarget_13 : Operand<OtherVT> {
|
||||
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.
|
||||
def call_target : Operand<iPTR> {
|
||||
let EncoderMethod = "encodeCallTarget";
|
||||
@ -965,10 +970,8 @@ let isBarrier = 1, isBranch = 1, isTerminator = 1 in {
|
||||
let isCall = 1 in {
|
||||
// SP is marked as a use to prevent stack-pointer assignments that appear
|
||||
// immediately before calls from potentially appearing dead.
|
||||
let Uses = [SP] in def RCALLk : FBRk<1, (outs),
|
||||
(ins brtarget_13
|
||||
: $target),
|
||||
"rcall\t$target", []>;
|
||||
let Uses = [SP] in def RCALLk : FBRk<1, (outs), (ins rcalltarget_13:$k),
|
||||
"rcall\t$k", [(AVRcall imm:$k)]>;
|
||||
|
||||
// SP is marked as a use to prevent stack-pointer assignments that appear
|
||||
// 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
|
||||
// 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.
|
||||
let Uses = [SP] in def CALLk : F32BRk<0b111, (outs),
|
||||
(ins call_target
|
||||
: $k),
|
||||
"call\t$k", [(AVRcall imm
|
||||
: $k)]>,
|
||||
let Uses = [SP] in def CALLk : F32BRk<0b111, (outs), (ins call_target:$k),
|
||||
"call\t$k", [(AVRcall imm:$k)]>,
|
||||
Requires<[HasJMPCALL]>;
|
||||
}
|
||||
|
||||
@ -2457,8 +2457,12 @@ def : Pat<(adde i8
|
||||
: $src2))>;
|
||||
|
||||
// Calls.
|
||||
let Predicates = [HasJMPCALL] in {
|
||||
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`
|
||||
def : Pat<(i16(anyext i8
|
||||
|
@ -37,6 +37,8 @@ class SystemZMCCodeEmitter : public MCCodeEmitter {
|
||||
const MCInstrInfo &MCII;
|
||||
MCContext &Ctx;
|
||||
|
||||
mutable unsigned MemOpsEmitted;
|
||||
|
||||
public:
|
||||
SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
|
||||
: MCII(mcii), Ctx(ctx) {
|
||||
@ -165,6 +167,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
verifyInstructionPredicates(MI,
|
||||
computeAvailableFeatures(STI.getFeatureBits()));
|
||||
|
||||
MemOpsEmitted = 0;
|
||||
uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
|
||||
unsigned Size = MCII.get(MI.getOpcode()).getSize();
|
||||
// Big-endian insertion of Size bytes.
|
||||
@ -191,12 +194,14 @@ getDispOpValue(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
SystemZ::FixupKind Kind) const {
|
||||
const MCOperand &MO = MI.getOperand(OpNum);
|
||||
if (MO.isImm())
|
||||
if (MO.isImm()) {
|
||||
++MemOpsEmitted;
|
||||
return static_cast<uint64_t>(MO.getImm());
|
||||
}
|
||||
if (MO.isExpr()) {
|
||||
// All instructions follow the pattern where the first displacement has a
|
||||
// 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,
|
||||
MI.getLoc()));
|
||||
assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
|
||||
|
@ -6442,20 +6442,24 @@ SDValue SystemZTargetLowering::combineINT_TO_FP(
|
||||
SDNode *N, DAGCombinerInfo &DCI) const {
|
||||
if (DCI.Level != BeforeLegalizeTypes)
|
||||
return SDValue();
|
||||
SelectionDAG &DAG = DCI.DAG;
|
||||
LLVMContext &Ctx = *DAG.getContext();
|
||||
unsigned Opcode = N->getOpcode();
|
||||
EVT OutVT = N->getValueType(0);
|
||||
SelectionDAG &DAG = DCI.DAG;
|
||||
Type *OutLLVMTy = OutVT.getTypeForEVT(Ctx);
|
||||
SDValue Op = N->getOperand(0);
|
||||
unsigned OutScalarBits = OutVT.getScalarSizeInBits();
|
||||
unsigned OutScalarBits = OutLLVMTy->getScalarSizeInBits();
|
||||
unsigned InScalarBits = Op->getValueType(0).getScalarSizeInBits();
|
||||
|
||||
// Insert an extension before type-legalization to avoid scalarization, e.g.:
|
||||
// v2f64 = uint_to_fp v2i16
|
||||
// =>
|
||||
// v2f64 = uint_to_fp (v2i64 zero_extend v2i16)
|
||||
if (OutVT.isVector() && OutScalarBits > InScalarBits) {
|
||||
MVT ExtVT = MVT::getVectorVT(MVT::getIntegerVT(OutVT.getScalarSizeInBits()),
|
||||
OutVT.getVectorNumElements());
|
||||
if (OutLLVMTy->isVectorTy() && OutScalarBits > InScalarBits &&
|
||||
OutScalarBits <= 64) {
|
||||
unsigned NumElts = cast<FixedVectorType>(OutLLVMTy)->getNumElements();
|
||||
EVT ExtVT = EVT::getVectorVT(
|
||||
Ctx, EVT::getIntegerVT(Ctx, OutLLVMTy->getScalarSizeInBits()), NumElts);
|
||||
unsigned ExtOpcode =
|
||||
(Opcode == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND);
|
||||
SDValue ExtOp = DAG.getNode(ExtOpcode, SDLoc(N), ExtVT, Op);
|
||||
|
@ -2488,8 +2488,12 @@ Value *InstCombinerImpl::matchSelectFromAndOr(Value *A, Value *C, Value *B,
|
||||
// not create unnecessary casts if the types already match.
|
||||
Type *SelTy = A->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();
|
||||
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());
|
||||
}
|
||||
Value *BitcastC = Builder.CreateBitCast(C, SelTy);
|
||||
|
@ -342,7 +342,8 @@ static void findReturnsToZap(Function &F,
|
||||
}
|
||||
|
||||
static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
|
||||
DomTreeUpdater &DTU) {
|
||||
DomTreeUpdater &DTU,
|
||||
BasicBlock *&NewUnreachableBB) {
|
||||
SmallPtrSet<BasicBlock *, 8> FeasibleSuccessors;
|
||||
bool HasNonFeasibleEdges = false;
|
||||
for (BasicBlock *Succ : successors(BB)) {
|
||||
@ -385,6 +386,23 @@ static bool removeNonFeasibleEdges(const SCCPSolver &Solver, BasicBlock *BB,
|
||||
} else if (FeasibleSuccessors.size() > 1) {
|
||||
SwitchInstProfUpdateWrapper SI(*cast<SwitchInst>(TI));
|
||||
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();) {
|
||||
if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) {
|
||||
++CI;
|
||||
@ -532,8 +550,9 @@ bool llvm::runIPSCCP(
|
||||
NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHI(),
|
||||
/*PreserveLCSSA=*/false, &DTU);
|
||||
|
||||
BasicBlock *NewUnreachableBB = nullptr;
|
||||
for (BasicBlock &BB : F)
|
||||
MadeChanges |= removeNonFeasibleEdges(Solver, &BB, DTU);
|
||||
MadeChanges |= removeNonFeasibleEdges(Solver, &BB, DTU, NewUnreachableBB);
|
||||
|
||||
for (BasicBlock *DeadBB : BlocksToErase)
|
||||
DTU.deleteBB(DeadBB);
|
||||
|
Loading…
Reference in New Issue
Block a user