Skip to content

Commit d98d58b

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:511ba45a47d6 into amd-gfx:8a11303f2b4e
Local branch amd-gfx 8a11303 Merged main:586986a063ee into amd-gfx:b8966b19ced0 Remote branch main 511ba45 [X86][MC][CodeGen] Support EGPR for KMOV (llvm#73781)
2 parents 8a11303 + 511ba45 commit d98d58b

38 files changed

+896
-307
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,11 @@ Bug Fixes to C++ Support
793793
- Fix crash when parsing nested requirement. Fixes:
794794
(`#73112 <https://github.com/llvm/llvm-project/issues/73112>`_)
795795

796+
- Clang now immediately instantiates function template specializations
797+
at the end of the definition of the corresponding function template
798+
when the definition appears after the first point of instantiation.
799+
(`#73232 <https://github.com/llvm/llvm-project/issues/73232>`_)
800+
796801
Bug Fixes to AST Handling
797802
^^^^^^^^^^^^^^^^^^^^^^^^^
798803
- Fixed an import failure of recursive friend class template.

clang/include/clang/Sema/ExternalSemaSource.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ class ExternalSemaSource : public ExternalASTSource {
181181
SmallVectorImpl<std::pair<ValueDecl *,
182182
SourceLocation> > &Pending) {}
183183

184+
virtual void ReadPendingInstantiationsOfConstexprEntity(
185+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls){};
186+
184187
/// Read the set of late parsed template functions for this source.
185188
///
186189
/// The external source should insert its own late parsed template functions

clang/include/clang/Sema/MultiplexExternalSemaSource.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
319319
void ReadPendingInstantiations(
320320
SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override;
321321

322+
virtual void ReadPendingInstantiationsOfConstexprEntity(
323+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) override;
324+
322325
/// Read the set of late parsed template functions for this source.
323326
///
324327
/// The external source should insert its own late parsed template functions

clang/include/clang/Sema/Sema.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include "clang/Sema/TypoCorrection.h"
6060
#include "clang/Sema/Weak.h"
6161
#include "llvm/ADT/ArrayRef.h"
62+
#include "llvm/ADT/DenseMap.h"
6263
#include "llvm/ADT/SetVector.h"
6364
#include "llvm/ADT/SmallBitVector.h"
6465
#include "llvm/ADT/SmallPtrSet.h"
@@ -10087,6 +10088,12 @@ class Sema final {
1008710088
/// but have not yet been performed.
1008810089
std::deque<PendingImplicitInstantiation> PendingInstantiations;
1008910090

10091+
/// Track constexpr functions referenced before they are (lexically) defined.
10092+
/// The key is the pattern, associated with a list of specialisations that
10093+
/// need to be instantiated when the pattern is defined.
10094+
llvm::DenseMap<NamedDecl *, SmallVector<NamedDecl *>>
10095+
PendingInstantiationsOfConstexprEntities;
10096+
1009010097
/// Queue of implicit template instantiations that cannot be performed
1009110098
/// eagerly.
1009210099
SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations;
@@ -10405,6 +10412,9 @@ class Sema final {
1040510412
bool Recursive = false,
1040610413
bool DefinitionRequired = false,
1040710414
bool AtEndOfTU = false);
10415+
10416+
void PerformPendingInstantiationsOfConstexprFunctions(FunctionDecl *Template);
10417+
1040810418
VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
1040910419
VarTemplateDecl *VarTemplate, VarDecl *FromVar,
1041010420
const TemplateArgumentList &TemplateArgList,

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,10 @@ enum ASTRecordTypes {
695695
/// Record code for an unterminated \#pragma clang assume_nonnull begin
696696
/// recorded in a preamble.
697697
PP_ASSUME_NONNULL_LOC = 67,
698+
699+
/// Record code for constexpr templated entities that have been used but not
700+
/// yet instantiated.
701+
PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES = 68,
698702
};
699703

700704
/// Record types used within a source manager block.

clang/include/clang/Serialization/ASTReader.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,9 @@ class ASTReader
814814
/// is the instantiation location.
815815
SmallVector<serialization::DeclID, 64> PendingInstantiations;
816816

817+
llvm::DenseMap<serialization::DeclID, std::set<serialization::DeclID>>
818+
PendingInstantiationsOfConstexprEntities;
819+
817820
//@}
818821

819822
/// \name DiagnosticsEngine-relevant special data
@@ -2101,6 +2104,9 @@ class ASTReader
21012104
SmallVectorImpl<std::pair<ValueDecl *,
21022105
SourceLocation>> &Pending) override;
21032106

2107+
virtual void ReadPendingInstantiationsOfConstexprEntity(
2108+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) override;
2109+
21042110
void ReadLateParsedTemplates(
21052111
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
21062112
&LPTMap) override;

clang/lib/Sema/MultiplexExternalSemaSource.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,12 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations(
310310
Sources[i]->ReadPendingInstantiations(Pending);
311311
}
312312

313+
void MultiplexExternalSemaSource::ReadPendingInstantiationsOfConstexprEntity(
314+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) {
315+
for (size_t i = 0; i < Sources.size(); ++i)
316+
Sources[i]->ReadPendingInstantiationsOfConstexprEntity(D, Decls);
317+
}
318+
313319
void MultiplexExternalSemaSource::ReadLateParsedTemplates(
314320
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
315321
&LPTMap) {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16275,6 +16275,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
1627516275
if (FD && !FD->isDeleted())
1627616276
checkTypeSupport(FD->getType(), FD->getLocation(), FD);
1627716277

16278+
if (FD && FD->isConstexpr() && FD->isTemplated())
16279+
PerformPendingInstantiationsOfConstexprFunctions(FD);
16280+
1627816281
return dcl;
1627916282
}
1628016283

clang/lib/Sema/SemaExpr.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19053,12 +19053,17 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
1905319053
CodeSynthesisContexts.size())
1905419054
PendingLocalImplicitInstantiations.push_back(
1905519055
std::make_pair(Func, PointOfInstantiation));
19056-
else if (Func->isConstexpr())
19056+
else if (Func->isConstexpr()) {
1905719057
// Do not defer instantiations of constexpr functions, to avoid the
1905819058
// expression evaluator needing to call back into Sema if it sees a
1905919059
// call to such a function.
1906019060
InstantiateFunctionDefinition(PointOfInstantiation, Func);
19061-
else {
19061+
if (!Func->isDefined()) {
19062+
PendingInstantiationsOfConstexprEntities
19063+
[Func->getTemplateInstantiationPattern()->getCanonicalDecl()]
19064+
.push_back(Func);
19065+
}
19066+
} else {
1906219067
Func->setInstantiationIsPending(true);
1906319068
PendingInstantiations.push_back(
1906419069
std::make_pair(Func, PointOfInstantiation));

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6495,6 +6495,34 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
64956495
PendingInstantiations.swap(delayedPCHInstantiations);
64966496
}
64976497

6498+
// Instantiate all referenced specializations of the given function template
6499+
// definition. This make sure that constexpr function templates that are defined
6500+
// after the point of instantiation of their use can be evaluated after they
6501+
// are defined. see CWG2497.
6502+
void Sema::PerformPendingInstantiationsOfConstexprFunctions(FunctionDecl *Tpl) {
6503+
6504+
auto InstantiateAll = [&](const auto &Range) {
6505+
for (NamedDecl *D : Range) {
6506+
FunctionDecl *Fun = cast<FunctionDecl>(D);
6507+
InstantiateFunctionDefinition(Fun->getPointOfInstantiation(), Fun);
6508+
}
6509+
};
6510+
6511+
auto It =
6512+
PendingInstantiationsOfConstexprEntities.find(Tpl->getCanonicalDecl());
6513+
if (It != PendingInstantiationsOfConstexprEntities.end()) {
6514+
auto Decls = std::move(It->second);
6515+
PendingInstantiationsOfConstexprEntities.erase(It);
6516+
InstantiateAll(Decls);
6517+
}
6518+
6519+
llvm::SmallSetVector<NamedDecl *, 4> Decls;
6520+
if (ExternalSource) {
6521+
ExternalSource->ReadPendingInstantiationsOfConstexprEntity(Tpl, Decls);
6522+
InstantiateAll(Decls);
6523+
}
6524+
}
6525+
64986526
void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
64996527
const MultiLevelTemplateArgumentList &TemplateArgs) {
65006528
for (auto *DD : Pattern->ddiags()) {

clang/lib/Serialization/ASTReader.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3709,6 +3709,19 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
37093709
}
37103710
break;
37113711

3712+
case PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES:
3713+
if (Record.size() % 2 != 0)
3714+
return llvm::createStringError(
3715+
std::errc::illegal_byte_sequence,
3716+
"Invalid PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES block");
3717+
3718+
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
3719+
DeclID Key = getGlobalDeclID(F, Record[I++]);
3720+
DeclID Value = getGlobalDeclID(F, Record[I++]);
3721+
PendingInstantiationsOfConstexprEntities[Key].insert(Value);
3722+
}
3723+
break;
3724+
37123725
case SEMA_DECL_REFS:
37133726
if (Record.size() != 3)
37143727
return llvm::createStringError(std::errc::illegal_byte_sequence,
@@ -8718,6 +8731,20 @@ void ASTReader::ReadPendingInstantiations(
87188731
PendingInstantiations.clear();
87198732
}
87208733

8734+
void ASTReader::ReadPendingInstantiationsOfConstexprEntity(
8735+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) {
8736+
for (auto *Redecl : D->redecls()) {
8737+
if (!Redecl->isFromASTFile())
8738+
continue;
8739+
DeclID Id = Redecl->getGlobalID();
8740+
auto It = PendingInstantiationsOfConstexprEntities.find(Id);
8741+
if (It == PendingInstantiationsOfConstexprEntities.end())
8742+
continue;
8743+
for (DeclID InstantiationId : It->second)
8744+
Decls.insert(cast<NamedDecl>(GetDecl(InstantiationId)));
8745+
}
8746+
}
8747+
87218748
void ASTReader::ReadLateParsedTemplates(
87228749
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
87238750
&LPTMap) {

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@ void ASTWriter::WriteBlockInfoBlock() {
849849
RECORD(SEMA_DECL_REFS);
850850
RECORD(WEAK_UNDECLARED_IDENTIFIERS);
851851
RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
852+
RECORD(PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES);
852853
RECORD(UPDATE_VISIBLE);
853854
RECORD(DECL_UPDATE_OFFSETS);
854855
RECORD(DECL_UPDATES);
@@ -4836,6 +4837,16 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
48364837
assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
48374838
"There are local ones at end of translation unit!");
48384839

4840+
// Build a record containing all pending instantiations of constexpr
4841+
// entities.
4842+
RecordData PendingInstantiationsOfConstexprEntities;
4843+
for (const auto &I : SemaRef.PendingInstantiationsOfConstexprEntities) {
4844+
for (const auto &Elem : I.second) {
4845+
AddDeclRef(I.first, PendingInstantiationsOfConstexprEntities);
4846+
AddDeclRef(Elem, PendingInstantiationsOfConstexprEntities);
4847+
}
4848+
}
4849+
48394850
// Build a record containing some declaration references.
48404851
RecordData SemaDeclRefs;
48414852
if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {
@@ -5153,6 +5164,11 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
51535164
if (!PendingInstantiations.empty())
51545165
Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
51555166

5167+
// Write the record containing pending instantiations of constexpr entities.
5168+
if (!PendingInstantiationsOfConstexprEntities.empty())
5169+
Stream.EmitRecord(PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES,
5170+
PendingInstantiationsOfConstexprEntities);
5171+
51565172
// Write the record containing declaration references of Sema.
51575173
if (!SemaDeclRefs.empty())
51585174
Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
2+
// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
3+
4+
// expected-no-diagnostics
5+
6+
#ifndef HEADER
7+
#define HEADER
8+
9+
template<typename T> constexpr T f();
10+
constexpr int g() { return f<int>(); } // #1
11+
12+
#else /*included pch*/
13+
14+
template<typename T> constexpr T f() { return 123; }
15+
int k[g()];
16+
17+
#endif // HEADER
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
// expected-no-diagnostics
3+
4+
namespace GH73232 {
5+
6+
template <typename _CharT>
7+
struct basic_string {
8+
constexpr void _M_construct();
9+
constexpr basic_string() {
10+
_M_construct();
11+
}
12+
};
13+
14+
basic_string<char> a;
15+
16+
template <typename _CharT>
17+
constexpr void basic_string<_CharT>::_M_construct(){}
18+
constexpr basic_string<char> str{};
19+
20+
template <typename T>
21+
constexpr void g(T);
22+
23+
constexpr int f() { g(0); return 0; }
24+
25+
template <typename T>
26+
constexpr void g(T) {}
27+
28+
constexpr int z = f();
29+
30+
}

llvm/include/llvm/Config/llvm-config.h.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
/* Indicate that this is LLVM compiled from the amd-gfx branch. */
1818
#define LLVM_HAVE_BRANCH_AMD_GFX
19-
#define LLVM_MAIN_REVISION 482223
19+
#define LLVM_MAIN_REVISION 482228
2020

2121
/* Define if LLVM_ENABLE_DUMP is enabled */
2222
#cmakedefine LLVM_ENABLE_DUMP

llvm/include/llvm/IR/IntrinsicsAMDGPU.td

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,12 +2024,14 @@ def int_amdgcn_alignbyte : ClangBuiltin<"__builtin_amdgcn_alignbyte">,
20242024
[IntrNoMem, IntrSpeculatable]
20252025
>;
20262026

2027-
def int_amdgcn_mul_i24 : DefaultAttrsIntrinsic<[llvm_i32_ty],
2027+
// mul24 intrinsics can return i32 or i64.
2028+
// When returning i64, they're lowered to a mul24/mulhi24 pair.
2029+
def int_amdgcn_mul_i24 : DefaultAttrsIntrinsic<[llvm_anyint_ty],
20282030
[llvm_i32_ty, llvm_i32_ty],
20292031
[IntrNoMem, IntrSpeculatable]
20302032
>;
20312033

2032-
def int_amdgcn_mul_u24 : DefaultAttrsIntrinsic<[llvm_i32_ty],
2034+
def int_amdgcn_mul_u24 : DefaultAttrsIntrinsic<[llvm_anyint_ty],
20332035
[llvm_i32_ty, llvm_i32_ty],
20342036
[IntrNoMem, IntrSpeculatable]
20352037
>;

llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -624,34 +624,6 @@ static Value *insertValues(IRBuilder<> &Builder,
624624
return NewVal;
625625
}
626626

627-
// Returns 24-bit or 48-bit (as per `NumBits` and `Size`) mul of `LHS` and
628-
// `RHS`. `NumBits` is the number of KnownBits of the result and `Size` is the
629-
// width of the original destination.
630-
static Value *getMul24(IRBuilder<> &Builder, Value *LHS, Value *RHS,
631-
unsigned Size, unsigned NumBits, bool IsSigned) {
632-
if (Size <= 32 || NumBits <= 32) {
633-
Intrinsic::ID ID =
634-
IsSigned ? Intrinsic::amdgcn_mul_i24 : Intrinsic::amdgcn_mul_u24;
635-
return Builder.CreateIntrinsic(ID, {}, {LHS, RHS});
636-
}
637-
638-
assert(NumBits <= 48);
639-
640-
Intrinsic::ID LoID =
641-
IsSigned ? Intrinsic::amdgcn_mul_i24 : Intrinsic::amdgcn_mul_u24;
642-
Intrinsic::ID HiID =
643-
IsSigned ? Intrinsic::amdgcn_mulhi_i24 : Intrinsic::amdgcn_mulhi_u24;
644-
645-
Value *Lo = Builder.CreateIntrinsic(LoID, {}, {LHS, RHS});
646-
Value *Hi = Builder.CreateIntrinsic(HiID, {}, {LHS, RHS});
647-
648-
IntegerType *I64Ty = Builder.getInt64Ty();
649-
Lo = Builder.CreateZExtOrTrunc(Lo, I64Ty);
650-
Hi = Builder.CreateZExtOrTrunc(Hi, I64Ty);
651-
652-
return Builder.CreateOr(Lo, Builder.CreateShl(Hi, 32));
653-
}
654-
655627
bool AMDGPUCodeGenPrepareImpl::replaceMulWithMul24(BinaryOperator &I) const {
656628
if (I.getOpcode() != Instruction::Mul)
657629
return false;
@@ -691,26 +663,20 @@ bool AMDGPUCodeGenPrepareImpl::replaceMulWithMul24(BinaryOperator &I) const {
691663
extractValues(Builder, RHSVals, RHS);
692664

693665
IntegerType *I32Ty = Builder.getInt32Ty();
694-
for (int I = 0, E = LHSVals.size(); I != E; ++I) {
695-
Value *LHS, *RHS;
696-
if (IsSigned) {
697-
LHS = Builder.CreateSExtOrTrunc(LHSVals[I], I32Ty);
698-
RHS = Builder.CreateSExtOrTrunc(RHSVals[I], I32Ty);
699-
} else {
700-
LHS = Builder.CreateZExtOrTrunc(LHSVals[I], I32Ty);
701-
RHS = Builder.CreateZExtOrTrunc(RHSVals[I], I32Ty);
702-
}
666+
IntegerType *IntrinTy = Size > 32 ? Builder.getInt64Ty() : I32Ty;
667+
Type *DstTy = LHSVals[0]->getType();
703668

704-
Value *Result =
705-
getMul24(Builder, LHS, RHS, Size, LHSBits + RHSBits, IsSigned);
706-
707-
if (IsSigned) {
708-
ResultVals.push_back(
709-
Builder.CreateSExtOrTrunc(Result, LHSVals[I]->getType()));
710-
} else {
711-
ResultVals.push_back(
712-
Builder.CreateZExtOrTrunc(Result, LHSVals[I]->getType()));
713-
}
669+
for (int I = 0, E = LHSVals.size(); I != E; ++I) {
670+
Value *LHS = IsSigned ? Builder.CreateSExtOrTrunc(LHSVals[I], I32Ty)
671+
: Builder.CreateZExtOrTrunc(LHSVals[I], I32Ty);
672+
Value *RHS = IsSigned ? Builder.CreateSExtOrTrunc(RHSVals[I], I32Ty)
673+
: Builder.CreateZExtOrTrunc(RHSVals[I], I32Ty);
674+
Intrinsic::ID ID =
675+
IsSigned ? Intrinsic::amdgcn_mul_i24 : Intrinsic::amdgcn_mul_u24;
676+
Value *Result = Builder.CreateIntrinsic(ID, {IntrinTy}, {LHS, RHS});
677+
Result = IsSigned ? Builder.CreateSExtOrTrunc(Result, DstTy)
678+
: Builder.CreateZExtOrTrunc(Result, DstTy);
679+
ResultVals.push_back(Result);
714680
}
715681

716682
Value *NewVal = insertValues(Builder, Ty, ResultVals);

0 commit comments

Comments
 (0)