aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-06-04 19:00:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-04 19:00:19 +0000
commit3b922bd9516f6dc5146815ed8d4363fcbe97997f (patch)
treecfcc71cf8890081a38ebce9b18028a4fc97b6bc7
parent791701a7dc6225242c41502cb3ed6874623c1785 (diff)
Vendor import of llvm-project branch release/16.x llvmorg-16.0.5-0-g185b81e034ba (aka 16.0.5 release).vendor/llvm-project/llvmorg-16.0.5-0-g185b81e034ba
-rw-r--r--clang/include/clang/AST/ExprConcepts.h8
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--clang/include/clang/Sema/Initialization.h18
-rw-r--r--clang/include/clang/Sema/Sema.h3
-rw-r--r--clang/lib/AST/ASTContext.cpp3
-rw-r--r--clang/lib/AST/ExprConcepts.cpp19
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp1
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.cpp6
-rw-r--r--clang/lib/Sema/SemaAccess.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp26
-rw-r--r--clang/lib/Sema/SemaInit.cpp335
-rw-r--r--libcxx/include/__config2
-rw-r--r--lld/docs/WebAssembly.rst33
-rw-r--r--llvm/include/llvm/Analysis/AliasAnalysis.h9
-rw-r--r--llvm/include/llvm/Analysis/TargetLibraryInfo.h12
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.cpp7
-rw-r--r--llvm/lib/Target/Hexagon/HexagonPatterns.td24
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp27
-rw-r--r--llvm/lib/Target/X86/X86InstrAVX512.td21
-rw-r--r--llvm/tools/llvm-mca/llvm-mca.cpp19
21 files changed, 403 insertions, 178 deletions
diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h
index f02c140c14c1..746a5b2fbfc6 100644
--- a/clang/include/clang/AST/ExprConcepts.h
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -64,6 +64,7 @@ protected:
const ConstraintSatisfaction *Satisfaction);
ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
@@ -85,6 +86,13 @@ public:
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack);
+ static ConceptSpecializationExpr *
+ Create(const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ImplicitConceptSpecializationDecl *SpecDecl,
+ const ConstraintSatisfaction *Satisfaction, bool Dependent,
+ bool ContainsUnexpandedParameterPack);
+
ArrayRef<TemplateArgument> getTemplateArguments() const {
return SpecDecl->getTemplateArguments();
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bfe582d8252f..6d72040c4b87 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2124,7 +2124,8 @@ def err_init_conversion_failed : Error<
"exception object|a member subobject|an array element|a new value|a value|a "
"base class|a constructor delegation|a vector element|a block element|a "
"block element|a complex element|a lambda capture|a compound literal "
- "initializer|a related result|a parameter of CF audited function}0 "
+ "initializer|a related result|a parameter of CF audited function|a "
+ "structured binding|a member subobject}0 "
"%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
"with an %select{rvalue|lvalue}2 of incompatible type}1,3"
"%select{|: different classes%diff{ ($ vs $)|}5,6"
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index e5a98ba97f4f..e1bbea0d118d 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -123,6 +123,10 @@ public:
/// decomposition declaration.
EK_Binding,
+ /// The entity being initialized is a non-static data member subobject of an
+ /// object initialized via parenthesized aggregate initialization.
+ EK_ParenAggInitMember,
+
// Note: err_init_conversion_failed in DiagnosticSemaKinds.td uses this
// enum as an index for its first %select. When modifying this list,
// that diagnostic text needs to be updated as well.
@@ -227,8 +231,10 @@ private:
/// Create the initialization entity for a member subobject.
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
- bool Implicit, bool DefaultMemberInit)
- : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ bool Implicit, bool DefaultMemberInit,
+ bool IsParenAggInit = false)
+ : Kind(IsParenAggInit ? EK_ParenAggInitMember : EK_Member),
+ Parent(Parent), Type(Member->getType()),
Variable{Member, Implicit, DefaultMemberInit} {}
/// Create the initialization entity for an array element.
@@ -388,6 +394,14 @@ public:
return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);
}
+ /// Create the initialization entity for a member subobject initialized via
+ /// parenthesized aggregate init.
+ static InitializedEntity InitializeMemberFromParenAggInit(FieldDecl *Member) {
+ return InitializedEntity(Member, /*Parent=*/nullptr, /*Implicit=*/false,
+ /*DefaultMemberInit=*/false,
+ /*IsParenAggInit=*/true);
+ }
+
/// Create the initialization entity for a default member initializer.
static InitializedEntity
InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d40dacb5aa0f..e57955f16bdd 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1394,6 +1394,9 @@ public:
/// A stack of expression evaluation contexts.
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+ // Set of failed immediate invocations to avoid double diagnosing.
+ llvm::SmallPtrSet<ConstantExpr *, 4> FailedImmediateInvocations;
+
/// Emit a warning for all pending noderef expressions that we recorded.
void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 2884fe660422..8054eb2e12d3 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -765,7 +765,8 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC,
CSE->getNamedConcept()->getLocation(), NewConverted);
Expr *NewIDC = ConceptSpecializationExpr::Create(
- C, CSE->getNamedConcept(), CSD, nullptr, CSE->isInstantiationDependent(),
+ C, CSE->getNamedConcept(), CSE->getTemplateArgsAsWritten(), CSD,
+ /*Satisfaction=*/nullptr, CSE->isInstantiationDependent(),
CSE->containsUnexpandedParameterPack());
if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC))
diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp
index fc8f1eb2abf1..cdc13c2d3969 100644
--- a/clang/lib/AST/ExprConcepts.cpp
+++ b/clang/lib/AST/ExprConcepts.cpp
@@ -59,6 +59,15 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
: Expr(ConceptSpecializationExprClass, Empty) {}
ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
+ const ASTContext &C, ConceptDecl *NamedConcept,
+ ImplicitConceptSpecializationDecl *SpecDecl,
+ const ConstraintSatisfaction *Satisfaction, bool Dependent,
+ bool ContainsUnexpandedParameterPack) {
+ return Create(C, NamedConcept, /*ArgsAsWritten*/ nullptr, SpecDecl, Satisfaction,
+ Dependent, ContainsUnexpandedParameterPack);
+}
+
+ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
const ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
@@ -72,13 +81,14 @@ ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
ConceptSpecializationExpr::ConceptSpecializationExpr(
const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack)
: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
DeclarationNameInfo(), NamedConcept, NamedConcept,
- nullptr),
+ ArgsAsWritten),
SpecDecl(SpecDecl),
Satisfaction(Satisfaction
? ASTConstraintSatisfaction::Create(C, *Satisfaction)
@@ -95,12 +105,13 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(
ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack) {
- return new (C)
- ConceptSpecializationExpr(C, NamedConcept, SpecDecl, Satisfaction,
- Dependent, ContainsUnexpandedParameterPack);
+ return new (C) ConceptSpecializationExpr(C, NamedConcept, ArgsAsWritten,
+ SpecDecl, Satisfaction, Dependent,
+ ContainsUnexpandedParameterPack);
}
const TypeConstraint *
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 238507e06335..77554aa2c462 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7801,6 +7801,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
} else {
D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs;
}
+ A->claim();
}
}
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
index 44034e44adec..3cc68673cd13 100644
--- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
@@ -113,7 +113,11 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
continue;
}
if (Style.isCpp()) {
- if (const auto Pos = Text.find_first_of("_i"); Pos != StringRef::npos) {
+ // Hex alpha digits a-f/A-F must be at the end of the string literal.
+ StringRef Suffixes = "_himnsuyd";
+ if (const auto Pos =
+ Text.find_first_of(IsBase16 ? Suffixes.drop_back() : Suffixes);
+ Pos != StringRef::npos) {
Text = Text.substr(0, Pos);
Length = Pos;
}
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index cbda62497e6a..4a39c2d065e6 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1651,7 +1651,8 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
<< Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
break;
- case InitializedEntity::EK_Member: {
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember: {
const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
PD = PDiag(diag::err_access_field_ctor);
PD << Field->getType() << getSpecialMember(Constructor);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 051fad04219f..0fbef1cc8b52 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8693,7 +8693,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
// Check that SVE types are only used in functions with SVE available.
- if (T->isSVESizelessBuiltinType() && CurContext->isFunctionOrMethod()) {
+ if (T->isSVESizelessBuiltinType() && isa<FunctionDecl>(CurContext)) {
const FunctionDecl *FD = cast<FunctionDecl>(CurContext);
llvm::StringMap<bool> CallerFeatureMap;
Context.getFunctionFeatureMap(CallerFeatureMap, FD);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2842add2cc4a..9d865f487098 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17805,6 +17805,7 @@ static void EvaluateAndDiagnoseImmediateInvocation(
bool Result = CE->EvaluateAsConstantExpr(
Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation);
if (!Result || !Notes.empty()) {
+ SemaRef.FailedImmediateInvocations.insert(CE);
Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
if (auto *FunctionalCast = dyn_cast<CXXFunctionalCastExpr>(InnerExpr))
InnerExpr = FunctionalCast->getSubExpr();
@@ -17849,10 +17850,16 @@ static void RemoveNestedImmediateInvocation(
[E](Sema::ImmediateInvocationCandidate Elem) {
return Elem.getPointer() == E;
});
- assert(It != IISet.rend() &&
- "ConstantExpr marked IsImmediateInvocation should "
- "be present");
- It->setInt(1); // Mark as deleted
+ // It is possible that some subexpression of the current immediate
+ // invocation was handled from another expression evaluation context. Do
+ // not handle the current immediate invocation if some of its
+ // subexpressions failed before.
+ if (It == IISet.rend()) {
+ if (SemaRef.FailedImmediateInvocations.contains(E))
+ CurrentII->setInt(1);
+ } else {
+ It->setInt(1); // Mark as deleted
+ }
}
ExprResult TransformConstantExpr(ConstantExpr *E) {
if (!E->isImmediateInvocation())
@@ -17925,10 +17932,13 @@ HandleImmediateInvocations(Sema &SemaRef,
SemaRef.RebuildingImmediateInvocation)
return;
- /// When we have more then 1 ImmediateInvocationCandidates we need to check
- /// for nested ImmediateInvocationCandidates. when we have only 1 we only
- /// need to remove ReferenceToConsteval in the immediate invocation.
- if (Rec.ImmediateInvocationCandidates.size() > 1) {
+ /// When we have more than 1 ImmediateInvocationCandidates or previously
+ /// failed immediate invocations, we need to check for nested
+ /// ImmediateInvocationCandidates in order to avoid duplicate diagnostics.
+ /// Otherwise we only need to remove ReferenceToConsteval in the immediate
+ /// invocation.
+ if (Rec.ImmediateInvocationCandidates.size() > 1 ||
+ !SemaRef.FailedImmediateInvocations.empty()) {
/// Prevent sema calls during the tree transform from adding pointers that
/// are already in the sets.
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 44adb167dcc0..cc8d1405ec55 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -1152,6 +1152,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_TemplateParameter:
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_ParenAggInitMember:
// Extra braces here are suspicious.
DiagID = diag::warn_braces_around_init;
break;
@@ -3348,6 +3349,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_Variable:
case EK_Member:
+ case EK_ParenAggInitMember:
case EK_Binding:
case EK_TemplateParameter:
return Variable.VariableOrMember->getDeclName();
@@ -3379,6 +3381,7 @@ ValueDecl *InitializedEntity::getDecl() const {
switch (getKind()) {
case EK_Variable:
case EK_Member:
+ case EK_ParenAggInitMember:
case EK_Binding:
case EK_TemplateParameter:
return Variable.VariableOrMember;
@@ -3420,6 +3423,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Parameter_CF_Audited:
case EK_TemplateParameter:
case EK_Member:
+ case EK_ParenAggInitMember:
case EK_Binding:
case EK_New:
case EK_Temporary:
@@ -3454,7 +3458,10 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
case EK_Result: OS << "Result"; break;
case EK_StmtExprResult: OS << "StmtExprResult"; break;
case EK_Exception: OS << "Exception"; break;
- case EK_Member: OS << "Member"; break;
+ case EK_Member:
+ case EK_ParenAggInitMember:
+ OS << "Member";
+ break;
case EK_Binding: OS << "Binding"; break;
case EK_New: OS << "New"; break;
case EK_Temporary: OS << "Temporary"; break;
@@ -5274,179 +5281,224 @@ static void TryOrBuildParenListInitialization(
Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
ExprResult *Result = nullptr) {
- unsigned ArgIndexToProcess = 0;
+ unsigned EntityIndexToProcess = 0;
SmallVector<Expr *, 4> InitExprs;
QualType ResultType;
Expr *ArrayFiller = nullptr;
FieldDecl *InitializedFieldInUnion = nullptr;
- // Process entities (i.e. array members, base classes, or class fields) by
- // adding an initialization expression to InitExprs for each entity to
- // initialize.
- auto ProcessEntities = [&](auto Range) -> bool {
- bool IsUnionType = Entity.getType()->isUnionType();
- for (InitializedEntity SubEntity : Range) {
- // Unions should only have one initializer expression.
- // If there are more initializers than it will be caught when we check
- // whether Index equals Args.size().
- if (ArgIndexToProcess == 1 && IsUnionType)
- return true;
-
- bool IsMember = SubEntity.getKind() == InitializedEntity::EK_Member;
-
- // Unnamed bitfields should not be initialized at all, either with an arg
- // or by default.
- if (IsMember && cast<FieldDecl>(SubEntity.getDecl())->isUnnamedBitfield())
- continue;
-
- if (ArgIndexToProcess < Args.size()) {
- // There are still expressions in Args that haven't been processed.
- // Let's match them to the current entity to initialize.
- Expr *E = Args[ArgIndexToProcess++];
-
- // Incomplete array types indicate flexible array members. Do not allow
- // paren list initializations of structs with these members, as GCC
- // doesn't either.
- if (IsMember) {
- auto *FD = cast<FieldDecl>(SubEntity.getDecl());
- if (FD->getType()->isIncompleteArrayType()) {
- if (!VerifyOnly) {
- S.Diag(E->getBeginLoc(), diag::err_flexible_array_init)
- << SourceRange(E->getBeginLoc(), E->getEndLoc());
- S.Diag(FD->getLocation(), diag::note_flexible_array_member) << FD;
- }
- Sequence.SetFailed(
- InitializationSequence::FK_ParenthesizedListInitFailed);
- return false;
- }
- }
-
- InitializationKind SubKind = InitializationKind::CreateForInit(
- E->getExprLoc(), /*isDirectInit=*/false, E);
- InitializationSequence SubSeq(S, SubEntity, SubKind, E);
-
- if (SubSeq.Failed()) {
- if (!VerifyOnly)
- SubSeq.Diagnose(S, SubEntity, SubKind, E);
- else
- Sequence.SetFailed(
- InitializationSequence::FK_ParenthesizedListInitFailed);
+ auto HandleInitializedEntity = [&](const InitializedEntity &SubEntity,
+ const InitializationKind &SubKind,
+ Expr *Arg, Expr **InitExpr = nullptr) {
+ InitializationSequence IS = [&]() {
+ if (Arg)
+ return InitializationSequence(S, SubEntity, SubKind, Arg);
+ return InitializationSequence(S, SubEntity, SubKind, std::nullopt);
+ }();
- return false;
- }
- if (!VerifyOnly) {
- ExprResult ER = SubSeq.Perform(S, SubEntity, SubKind, E);
- InitExprs.push_back(ER.get());
- if (IsMember && IsUnionType)
- InitializedFieldInUnion = cast<FieldDecl>(SubEntity.getDecl());
- }
+ if (IS.Failed()) {
+ if (!VerifyOnly) {
+ if (Arg)
+ IS.Diagnose(S, SubEntity, SubKind, Arg);
+ else
+ IS.Diagnose(S, SubEntity, SubKind, std::nullopt);
} else {
- // We've processed all of the args, but there are still entities that
- // have to be initialized.
- if (IsMember) {
- // C++ [dcl.init]p17.6.2.2
- // The remaining elements are initialized with their default member
- // initializers, if any
- auto *FD = cast<FieldDecl>(SubEntity.getDecl());
- if (FD->hasInClassInitializer()) {
- if (!VerifyOnly) {
- ExprResult DIE = S.BuildCXXDefaultInitExpr(FD->getLocation(), FD);
- if (DIE.isInvalid())
- return false;
- S.checkInitializerLifetime(SubEntity, DIE.get());
- InitExprs.push_back(DIE.get());
- }
- continue;
- }
- }
- // Remaining class elements without default member initializers and
- // array elements are value initialized:
- //
- // C++ [dcl.init]p17.6.2.2
- // The remaining elements...otherwise are value initialzed
- //
- // C++ [dcl.init]p17.5
- // if the destination type is an array, the object is initialized as
- // . follows. Let x1, . . . , xk be the elements of the expression-list
- // ...Let n denote the array size...the ith array element is...value-
- // initialized for each k < i <= n.
- InitializationKind SubKind = InitializationKind::CreateValue(
- Kind.getLocation(), Kind.getLocation(), Kind.getLocation(), true);
- InitializationSequence SubSeq(S, SubEntity, SubKind, std::nullopt);
- if (SubSeq.Failed()) {
- if (!VerifyOnly)
- SubSeq.Diagnose(S, SubEntity, SubKind, std::nullopt);
- return false;
- }
- if (!VerifyOnly) {
- ExprResult ER = SubSeq.Perform(S, SubEntity, SubKind, std::nullopt);
- if (SubEntity.getKind() == InitializedEntity::EK_ArrayElement) {
- ArrayFiller = ER.get();
- return true;
- }
- InitExprs.push_back(ER.get());
- }
+ Sequence.SetFailed(
+ InitializationSequence::FK_ParenthesizedListInitFailed);
}
+
+ return false;
+ }
+ if (!VerifyOnly) {
+ ExprResult ER;
+ if (Arg)
+ ER = IS.Perform(S, SubEntity, SubKind, Arg);
+ else
+ ER = IS.Perform(S, SubEntity, SubKind, std::nullopt);
+ if (InitExpr)
+ *InitExpr = ER.get();
+ else
+ InitExprs.push_back(ER.get());
}
return true;
};
if (const ArrayType *AT =
S.getASTContext().getAsArrayType(Entity.getType())) {
-
SmallVector<InitializedEntity, 4> ElementEntities;
uint64_t ArrayLength;
- // C++ [dcl.init]p17.5
+ // C++ [dcl.init]p16.5
// if the destination type is an array, the object is initialized as
// follows. Let x1, . . . , xk be the elements of the expression-list. If
- // the destination type is an array of unknown bound, it is define as
+ // the destination type is an array of unknown bound, it is defined as
// having k elements.
if (const ConstantArrayType *CAT =
- S.getASTContext().getAsConstantArrayType(Entity.getType()))
+ S.getASTContext().getAsConstantArrayType(Entity.getType())) {
ArrayLength = CAT->getSize().getZExtValue();
- else
+ ResultType = Entity.getType();
+ } else if (const VariableArrayType *VAT =
+ S.getASTContext().getAsVariableArrayType(Entity.getType())) {
+ // Braced-initialization of variable array types is not allowed, even if
+ // the size is greater than or equal to the number of args, so we don't
+ // allow them to be initialized via parenthesized aggregate initialization
+ // either.
+ const Expr *SE = VAT->getSizeExpr();
+ S.Diag(SE->getBeginLoc(), diag::err_variable_object_no_init)
+ << SE->getSourceRange();
+ return;
+ } else {
+ assert(isa<IncompleteArrayType>(Entity.getType()));
ArrayLength = Args.size();
+ }
+ EntityIndexToProcess = ArrayLength;
- if (ArrayLength >= Args.size()) {
- for (uint64_t I = 0; I < ArrayLength; ++I)
- ElementEntities.push_back(
- InitializedEntity::InitializeElement(S.getASTContext(), I, Entity));
-
- if (!ProcessEntities(ElementEntities))
+ // ...the ith array element is copy-initialized with xi for each
+ // 1 <= i <= k
+ for (Expr *E : Args) {
+ InitializedEntity SubEntity = InitializedEntity::InitializeElement(
+ S.getASTContext(), EntityIndexToProcess, Entity);
+ InitializationKind SubKind = InitializationKind::CreateForInit(
+ E->getExprLoc(), /*isDirectInit=*/false, E);
+ if (!HandleInitializedEntity(SubEntity, SubKind, E))
+ return;
+ }
+ // ...and value-initialized for each k < i <= n;
+ if (ArrayLength > Args.size()) {
+ InitializedEntity SubEntity = InitializedEntity::InitializeElement(
+ S.getASTContext(), Args.size(), Entity);
+ InitializationKind SubKind = InitializationKind::CreateValue(
+ Kind.getLocation(), Kind.getLocation(), Kind.getLocation(), true);
+ if (!HandleInitializedEntity(SubEntity, SubKind, nullptr, &ArrayFiller))
return;
+ }
+ if (ResultType.isNull()) {
ResultType = S.Context.getConstantArrayType(
AT->getElementType(), llvm::APInt(/*numBits=*/32, ArrayLength),
- nullptr, ArrayType::Normal, 0);
+ /*SizeExpr=*/nullptr, ArrayType::Normal, 0);
}
} else if (auto *RT = Entity.getType()->getAs<RecordType>()) {
+ bool IsUnion = RT->isUnionType();
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- auto BaseRange = map_range(RD->bases(), [&](auto &base) {
- return InitializedEntity::InitializeBase(S.getASTContext(), &base, false,
- &Entity);
- });
- auto FieldRange = map_range(RD->fields(), [](auto *field) {
- return InitializedEntity::InitializeMember(field);
- });
+ if (!IsUnion) {
+ for (const CXXBaseSpecifier &Base : RD->bases()) {
+ InitializedEntity SubEntity = InitializedEntity::InitializeBase(
+ S.getASTContext(), &Base, false, &Entity);
+ if (EntityIndexToProcess < Args.size()) {
+ // C++ [dcl.init]p16.6.2.2.
+ // ...the object is initialized is follows. Let e1, ..., en be the
+ // elements of the aggregate([dcl.init.aggr]). Let x1, ..., xk be
+ // the elements of the expression-list...The element ei is
+ // copy-initialized with xi for 1 <= i <= k.
+ Expr *E = Args[EntityIndexToProcess];
+ InitializationKind SubKind = InitializationKind::CreateForInit(
+ E->getExprLoc(), /*isDirectInit=*/false, E);
+ if (!HandleInitializedEntity(SubEntity, SubKind, E))
+ return;
+ } else {
+ // We've processed all of the args, but there are still base classes
+ // that have to be initialized.
+ // C++ [dcl.init]p17.6.2.2
+ // The remaining elements...otherwise are value initialzed
+ InitializationKind SubKind = InitializationKind::CreateValue(
+ Kind.getLocation(), Kind.getLocation(), Kind.getLocation(),
+ /*IsImplicit=*/true);
+ if (!HandleInitializedEntity(SubEntity, SubKind, nullptr))
+ return;
+ }
+ EntityIndexToProcess++;
+ }
+ }
- if (!ProcessEntities(BaseRange))
- return;
+ for (FieldDecl *FD : RD->fields()) {
+ // Unnamed bitfields should not be initialized at all, either with an arg
+ // or by default.
+ if (FD->isUnnamedBitfield())
+ continue;
- if (!ProcessEntities(FieldRange))
- return;
+ InitializedEntity SubEntity =
+ InitializedEntity::InitializeMemberFromParenAggInit(FD);
+ if (EntityIndexToProcess < Args.size()) {
+ // ...The element ei is copy-initialized with xi for 1 <= i <= k.
+ Expr *E = Args[EntityIndexToProcess];
+
+ // Incomplete array types indicate flexible array members. Do not allow
+ // paren list initializations of structs with these members, as GCC
+ // doesn't either.
+ if (FD->getType()->isIncompleteArrayType()) {
+ if (!VerifyOnly) {
+ S.Diag(E->getBeginLoc(), diag::err_flexible_array_init)
+ << SourceRange(E->getBeginLoc(), E->getEndLoc());
+ S.Diag(FD->getLocation(), diag::note_flexible_array_member) << FD;
+ }
+ Sequence.SetFailed(
+ InitializationSequence::FK_ParenthesizedListInitFailed);
+ return;
+ }
+
+ InitializationKind SubKind = InitializationKind::CreateForInit(
+ E->getExprLoc(), /*isDirectInit=*/false, E);
+ if (!HandleInitializedEntity(SubEntity, SubKind, E))
+ return;
+
+ // Unions should have only one initializer expression, so we bail out
+ // after processing the first field. If there are more initializers then
+ // it will be caught when we later check whether EntityIndexToProcess is
+ // less than Args.size();
+ if (IsUnion) {
+ InitializedFieldInUnion = FD;
+ EntityIndexToProcess = 1;
+ break;
+ }
+ } else {
+ // We've processed all of the args, but there are still members that
+ // have to be initialized.
+ if (FD->hasInClassInitializer()) {
+ if (!VerifyOnly) {
+ // C++ [dcl.init]p16.6.2.2
+ // The remaining elements are initialized with their default
+ // member initializers, if any
+ ExprResult DIE = S.BuildCXXDefaultInitExpr(FD->getLocation(), FD);
+ if (DIE.isInvalid())
+ return;
+ S.checkInitializerLifetime(SubEntity, DIE.get());
+ InitExprs.push_back(DIE.get());
+ }
+ } else {
+ // C++ [dcl.init]p17.6.2.2
+ // The remaining elements...otherwise are value initialzed
+ if (FD->getType()->isReferenceType()) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_ParenthesizedListInitFailed);
+ if (!VerifyOnly) {
+ SourceRange SR = Kind.getParenOrBraceRange();
+ S.Diag(SR.getEnd(), diag::err_init_reference_member_uninitialized)
+ << FD->getType() << SR;
+ S.Diag(FD->getLocation(), diag::note_uninit_reference_member);
+ }
+ return;
+ }
+ InitializationKind SubKind = InitializationKind::CreateValue(
+ Kind.getLocation(), Kind.getLocation(), Kind.getLocation(), true);
+ if (!HandleInitializedEntity(SubEntity, SubKind, nullptr))
+ return;
+ }
+ }
+ EntityIndexToProcess++;
+ }
ResultType = Entity.getType();
}
// Not all of the args have been processed, so there must've been more args
- // then were required to initialize the element.
- if (ArgIndexToProcess < Args.size()) {
+ // than were required to initialize the element.
+ if (EntityIndexToProcess < Args.size()) {
Sequence.SetFailed(InitializationSequence::FK_ParenthesizedListInitFailed);
if (!VerifyOnly) {
QualType T = Entity.getType();
int InitKind = T->isArrayType() ? 0 : T->isUnionType() ? 3 : 4;
- SourceRange ExcessInitSR(Args[ArgIndexToProcess]->getBeginLoc(),
+ SourceRange ExcessInitSR(Args[EntityIndexToProcess]->getBeginLoc(),
Args.back()->getEndLoc());
S.Diag(Kind.getLocation(), diag::err_excess_initializers)
<< InitKind << ExcessInitSR;
@@ -6412,6 +6464,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
return Sema::AA_Converting;
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Binding:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
@@ -6432,6 +6485,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Result:
case InitializedEntity::EK_StmtExprResult:
case InitializedEntity::EK_New:
@@ -6476,6 +6530,7 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) {
return false;
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Binding:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Parameter:
@@ -6512,6 +6567,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_TemplateParameter:
@@ -7080,7 +7136,15 @@ static LifetimeResult getEntityLifetime(
case InitializedEntity::EK_Exception:
// FIXME: Can we diagnose lifetime problems with exceptions?
return {nullptr, LK_FullExpression};
+
+ case InitializedEntity::EK_ParenAggInitMember:
+ // -- A temporary object bound to a reference element of an aggregate of
+ // class type initialized from a parenthesized expression-list
+ // [dcl.init, 9.3] persists until the completion of the full-expression
+ // containing the expression-list.
+ return {nullptr, LK_FullExpression};
}
+
llvm_unreachable("unknown entity kind");
}
@@ -9196,7 +9260,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
S.checkInitializerLifetime(Entity, Init);
// Diagnose non-fatal problems with the completed initialization.
- if (Entity.getKind() == InitializedEntity::EK_Member &&
+ if (InitializedEntity::EntityKind EK = Entity.getKind();
+ (EK == InitializedEntity::EK_Member ||
+ EK == InitializedEntity::EK_ParenAggInitMember) &&
cast<FieldDecl>(Entity.getDecl())->isBitField())
S.CheckBitFieldInitialization(Kind.getLocation(),
cast<FieldDecl>(Entity.getDecl()),
@@ -9650,7 +9716,8 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_No_Viable_Function:
if (Kind.getKind() == InitializationKind::IK_Default &&
(Entity.getKind() == InitializedEntity::EK_Base ||
- Entity.getKind() == InitializedEntity::EK_Member) &&
+ Entity.getKind() == InitializedEntity::EK_Member ||
+ Entity.getKind() == InitializedEntity::EK_ParenAggInitMember) &&
isa<CXXConstructorDecl>(S.CurContext)) {
// This is implicit default initialization of a member or
// base within a constructor. If no viable function was
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 9009b9014abb..d7ba71906e26 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -38,7 +38,7 @@
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 16.0.1 == 16.00.01), _LIBCPP_VERSION is
// defined to XXYYZZ.
-# define _LIBCPP_VERSION 160004
+# define _LIBCPP_VERSION 160005
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
diff --git a/lld/docs/WebAssembly.rst b/lld/docs/WebAssembly.rst
index c40d4b322080..dad3177e2c7d 100644
--- a/lld/docs/WebAssembly.rst
+++ b/lld/docs/WebAssembly.rst
@@ -75,6 +75,11 @@ WebAssembly-specific options:
flag which corresponds to ``--unresolve-symbols=ignore`` +
``--import-undefined``.
+.. option:: --allow-undefined-file=<filename>
+
+ Like ``--allow-undefined``, but the filename specified a flat list of
+ symbols, one per line, which are allowed to be undefined.
+
.. option:: --unresolved-symbols=<method>
This is a more full featured version of ``--allow-undefined``.
@@ -182,11 +187,39 @@ Imports
By default no undefined symbols are allowed in the final binary. The flag
``--allow-undefined`` results in a WebAssembly import being defined for each
undefined symbol. It is then up to the runtime to provide such symbols.
+``--allow-undefined-file`` is the same but allows a list of symbols to be
+specified.
Alternatively symbols can be marked in the source code as with the
``import_name`` and/or ``import_module`` clang attributes which signals that
they are expected to be undefined at static link time.
+Stub Libraries
+~~~~~~~~~~~~~~
+
+Another way to specify imports and exports is via a "stub library". This
+feature is inspired by the ELF stub objects which are supported by the Solaris
+linker. Stub libraries are text files that can be passed as normal linker
+inputs, similar to how linker scripts can be passed to the ELF linker. The stub
+library is a stand-in for a set of symbols that will be available at runtime,
+but doesn't contain any actual code or data. Instead it contains just a list of
+symbols, one per line. Each symbol can specify zero or more dependencies.
+These dependencies are symbols that must be defined, and exported, by the output
+module if the symbol is question is imported/required by the output module.
+
+For example, imagine the runtime provides an external symbol ``foo`` that
+depends on the ``malloc`` and ``free``. This can be expressed simply as::
+
+ #STUB
+ foo: malloc,free
+
+Here we are saying that ``foo`` is allowed to be imported (undefined) but that
+if it is imported, then the output module must also export ``malloc`` and
+``free`` to the runtime. If ``foo`` is imported (undefined), but the output
+module does not define ``malloc`` and ``free`` then the link will fail.
+
+Stub libraries must begin with ``#STUB`` on a line by itself.
+
Garbage Collection
~~~~~~~~~~~~~~~~~~
diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h
index 953e15e358f1..8ac6e7dac63e 100644
--- a/llvm/include/llvm/Analysis/AliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -116,6 +116,15 @@ public:
operator Kind() const { return static_cast<Kind>(Alias); }
+ bool operator==(const AliasResult &Other) const {
+ return Alias == Other.Alias && HasOffset == Other.HasOffset &&
+ Offset == Other.Offset;
+ }
+ bool operator!=(const AliasResult &Other) const { return !(*this == Other); }
+
+ bool operator==(Kind K) const { return Alias == K; }
+ bool operator!=(Kind K) const { return !(*this == K); }
+
constexpr bool hasOffset() const { return HasOffset; }
constexpr int32_t getOffset() const {
assert(HasOffset && "No offset!");
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index 8fcfbdbd6665..951945f7b765 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -408,14 +408,14 @@ public:
ShouldExtI32Param = true;
ShouldExtI32Return = true;
}
- // Mips and riscv64, on the other hand, needs signext on i32 parameters
- // corresponding to both signed and unsigned ints.
- if (T.isMIPS() || T.isRISCV64()) {
+ // LoongArch, Mips, and riscv64, on the other hand, need signext on i32
+ // parameters corresponding to both signed and unsigned ints.
+ if (T.isLoongArch() || T.isMIPS() || T.isRISCV64()) {
ShouldSignExtI32Param = true;
}
- // riscv64 needs signext on i32 returns corresponding to both signed and
- // unsigned ints.
- if (T.isRISCV64()) {
+ // LoongArch and riscv64 need signext on i32 returns corresponding to both
+ // signed and unsigned ints.
+ if (T.isLoongArch() || T.isRISCV64()) {
ShouldSignExtI32Return = true;
}
}
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 202fc473f9e4..609a383426d6 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1628,7 +1628,7 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
ISD::UADDO, ISD::SSUBO, ISD::USUBO, ISD::SMUL_LOHI, ISD::UMUL_LOHI,
// Logical/bit:
ISD::AND, ISD::OR, ISD::XOR, ISD::ROTL, ISD::ROTR,
- ISD::CTPOP, ISD::CTLZ, ISD::CTTZ,
+ ISD::CTPOP, ISD::CTLZ, ISD::CTTZ, ISD::BSWAP, ISD::BITREVERSE,
// Floating point arithmetic/math functions:
ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FMA, ISD::FDIV,
ISD::FREM, ISD::FNEG, ISD::FABS, ISD::FSQRT, ISD::FSIN,
@@ -1701,8 +1701,11 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::OR, NativeVT, Legal);
setOperationAction(ISD::XOR, NativeVT, Legal);
- if (NativeVT.getVectorElementType() != MVT::i1)
+ if (NativeVT.getVectorElementType() != MVT::i1) {
setOperationAction(ISD::SPLAT_VECTOR, NativeVT, Legal);
+ setOperationAction(ISD::BSWAP, NativeVT, Legal);
+ setOperationAction(ISD::BITREVERSE, NativeVT, Legal);
+ }
}
for (MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32}) {
diff --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td
index a75ac0e1378e..375e519a6848 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatterns.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td
@@ -117,8 +117,8 @@ def usat: PatFrag<(ops node:$V, node:$Ty), (HexagonUSAT node:$V, node:$Ty)>;
// Pattern fragments to extract the low and high subregisters from a
// 64-bit value.
-def LoReg: OutPatFrag<(ops node:$Rs), (EXTRACT_SUBREG (i64 $Rs), isub_lo)>;
-def HiReg: OutPatFrag<(ops node:$Rs), (EXTRACT_SUBREG (i64 $Rs), isub_hi)>;
+def LoReg: OutPatFrag<(ops node:$Rs), (EXTRACT_SUBREG $Rs, isub_lo)>;
+def HiReg: OutPatFrag<(ops node:$Rs), (EXTRACT_SUBREG $Rs, isub_hi)>;
def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{
return isOrEquivalentToAdd(N);
@@ -1123,6 +1123,12 @@ def: Pat<(bswap I32:$Rs), (A2_swiz I32:$Rs)>;
def: Pat<(bswap I64:$Rss), (Combinew (A2_swiz (LoReg $Rss)),
(A2_swiz (HiReg $Rss)))>;
+def: Pat<(bswap V2I16:$Rs), (A2_combine_lh (A2_swiz $Rs), (A2_swiz $Rs))>;
+def: Pat<(bswap V2I32:$Rs), (Combinew (A2_swiz (HiReg $Rs)),
+ (A2_swiz (LoReg $Rs)))>;
+def: Pat<(bswap V4I16:$Rs), (A2_orp (S2_lsr_i_vh $Rs, 8),
+ (S2_asl_i_vh $Rs, 8))>;
+
def: Pat<(shl s6_0ImmPred:$s6, I32:$Rt), (S4_lsli imm:$s6, I32:$Rt)>;
def: Pat<(shl I32:$Rs, (i32 16)), (A2_aslh I32:$Rs)>;
def: Pat<(sra I32:$Rs, (i32 16)), (A2_asrh I32:$Rs)>;
@@ -1854,6 +1860,20 @@ def: Pat<(i32 (ctpop I32:$Rs)), (S5_popcountp (A4_combineir 0, I32:$Rs))>;
def: Pat<(bitreverse I32:$Rs), (S2_brev I32:$Rs)>;
def: Pat<(bitreverse I64:$Rss), (S2_brevp I64:$Rss)>;
+def: Pat<(bitreverse V4I8:$Rs), (A2_swiz (S2_brev $Rs))>;
+def: Pat<(bitreverse V8I8:$Rs), (Combinew (A2_swiz (LoReg (S2_brevp $Rs))),
+ (A2_swiz (HiReg (S2_brevp $Rs))))>;
+def: Pat<(bitreverse V2I16:$Rs), (A2_combine_lh (S2_brev $Rs),
+ (S2_brev $Rs))>;
+def: Pat<(bitreverse V4I16:$Rs),
+ (Combinew (A2_combine_lh (LoReg (S2_brevp $Rs)),
+ (LoReg (S2_brevp $Rs))),
+ (A2_combine_lh (HiReg (S2_brevp $Rs)),
+ (HiReg (S2_brevp $Rs))))>;
+def: Pat<(bitreverse V2I32:$Rs),
+ (Combinew (i32 (LoReg (S2_brevp $Rs))),
+ (i32 (HiReg (S2_brevp $Rs))))>;
+
let AddedComplexity = 20 in { // Complexity greater than and/or/xor
def: Pat<(and I32:$Rs, IsNPow2_32:$V),
(S2_clrbit_i IntRegs:$Rs, (LogN2_32 $V))>;
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index cf17c51b04fc..e43b33eed470 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -499,7 +499,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
}
if (Subtarget.hasSSEPrefetch() || Subtarget.hasThreeDNow())
- setOperationAction(ISD::PREFETCH , MVT::Other, Legal);
+ setOperationAction(ISD::PREFETCH , MVT::Other, Custom);
setOperationAction(ISD::ATOMIC_FENCE , MVT::Other, Custom);
@@ -2195,6 +2195,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::FMUL, VT, Expand);
setOperationAction(ISD::FDIV, VT, Expand);
setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
+ setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
}
addLegalFPImmediate(APFloat::getZero(APFloat::BFloat()));
}
@@ -2207,6 +2208,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::FMUL, MVT::v32bf16, Expand);
setOperationAction(ISD::FDIV, MVT::v32bf16, Expand);
setOperationAction(ISD::BUILD_VECTOR, MVT::v32bf16, Custom);
+ setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v32bf16, Custom);
}
if (!Subtarget.useSoftFloat() && Subtarget.hasVLX()) {
@@ -18773,11 +18775,11 @@ static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
return DAG.getBitcast(VT, DAG.getVectorShuffle(FpVT, DL, V1, V2, Mask));
}
- if (VT == MVT::v16f16) {
- V1 = DAG.getBitcast(MVT::v16i16, V1);
- V2 = DAG.getBitcast(MVT::v16i16, V2);
- return DAG.getBitcast(MVT::v16f16,
- DAG.getVectorShuffle(MVT::v16i16, DL, V1, V2, Mask));
+ if (VT == MVT::v16f16 || VT.getVectorElementType() == MVT::bf16) {
+ MVT IVT = VT.changeVectorElementTypeToInteger();
+ V1 = DAG.getBitcast(IVT, V1);
+ V2 = DAG.getBitcast(IVT, V2);
+ return DAG.getBitcast(VT, DAG.getVectorShuffle(IVT, DL, V1, V2, Mask));
}
switch (VT.SimpleTy) {
@@ -33093,6 +33095,18 @@ static SDValue LowerCVTPS2PH(SDValue Op, SelectionDAG &DAG) {
return DAG.getNode(ISD::CONCAT_VECTORS, dl, VT, Lo, Hi);
}
+static SDValue LowerPREFETCH(SDValue Op, const X86Subtarget &Subtarget,
+ SelectionDAG &DAG) {
+ unsigned IsData = cast<ConstantSDNode>(Op.getOperand(4))->getZExtValue();
+
+ // We don't support non-data prefetch without PREFETCHI.
+ // Just preserve the chain.
+ if (!IsData && !Subtarget.hasPREFETCHI())
+ return Op.getOperand(0);
+
+ return Op;
+}
+
static StringRef getInstrStrFromOpNo(const SmallVectorImpl<StringRef> &AsmStrs,
unsigned OpNo) {
const APInt Operand(32, OpNo);
@@ -33294,6 +33308,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::GC_TRANSITION_END: return LowerGC_TRANSITION(Op, DAG);
case ISD::ADDRSPACECAST: return LowerADDRSPACECAST(Op, DAG);
case X86ISD::CVTPS2PH: return LowerCVTPS2PH(Op, DAG);
+ case ISD::PREFETCH: return LowerPREFETCH(Op, Subtarget, DAG);
}
}
diff --git a/llvm/lib/Target/X86/X86InstrAVX512.td b/llvm/lib/Target/X86/X86InstrAVX512.td
index 6da4dd2b942c..888e69ac4ac0 100644
--- a/llvm/lib/Target/X86/X86InstrAVX512.td
+++ b/llvm/lib/Target/X86/X86InstrAVX512.td
@@ -12969,6 +12969,27 @@ let Predicates = [HasBF16, HasVLX] in {
(VCVTNEPS2BF16Z256rr VR256X:$src)>;
def : Pat<(v8bf16 (int_x86_vcvtneps2bf16256 (loadv8f32 addr:$src))),
(VCVTNEPS2BF16Z256rm addr:$src)>;
+
+ def : Pat<(v8bf16 (X86VBroadcastld16 addr:$src)),
+ (VPBROADCASTWZ128rm addr:$src)>;
+ def : Pat<(v16bf16 (X86VBroadcastld16 addr:$src)),
+ (VPBROADCASTWZ256rm addr:$src)>;
+
+ def : Pat<(v8bf16 (X86VBroadcast (v8bf16 VR128X:$src))),
+ (VPBROADCASTWZ128rr VR128X:$src)>;
+ def : Pat<(v16bf16 (X86VBroadcast (v8bf16 VR128X:$src))),
+ (VPBROADCASTWZ256rr VR128X:$src)>;
+
+ // TODO: No scalar broadcast due to we don't support legal scalar bf16 so far.
+}
+
+let Predicates = [HasBF16] in {
+ def : Pat<(v32bf16 (X86VBroadcastld16 addr:$src)),
+ (VPBROADCASTWZrm addr:$src)>;
+
+ def : Pat<(v32bf16 (X86VBroadcast (v8bf16 VR128X:$src))),
+ (VPBROADCASTWZrr VR128X:$src)>;
+ // TODO: No scalar broadcast due to we don't support legal scalar bf16 so far.
}
let Constraints = "$src1 = $dst" in {
diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp
index 73c341891ab7..33adf15fccaf 100644
--- a/llvm/tools/llvm-mca/llvm-mca.cpp
+++ b/llvm/tools/llvm-mca/llvm-mca.cpp
@@ -401,11 +401,6 @@ int main(int argc, char **argv) {
// Tell SrcMgr about this buffer, which is what the parser will pick up.
SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
- MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
- std::unique_ptr<MCObjectFileInfo> MOFI(
- TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
- Ctx.setObjectFileInfo(MOFI.get());
-
std::unique_ptr<buffer_ostream> BOS;
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
@@ -433,7 +428,11 @@ int main(int argc, char **argv) {
}
// Parse the input and create CodeRegions that llvm-mca can analyze.
- mca::AsmAnalysisRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI,
+ MCContext ACtx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
+ std::unique_ptr<MCObjectFileInfo> AMOFI(
+ TheTarget->createMCObjectFileInfo(ACtx, /*PIC=*/false));
+ ACtx.setObjectFileInfo(AMOFI.get());
+ mca::AsmAnalysisRegionGenerator CRG(*TheTarget, SrcMgr, ACtx, *MAI, *STI,
*MCII);
Expected<const mca::AnalysisRegions &> RegionsOrErr =
CRG.parseAnalysisRegions(std::move(IPtemp));
@@ -471,7 +470,11 @@ int main(int argc, char **argv) {
// Parse the input and create InstrumentRegion that llvm-mca
// can use to improve analysis.
- mca::AsmInstrumentRegionGenerator IRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI,
+ MCContext ICtx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
+ std::unique_ptr<MCObjectFileInfo> IMOFI(
+ TheTarget->createMCObjectFileInfo(ICtx, /*PIC=*/false));
+ ICtx.setObjectFileInfo(IMOFI.get());
+ mca::AsmInstrumentRegionGenerator IRG(*TheTarget, SrcMgr, ICtx, *MAI, *STI,
*MCII, *IM);
Expected<const mca::InstrumentRegions &> InstrumentRegionsOrErr =
IRG.parseInstrumentRegions(std::move(IPtemp));
@@ -547,7 +550,7 @@ int main(int argc, char **argv) {
unsigned RegionIdx = 0;
std::unique_ptr<MCCodeEmitter> MCE(
- TheTarget->createMCCodeEmitter(*MCII, Ctx));
+ TheTarget->createMCCodeEmitter(*MCII, ACtx));
assert(MCE && "Unable to create code emitter!");
std::unique_ptr<MCAsmBackend> MAB(TheTarget->createMCAsmBackend(