Skip to content

Commit

Permalink
merge main into amd-staging
Browse files Browse the repository at this point in the history
Merges commit '990bed64' into amd-staging

Change-Id: Ie4718fee0948abe7e867017089d1c5c8d65f3239
  • Loading branch information
ronlieb committed May 24, 2024
2 parents 226e581 + 990bed6 commit fb3bf37
Show file tree
Hide file tree
Showing 124 changed files with 1,894 additions and 891 deletions.
7 changes: 4 additions & 3 deletions bolt/include/bolt/Profile/BoltAddressTranslation.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class BoltAddressTranslation {
std::error_code parse(raw_ostream &OS, StringRef Buf);

/// Dump the parsed address translation tables
void dump(raw_ostream &OS);
void dump(raw_ostream &OS) const;

/// If the maps are loaded in memory, perform the lookup to translate LBR
/// addresses in function located at \p FuncAddress.
Expand Down Expand Up @@ -137,7 +137,8 @@ class BoltAddressTranslation {
/// emitted for the start of the BB. More entries may be emitted to cover
/// the location of calls or any instruction that may change control flow.
void writeEntriesForBB(MapTy &Map, const BinaryBasicBlock &BB,
uint64_t FuncInputAddress, uint64_t FuncOutputAddress);
uint64_t FuncInputAddress,
uint64_t FuncOutputAddress) const;

/// Write the serialized address translation table for a function.
template <bool Cold>
Expand All @@ -152,7 +153,7 @@ class BoltAddressTranslation {

/// Returns the bitmask with set bits corresponding to indices of BRANCHENTRY
/// entries in function address translation map.
APInt calculateBranchEntriesBitMask(MapTy &Map, size_t EqualElems);
APInt calculateBranchEntriesBitMask(MapTy &Map, size_t EqualElems) const;

/// Calculate the number of equal offsets (output = input - skew) in the
/// beginning of the function.
Expand Down
25 changes: 14 additions & 11 deletions bolt/lib/Profile/BoltAddressTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ namespace bolt {

const char *BoltAddressTranslation::SECTION_NAME = ".note.bolt_bat";

void BoltAddressTranslation::writeEntriesForBB(MapTy &Map,
const BinaryBasicBlock &BB,
uint64_t FuncInputAddress,
uint64_t FuncOutputAddress) {
void BoltAddressTranslation::writeEntriesForBB(
MapTy &Map, const BinaryBasicBlock &BB, uint64_t FuncInputAddress,
uint64_t FuncOutputAddress) const {
const uint64_t BBOutputOffset =
BB.getOutputAddressRange().first - FuncOutputAddress;
const uint32_t BBInputOffset = BB.getInputOffset();
Expand Down Expand Up @@ -138,8 +137,8 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) {
<< " basic block hashes\n";
}

APInt BoltAddressTranslation::calculateBranchEntriesBitMask(MapTy &Map,
size_t EqualElems) {
APInt BoltAddressTranslation::calculateBranchEntriesBitMask(
MapTy &Map, size_t EqualElems) const {
APInt BitMask(alignTo(EqualElems, 8), 0);
size_t Index = 0;
for (std::pair<const uint32_t, uint32_t> &KeyVal : Map) {
Expand Down Expand Up @@ -422,7 +421,7 @@ void BoltAddressTranslation::parseMaps(std::vector<uint64_t> &HotFuncs,
}
}

void BoltAddressTranslation::dump(raw_ostream &OS) {
void BoltAddressTranslation::dump(raw_ostream &OS) const {
const size_t NumTables = Maps.size();
OS << "BAT tables for " << NumTables << " functions:\n";
for (const auto &MapEntry : Maps) {
Expand All @@ -447,11 +446,15 @@ void BoltAddressTranslation::dump(raw_ostream &OS) {
OS << formatv(" hash: {0:x}", BBHashMap.getBBHash(Val));
OS << "\n";
}
if (IsHotFunction)
OS << "NumBlocks: " << NumBasicBlocksMap[Address] << '\n';
if (SecondaryEntryPointsMap.count(Address)) {
if (IsHotFunction) {
auto NumBasicBlocksIt = NumBasicBlocksMap.find(Address);
assert(NumBasicBlocksIt != NumBasicBlocksMap.end());
OS << "NumBlocks: " << NumBasicBlocksIt->second << '\n';
}
auto SecondaryEntryPointsIt = SecondaryEntryPointsMap.find(Address);
if (SecondaryEntryPointsIt != SecondaryEntryPointsMap.end()) {
const std::vector<uint32_t> &SecondaryEntryPoints =
SecondaryEntryPointsMap[Address];
SecondaryEntryPointsIt->second;
OS << SecondaryEntryPoints.size() << " secondary entry points:\n";
for (uint32_t EntryPointOffset : SecondaryEntryPoints)
OS << formatv("{0:x}\n", EntryPointOffset);
Expand Down
6 changes: 6 additions & 0 deletions bolt/lib/Profile/StaleProfileMatching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "llvm/ADT/Bitfields.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/xxhash.h"
#include "llvm/Transforms/Utils/SampleProfileInference.h"

Expand All @@ -42,6 +43,7 @@ using namespace llvm;

namespace opts {

extern cl::opt<bool> TimeRewrite;
extern cl::OptionCategory BoltOptCategory;

cl::opt<bool>
Expand Down Expand Up @@ -707,6 +709,10 @@ void assignProfile(BinaryFunction &BF,

bool YAMLProfileReader::inferStaleProfile(
BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF) {

NamedRegionTimer T("inferStaleProfile", "stale profile inference", "rewrite",
"Rewrite passes", opts::TimeRewrite);

if (!BF.hasCFG())
return false;

Expand Down
6 changes: 1 addition & 5 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ extern cl::list<std::string> ReorderData;
extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
extern cl::opt<bool> TerminalTrap;
extern cl::opt<bool> TimeBuild;
extern cl::opt<bool> TimeRewrite;

cl::opt<bool> AllowStripped("allow-stripped",
cl::desc("allow processing of stripped binaries"),
Expand Down Expand Up @@ -235,11 +236,6 @@ UseGnuStack("use-gnu-stack",
cl::ZeroOrMore,
cl::cat(BoltCategory));

static cl::opt<bool>
TimeRewrite("time-rewrite",
cl::desc("print time spent in rewriting passes"), cl::Hidden,
cl::cat(BoltCategory));

static cl::opt<bool>
SequentialDisassembly("sequential-disassembly",
cl::desc("performs disassembly sequentially"),
Expand Down
4 changes: 4 additions & 0 deletions bolt/lib/Utils/CommandLineOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ cl::opt<bool> TimeOpts("time-opts",
cl::desc("print time spent in each optimization"),
cl::cat(BoltOptCategory));

cl::opt<bool> TimeRewrite("time-rewrite",
cl::desc("print time spent in rewriting passes"),
cl::Hidden, cl::cat(BoltCategory));

cl::opt<bool> UseOldText(
"use-old-text",
cl::desc("re-use space in old .text if possible (relocation mode)"),
Expand Down
8 changes: 8 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,14 @@ Bug Fixes to C++ Support
explicit object argument member functions. Fixes (#GH92188).
- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with
the ``constexpr`` specifier. Fixes (#GH61004).
- Clang no longer transforms dependent qualified names into implicit class member access expressions
until it can be determined whether the name is that of a non-static member.
- Clang now correctly diagnoses when the current instantiation is used as an incomplete base class.
- Clang no longer treats ``constexpr`` class scope function template specializations of non-static members
as implicitly ``const`` in language modes after C++11.
- Fixed a crash when trying to emit captures in a lambda call operator with an explicit object
parameter that is called on a derived type of the lambda.
Fixes (#GH87210), (GH89541).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class VarTemplateDecl;
class VTableContextBase;
class XRayFunctionFilter;

/// A simple array of base specifiers.
typedef SmallVector<CXXBaseSpecifier *, 4> CXXCastPath;

namespace Builtin {

class Context;
Expand Down Expand Up @@ -1170,6 +1173,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// in device compilation.
llvm::DenseSet<const FunctionDecl *> CUDAImplicitHostDeviceFunUsedByDevice;

/// For capturing lambdas with an explicit object parameter whose type is
/// derived from the lambda type, we need to perform derived-to-base
/// conversion so we can access the captures; the cast paths for that
/// are stored here.
llvm::DenseMap<const CXXMethodDecl *, CXXCastPath> LambdaCastPaths;

ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
SelectorTable &sels, Builtin::Context &builtins,
TranslationUnitKind TUKind);
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1345,8 +1345,8 @@ def note_pragma_attribute_namespace_on_attribute : Note<
"omit the namespace to add attributes to the most-recently"
" pushed attribute group">;
def warn_no_support_for_eval_method_source_on_m32 : Warning<
"Setting the floating point evaluation method to `source` on a target"
" without SSE is not supported.">, InGroup<Pragmas>;
"setting the floating point evaluation method to `source` on a target "
"without SSE is not supported">, InGroup<Pragmas>;
// - #pragma __debug
def warn_pragma_debug_dependent_argument : Warning<
"%select{value|type}0-dependent expression passed as an argument to debug "
Expand Down
11 changes: 8 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7525,6 +7525,11 @@ def err_explicit_object_parameter_mutable: Error<
def err_invalid_explicit_object_type_in_lambda: Error<
"invalid explicit object parameter type %0 in lambda with capture; "
"the type must be the same as, or derived from, the lambda">;
def err_explicit_object_lambda_ambiguous_base : Error<
"lambda %0 is inaccessible due to ambiguity:%1">;
def err_explicit_object_lambda_inaccessible_base : Error<
"invalid explicit object parameter type %0 in lambda with capture; "
"the type must derive publicly from the lambda">;

def err_ref_qualifier_overload : Error<
"cannot overload a member function %select{without a ref-qualifier|with "
Expand Down Expand Up @@ -11335,18 +11340,18 @@ def err_omp_reduction_vla_unsupported : Error<
def err_omp_linear_distribute_var_non_loop_iteration : Error<
"only loop iteration variables are allowed in 'linear' clause in distribute directives">;
def warn_omp_non_trivial_type_mapped : Warning<
"Type %0 is not trivially copyable and not guaranteed to be mapped correctly">,
"type %0 is not trivially copyable and not guaranteed to be mapped correctly">,
InGroup<OpenMPMapping>;
def err_omp_requires_clause_redeclaration : Error <
"Only one %0 clause can appear on a requires directive in a single translation unit">;
"only one %0 clause can appear on a requires directive in a single translation unit">;
def note_omp_requires_previous_clause : Note <
"%0 clause previously used here">;
def err_omp_directive_before_requires : Error <
"'%0' region encountered before requires directive with '%1' clause">;
def note_omp_requires_encountered_directive : Note <
"'%0' previously encountered here">;
def err_omp_device_ancestor_without_requires_reverse_offload : Error <
"Device clause with ancestor device-modifier used without specifying 'requires reverse_offload'">;
"device clause with ancestor device-modifier used without specifying 'requires reverse_offload'">;
def err_omp_invalid_scope : Error <
"'#pragma omp %0' directive must appear only in file scope">;
def note_omp_invalid_length_on_this_ptr_mapping : Note <
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -7083,7 +7083,9 @@ class Sema final : public SemaBase {
StorageClass SC, ArrayRef<ParmVarDecl *> Params,
bool HasExplicitResultType);

void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
/// Returns true if the explicit object parameter was invalid.
bool DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method,
SourceLocation CallLoc);

/// Perform initialization analysis of the init-capture and perform
/// any implicit conversions such as an lvalue-to-rvalue conversion if
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4676,7 +4676,8 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field,
llvm::Value *ThisValue) {
bool HasExplicitObjectParameter = false;
if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(CurCodeDecl)) {
const auto *MD = dyn_cast_if_present<CXXMethodDecl>(CurCodeDecl);
if (MD) {
HasExplicitObjectParameter = MD->isExplicitObjectMemberFunction();
assert(MD->getParent()->isLambda());
assert(MD->getParent() == Field->getParent());
Expand All @@ -4693,6 +4694,17 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field,
else
LambdaLV = MakeAddrLValue(AddrOfExplicitObject,
D->getType().getNonReferenceType());

// Make sure we have an lvalue to the lambda itself and not a derived class.
auto *ThisTy = D->getType().getNonReferenceType()->getAsCXXRecordDecl();
auto *LambdaTy = cast<CXXRecordDecl>(Field->getParent());
if (ThisTy != LambdaTy) {
const CXXCastPath &BasePathArray = getContext().LambdaCastPaths.at(MD);
Address Base = GetAddressOfBaseClass(
LambdaLV.getAddress(), ThisTy, BasePathArray.begin(),
BasePathArray.end(), /*NullCheckValue=*/false, SourceLocation());
LambdaLV = MakeAddrLValue(Base, QualType{LambdaTy->getTypeForDecl(), 0});
}
} else {
QualType LambdaTagType = getContext().getTagDeclType(Field->getParent());
LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType);
Expand Down
68 changes: 54 additions & 14 deletions clang/lib/Sema/SemaLambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "clang/Sema/SemaLambda.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
Expand Down Expand Up @@ -386,30 +387,69 @@ buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class,
// parameter, if any, of the lambda's function call operator (possibly
// instantiated from a function call operator template) shall be either:
// - the closure type,
// - class type derived from the closure type, or
// - class type publicly and unambiguously derived from the closure type, or
// - a reference to a possibly cv-qualified such type.
void Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
CXXMethodDecl *Method) {
bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
CXXMethodDecl *Method, SourceLocation CallLoc) {
if (!isLambdaCallWithExplicitObjectParameter(Method))
return;
return false;
CXXRecordDecl *RD = Method->getParent();
if (Method->getType()->isDependentType())
return;
return false;
if (RD->isCapturelessLambda())
return;
QualType ExplicitObjectParameterType = Method->getParamDecl(0)
->getType()
return false;

ParmVarDecl *Param = Method->getParamDecl(0);
QualType ExplicitObjectParameterType = Param->getType()
.getNonReferenceType()
.getUnqualifiedType()
.getDesugaredType(getASTContext());
QualType LambdaType = getASTContext().getRecordType(RD);
if (LambdaType == ExplicitObjectParameterType)
return;
if (IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType))
return;
Diag(Method->getParamDecl(0)->getLocation(),
diag::err_invalid_explicit_object_type_in_lambda)
<< ExplicitObjectParameterType;
return false;

// Don't check the same instantiation twice.
//
// If this call operator is ill-formed, there is no point in issuing
// a diagnostic every time it is called because the problem is in the
// definition of the derived type, not at the call site.
//
// FIXME: Move this check to where we instantiate the method? This should
// be possible, but the naive approach of just marking the method as invalid
// leads to us emitting more diagnostics than we should have to for this case
// (1 error here *and* 1 error about there being no matching overload at the
// call site). It might be possible to avoid that by also checking if there
// is an empty cast path for the method stored in the context (signalling that
// we've already diagnosed it) and then just not building the call, but that
// doesn't really seem any simpler than diagnosing it at the call site...
if (auto It = Context.LambdaCastPaths.find(Method);
It != Context.LambdaCastPaths.end())
return It->second.empty();

CXXCastPath &Path = Context.LambdaCastPaths[Method];
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
if (!IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType,
Paths)) {
Diag(Param->getLocation(), diag::err_invalid_explicit_object_type_in_lambda)
<< ExplicitObjectParameterType;
return true;
}

if (Paths.isAmbiguous(LambdaType->getCanonicalTypeUnqualified())) {
std::string PathsDisplay = getAmbiguousPathsDisplayString(Paths);
Diag(CallLoc, diag::err_explicit_object_lambda_ambiguous_base)
<< LambdaType << PathsDisplay;
return true;
}

if (CheckBaseClassAccess(CallLoc, LambdaType, ExplicitObjectParameterType,
Paths.front(),
diag::err_explicit_object_lambda_inaccessible_base))
return true;

BuildBasePathArray(Paths, Path);
return false;
}

void Sema::handleLambdaNumbering(
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6472,17 +6472,20 @@ ExprResult Sema::InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
Obj->getExprLoc(), Obj);
}

static void PrepareExplicitObjectArgument(Sema &S, CXXMethodDecl *Method,
static bool PrepareExplicitObjectArgument(Sema &S, CXXMethodDecl *Method,
Expr *Object, MultiExprArg &Args,
SmallVectorImpl<Expr *> &NewArgs) {
assert(Method->isExplicitObjectMemberFunction() &&
"Method is not an explicit member function");
assert(NewArgs.empty() && "NewArgs should be empty");

NewArgs.reserve(Args.size() + 1);
Expr *This = GetExplicitObjectExpr(S, Object, Method);
NewArgs.push_back(This);
NewArgs.append(Args.begin(), Args.end());
Args = NewArgs;
return S.DiagnoseInvalidExplicitObjectParameterInLambda(
Method, Object->getBeginLoc());
}

/// Determine whether the provided type is an integral type, or an enumeration
Expand Down Expand Up @@ -15612,8 +15615,10 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
CallExpr *TheCall = nullptr;
llvm::SmallVector<Expr *, 8> NewArgs;
if (Method->isExplicitObjectMemberFunction()) {
PrepareExplicitObjectArgument(*this, Method, MemExpr->getBase(), Args,
NewArgs);
if (PrepareExplicitObjectArgument(*this, Method, MemExpr->getBase(), Args,
NewArgs))
return ExprError();

// Build the actual expression node.
ExprResult FnExpr =
CreateFunctionRefExpr(*this, Method, FoundDecl, MemExpr,
Expand Down Expand Up @@ -15927,9 +15932,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// Initialize the object parameter.
llvm::SmallVector<Expr *, 8> NewArgs;
if (Method->isExplicitObjectMemberFunction()) {
// FIXME: we should do that during the definition of the lambda when we can.
DiagnoseInvalidExplicitObjectParameterInLambda(Method);
PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs);
IsError |= PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs);
} else {
ExprResult ObjRes = PerformImplicitObjectArgumentInitialization(
Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method);
Expand Down
Loading

0 comments on commit fb3bf37

Please sign in to comment.