From eb4ff84dc5f98e31aebadff6c8aa38454c69a572 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Thu, 26 Mar 2020 17:40:50 +0000 Subject: [PATCH] Vendor import of llvm-project tag llvmorg-10.0.0-0-gd32170dbd5b (aka 10.0.0 release). --- clang/include/clang/Sema/Sema.h | 6 ++- clang/lib/Driver/ToolChains/Cuda.cpp | 32 +++++++++------- clang/lib/Driver/ToolChains/Cuda.h | 6 +++ clang/lib/Parse/ParseDecl.cpp | 6 +++ clang/lib/Parse/ParseTemplate.cpp | 3 +- clang/lib/Sema/SemaTemplate.cpp | 13 ++++--- clang/lib/Sema/TreeTransform.h | 2 +- llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 51 +++++++++++++++++++++---- 8 files changed, 90 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 033f7af6f2f3..842e49602274 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6885,7 +6885,8 @@ class Sema final { QualType ObjectType, bool EnteringContext, bool &MemberOfUnknownSpecialization, SourceLocation TemplateKWLoc = SourceLocation(), - AssumedTemplateKind *ATK = nullptr); + AssumedTemplateKind *ATK = nullptr, + bool Disambiguation = false); TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS, @@ -6894,7 +6895,8 @@ class Sema final { ParsedType ObjectType, bool EnteringContext, TemplateTy &Template, - bool &MemberOfUnknownSpecialization); + bool &MemberOfUnknownSpecialization, + bool Disambiguation = false); /// Try to resolve an undeclared template name as a type template. /// diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 8a7da4f86b39..50d22a2a8ea7 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -32,24 +32,28 @@ using namespace llvm::opt; // Parses the contents of version.txt in an CUDA installation. It should // contain one line of the from e.g. "CUDA Version 7.5.2". -static CudaVersion ParseCudaVersionFile(const Driver &D, llvm::StringRef V) { +void CudaInstallationDetector::ParseCudaVersionFile(llvm::StringRef V) { + Version = CudaVersion::UNKNOWN; if (!V.startswith("CUDA Version ")) - return CudaVersion::UNKNOWN; + return; V = V.substr(strlen("CUDA Version ")); SmallVector VersionParts; V.split(VersionParts, '.'); if (VersionParts.size() < 2) - return CudaVersion::UNKNOWN; - std::string MajorMinor = join_items(".", VersionParts[0], VersionParts[1]); - CudaVersion Version = CudaStringToVersion(MajorMinor); + return; + DetectedVersion = join_items(".", VersionParts[0], VersionParts[1]); + Version = CudaStringToVersion(DetectedVersion); if (Version != CudaVersion::UNKNOWN) - return Version; + return; - // Issue a warning and assume that the version we've found is compatible with - // the latest version we support. - D.Diag(diag::warn_drv_unknown_cuda_version) - << MajorMinor << CudaVersionToString(CudaVersion::LATEST); - return CudaVersion::LATEST; + Version = CudaVersion::LATEST; + DetectedVersionIsNotSupported = true; +} + +void CudaInstallationDetector::WarnIfUnsupportedVersion() { + if (DetectedVersionIsNotSupported) + D.Diag(diag::warn_drv_unknown_cuda_version) + << DetectedVersion << CudaVersionToString(Version); } CudaInstallationDetector::CudaInstallationDetector( @@ -147,7 +151,7 @@ CudaInstallationDetector::CudaInstallationDetector( // version.txt isn't present. Version = CudaVersion::CUDA_70; } else { - Version = ParseCudaVersionFile(D, (*VersionFile)->getBuffer()); + ParseCudaVersionFile((*VersionFile)->getBuffer()); } if (Version >= CudaVersion::CUDA_90) { @@ -565,8 +569,10 @@ CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple, const Action::OffloadKind OK) : ToolChain(D, Triple, Args), HostTC(HostTC), CudaInstallation(D, HostTC.getTriple(), Args), OK(OK) { - if (CudaInstallation.isValid()) + if (CudaInstallation.isValid()) { + CudaInstallation.WarnIfUnsupportedVersion(); getProgramPaths().push_back(CudaInstallation.getBinPath()); + } // Lookup binaries into the driver directory, this is used to // discover the clang-offload-bundler executable. getProgramPaths().push_back(getDriver().Dir); diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h index 4ee8b6f1fea9..d1e066f93dfb 100644 --- a/clang/lib/Driver/ToolChains/Cuda.h +++ b/clang/lib/Driver/ToolChains/Cuda.h @@ -30,6 +30,8 @@ class CudaInstallationDetector { const Driver &D; bool IsValid = false; CudaVersion Version = CudaVersion::UNKNOWN; + std::string DetectedVersion; + bool DetectedVersionIsNotSupported = false; std::string InstallPath; std::string BinPath; std::string LibPath; @@ -75,6 +77,10 @@ class CudaInstallationDetector { std::string getLibDeviceFile(StringRef Gpu) const { return LibDeviceMap.lookup(Gpu); } + void WarnIfUnsupportedVersion(); + +private: + void ParseCudaVersionFile(llvm::StringRef V); }; namespace tools { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index cdc3506d5c68..6353e14bc41a 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3252,6 +3252,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; if (isTypeConstraintAnnotation()) continue; + if (NextToken().is(tok::annot_template_id)) + // Might have been annotated by TryAnnotateTypeConstraint. + continue; // Eat the scope spec so the identifier is current. ConsumeAnnotationToken(); ParsedAttributesWithRange Attrs(AttrFactory); @@ -3405,6 +3408,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; if (isTypeConstraintAnnotation()) continue; + if (Tok.is(tok::annot_template_id)) + // Might have been annotated by TryAnnotateTypeConstraint. + continue; ParsedAttributesWithRange Attrs(AttrFactory); if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) { if (!Attrs.empty()) { diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 3bc4e3596f12..609640576e9e 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -710,7 +710,8 @@ bool Parser::TryAnnotateTypeConstraint() { /*ObjectType=*/ParsedType(), /*EnteringContext=*/false, PossibleConcept, - MemberOfUnknownSpecialization); + MemberOfUnknownSpecialization, + /*Disambiguation=*/true); if (MemberOfUnknownSpecialization || !PossibleConcept || TNK != TNK_Concept_template) { if (SS.isNotEmpty()) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4f577a3cf748..c38c724ed9b0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -174,7 +174,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, ParsedType ObjectTypePtr, bool EnteringContext, TemplateTy &TemplateResult, - bool &MemberOfUnknownSpecialization) { + bool &MemberOfUnknownSpecialization, + bool Disambiguation) { assert(getLangOpts().CPlusPlus && "No template names in C!"); DeclarationName TName; @@ -204,7 +205,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName); if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext, MemberOfUnknownSpecialization, SourceLocation(), - &AssumedTemplate)) + &AssumedTemplate, Disambiguation)) return TNK_Non_template; if (AssumedTemplate != AssumedTemplateKind::None) { @@ -371,7 +372,8 @@ bool Sema::LookupTemplateName(LookupResult &Found, bool EnteringContext, bool &MemberOfUnknownSpecialization, SourceLocation TemplateKWLoc, - AssumedTemplateKind *ATK) { + AssumedTemplateKind *ATK, + bool Disambiguation) { if (ATK) *ATK = AssumedTemplateKind::None; @@ -494,8 +496,9 @@ bool Sema::LookupTemplateName(LookupResult &Found, } } - if (Found.empty() && !IsDependent) { - // If we did not find any names, attempt to correct any typos. + if (Found.empty() && !IsDependent && !Disambiguation) { + // If we did not find any names, and this is not a disambiguation, attempt + // to correct any typos. DeclarationName Name = Found.getLookupName(); Found.clear(); // Simple filter callback that, for keywords, only accepts the C++ *_cast diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 805fe6684205..0305954a278e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11303,7 +11303,7 @@ TreeTransform::TransformRequiresExpr(RequiresExpr *E) { SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create( - getSema().Context, E->getBody()->getDeclContext(), + getSema().Context, getSema().CurContext, E->getBody()->getBeginLoc()); Sema::ContextRAII SavedContext(getSema(), Body, /*NewThisContext*/false); diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp index 40c1ba88354f..55d3761c036f 100644 --- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp @@ -152,13 +152,50 @@ static bool matchSelectWithOptionalNotCond(Value *V, Value *&Cond, Value *&A, std::swap(A, B); } - // Set flavor if we find a match, or set it to unknown otherwise; in - // either case, return true to indicate that this is a select we can - // process. - if (auto *CmpI = dyn_cast(Cond)) - Flavor = matchDecomposedSelectPattern(CmpI, A, B, A, B).Flavor; - else - Flavor = SPF_UNKNOWN; + // Match canonical forms of abs/nabs/min/max. We are not using ValueTracking's + // more powerful matchSelectPattern() because it may rely on instruction flags + // such as "nsw". That would be incompatible with the current hashing + // mechanism that may remove flags to increase the likelihood of CSE. + + // These are the canonical forms of abs(X) and nabs(X) created by instcombine: + // %N = sub i32 0, %X + // %C = icmp slt i32 %X, 0 + // %ABS = select i1 %C, i32 %N, i32 %X + // + // %N = sub i32 0, %X + // %C = icmp slt i32 %X, 0 + // %NABS = select i1 %C, i32 %X, i32 %N + Flavor = SPF_UNKNOWN; + CmpInst::Predicate Pred; + if (match(Cond, m_ICmp(Pred, m_Specific(B), m_ZeroInt())) && + Pred == ICmpInst::ICMP_SLT && match(A, m_Neg(m_Specific(B)))) { + // ABS: B < 0 ? -B : B + Flavor = SPF_ABS; + return true; + } + if (match(Cond, m_ICmp(Pred, m_Specific(A), m_ZeroInt())) && + Pred == ICmpInst::ICMP_SLT && match(B, m_Neg(m_Specific(A)))) { + // NABS: A < 0 ? A : -A + Flavor = SPF_NABS; + return true; + } + + if (!match(Cond, m_ICmp(Pred, m_Specific(A), m_Specific(B)))) { + // Check for commuted variants of min/max by swapping predicate. + // If we do not match the standard or commuted patterns, this is not a + // recognized form of min/max, but it is still a select, so return true. + if (!match(Cond, m_ICmp(Pred, m_Specific(B), m_Specific(A)))) + return true; + Pred = ICmpInst::getSwappedPredicate(Pred); + } + + switch (Pred) { + case CmpInst::ICMP_UGT: Flavor = SPF_UMAX; break; + case CmpInst::ICMP_ULT: Flavor = SPF_UMIN; break; + case CmpInst::ICMP_SGT: Flavor = SPF_SMAX; break; + case CmpInst::ICMP_SLT: Flavor = SPF_SMIN; break; + default: break; + } return true; }