207 changes: 140 additions & 67 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,54 @@ static void pushInt(InterpState &S, int32_t Val) {
llvm_unreachable("Int isn't 16 or 32 bit?");
}

static bool retInt(InterpState &S, CodePtr OpPC, APValue &Result) {
PrimType IntType = getIntPrimType(S);
if (IntType == PT_Sint32)
return Ret<PT_Sint32>(S, OpPC, Result);
else if (IntType == PT_Sint16)
return Ret<PT_Sint16>(S, OpPC, Result);
llvm_unreachable("Int isn't 16 or 32 bit?");
static void pushAPSInt(InterpState &S, const APSInt &Val) {
bool Signed = Val.isSigned();

if (Signed) {
switch (Val.getBitWidth()) {
case 64:
S.Stk.push<Integral<64, true>>(
Integral<64, true>::from(Val.getSExtValue()));
break;
case 32:
S.Stk.push<Integral<32, true>>(
Integral<32, true>::from(Val.getSExtValue()));
break;
case 16:
S.Stk.push<Integral<16, true>>(
Integral<16, true>::from(Val.getSExtValue()));
break;
case 8:
S.Stk.push<Integral<8, true>>(
Integral<8, true>::from(Val.getSExtValue()));
break;
default:
llvm_unreachable("Invalid integer bitwidth");
}
return;
}

// Unsigned.
switch (Val.getBitWidth()) {
case 64:
S.Stk.push<Integral<64, false>>(
Integral<64, false>::from(Val.getZExtValue()));
break;
case 32:
S.Stk.push<Integral<32, false>>(
Integral<32, false>::from(Val.getZExtValue()));
break;
case 16:
S.Stk.push<Integral<16, false>>(
Integral<16, false>::from(Val.getZExtValue()));
break;
case 8:
S.Stk.push<Integral<8, false>>(
Integral<8, false>::from(Val.getZExtValue()));
break;
default:
llvm_unreachable("Invalid integer bitwidth");
}
}

static void pushSizeT(InterpState &S, uint64_t Val) {
Expand All @@ -87,20 +128,29 @@ static void pushSizeT(InterpState &S, uint64_t Val) {
}
}

static bool retSizeT(InterpState &S, CodePtr OpPC, APValue &Result) {
const TargetInfo &TI = S.getCtx().getTargetInfo();
unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType());

switch (SizeTWidth) {
case 64:
return Ret<PT_Uint64>(S, OpPC, Result);
case 32:
return Ret<PT_Uint32>(S, OpPC, Result);
case 16:
return Ret<PT_Uint16>(S, OpPC, Result);
static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result,
std::optional<PrimType> &T) {
if (!T)
return RetVoid(S, OpPC, Result);

#define RET_CASE(X) \
case X: \
return Ret<X>(S, OpPC, Result);
switch (*T) {
RET_CASE(PT_Float);
RET_CASE(PT_Bool);
RET_CASE(PT_Sint8);
RET_CASE(PT_Uint8);
RET_CASE(PT_Sint16);
RET_CASE(PT_Uint16);
RET_CASE(PT_Sint32);
RET_CASE(PT_Uint32);
RET_CASE(PT_Sint64);
RET_CASE(PT_Uint64);
default:
llvm_unreachable("Unsupported return type for builtin function");
}

llvm_unreachable("size_t isn't 64 or 32 bit?");
#undef RET_CASE
}

static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
Expand Down Expand Up @@ -457,40 +507,55 @@ static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,
return true;
}

static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
pushAPSInt(S, APSInt(Val.reverseBits(), /*IsUnsigned=*/true));
return true;
}

bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
InterpFrame *Frame = S.Current;
APValue Dummy;

QualType ReturnType = Call->getCallReturnType(S.getCtx());
std::optional<PrimType> ReturnT = S.getContext().classify(ReturnType);
// If classify failed, we assume void.
assert(ReturnT || ReturnType->isVoidType());

switch (F->getBuiltinID()) {
case Builtin::BI__builtin_is_constant_evaluated:
S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
return Ret<PT_Bool>(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_assume:
return RetVoid(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_strcmp:
if (interp__builtin_strcmp(S, OpPC, Frame))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_strcmp(S, OpPC, Frame))
return false;
break;
case Builtin::BI__builtin_strlen:
if (interp__builtin_strlen(S, OpPC, Frame))
return retSizeT(S, OpPC, Dummy);
if (!interp__builtin_strlen(S, OpPC, Frame))
return false;
break;
case Builtin::BI__builtin_nan:
case Builtin::BI__builtin_nanf:
case Builtin::BI__builtin_nanl:
case Builtin::BI__builtin_nanf16:
case Builtin::BI__builtin_nanf128:
if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false))
return Ret<PT_Float>(S, OpPC, Dummy);
if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false))
return false;
break;
case Builtin::BI__builtin_nans:
case Builtin::BI__builtin_nansf:
case Builtin::BI__builtin_nansl:
case Builtin::BI__builtin_nansf16:
case Builtin::BI__builtin_nansf128:
if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true))
return Ret<PT_Float>(S, OpPC, Dummy);
if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true))
return false;
break;

case Builtin::BI__builtin_huge_val:
Expand All @@ -503,85 +568,85 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
case Builtin::BI__builtin_infl:
case Builtin::BI__builtin_inff16:
case Builtin::BI__builtin_inff128:
if (interp__builtin_inf(S, OpPC, Frame, F))
return Ret<PT_Float>(S, OpPC, Dummy);
if (!interp__builtin_inf(S, OpPC, Frame, F))
return false;
break;
case Builtin::BI__builtin_copysign:
case Builtin::BI__builtin_copysignf:
case Builtin::BI__builtin_copysignl:
case Builtin::BI__builtin_copysignf128:
if (interp__builtin_copysign(S, OpPC, Frame, F))
return Ret<PT_Float>(S, OpPC, Dummy);
if (!interp__builtin_copysign(S, OpPC, Frame, F))
return false;
break;

case Builtin::BI__builtin_fmin:
case Builtin::BI__builtin_fminf:
case Builtin::BI__builtin_fminl:
case Builtin::BI__builtin_fminf16:
case Builtin::BI__builtin_fminf128:
if (interp__builtin_fmin(S, OpPC, Frame, F))
return Ret<PT_Float>(S, OpPC, Dummy);
if (!interp__builtin_fmin(S, OpPC, Frame, F))
return false;
break;

case Builtin::BI__builtin_fmax:
case Builtin::BI__builtin_fmaxf:
case Builtin::BI__builtin_fmaxl:
case Builtin::BI__builtin_fmaxf16:
case Builtin::BI__builtin_fmaxf128:
if (interp__builtin_fmax(S, OpPC, Frame, F))
return Ret<PT_Float>(S, OpPC, Dummy);
if (!interp__builtin_fmax(S, OpPC, Frame, F))
return false;
break;

case Builtin::BI__builtin_isnan:
if (interp__builtin_isnan(S, OpPC, Frame, F))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_isnan(S, OpPC, Frame, F))
return false;
break;
case Builtin::BI__builtin_issignaling:
if (interp__builtin_issignaling(S, OpPC, Frame, F))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_issignaling(S, OpPC, Frame, F))
return false;
break;

case Builtin::BI__builtin_isinf:
if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false))
return false;
break;

case Builtin::BI__builtin_isinf_sign:
if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true))
return false;
break;

case Builtin::BI__builtin_isfinite:
if (interp__builtin_isfinite(S, OpPC, Frame, F))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_isfinite(S, OpPC, Frame, F))
return false;
break;
case Builtin::BI__builtin_isnormal:
if (interp__builtin_isnormal(S, OpPC, Frame, F))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_isnormal(S, OpPC, Frame, F))
return false;
break;
case Builtin::BI__builtin_issubnormal:
if (interp__builtin_issubnormal(S, OpPC, Frame, F))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_issubnormal(S, OpPC, Frame, F))
return false;
break;
case Builtin::BI__builtin_iszero:
if (interp__builtin_iszero(S, OpPC, Frame, F))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_iszero(S, OpPC, Frame, F))
return false;
break;
case Builtin::BI__builtin_isfpclass:
if (interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BI__builtin_fpclassify:
if (interp__builtin_fpclassify(S, OpPC, Frame, F))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_fpclassify(S, OpPC, Frame, F))
return false;
break;

case Builtin::BI__builtin_fabs:
case Builtin::BI__builtin_fabsf:
case Builtin::BI__builtin_fabsl:
case Builtin::BI__builtin_fabsf128:
if (interp__builtin_fabs(S, OpPC, Frame, F))
return Ret<PT_Float>(S, OpPC, Dummy);
if (!interp__builtin_fabs(S, OpPC, Frame, F))
return false;
break;

case Builtin::BI__builtin_popcount:
Expand All @@ -590,29 +655,37 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
case Builtin::BI__popcnt16: // Microsoft variants of popcount
case Builtin::BI__popcnt:
case Builtin::BI__popcnt64:
if (interp__builtin_popcount(S, OpPC, Frame, F, Call))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_popcount(S, OpPC, Frame, F, Call))
return false;
break;

case Builtin::BI__builtin_parity:
case Builtin::BI__builtin_parityl:
case Builtin::BI__builtin_parityll:
if (interp__builtin_parity(S, OpPC, Frame, F, Call))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_parity(S, OpPC, Frame, F, Call))
return false;
break;

case Builtin::BI__builtin_clrsb:
case Builtin::BI__builtin_clrsbl:
case Builtin::BI__builtin_clrsbll:
if (interp__builtin_clrsb(S, OpPC, Frame, F, Call))
return retInt(S, OpPC, Dummy);
if (!interp__builtin_clrsb(S, OpPC, Frame, F, Call))
return false;
break;

case Builtin::BI__builtin_bitreverse8:
case Builtin::BI__builtin_bitreverse16:
case Builtin::BI__builtin_bitreverse32:
case Builtin::BI__builtin_bitreverse64:
if (!interp__builtin_bitreverse(S, OpPC, Frame, F, Call))
return false;
break;

default:
return false;
}

return false;
return retPrimValue(S, OpPC, Dummy, ReturnT);
}

bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Driver/ToolChains/DragonFly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const auto &ToolChain = static_cast<const DragonFly &>(getToolChain());
const Driver &D = ToolChain.getDriver();
const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool Static = Args.hasArg(options::OPT_static);
const bool Shared = Args.hasArg(options::OPT_shared);
const bool Profiling = Args.hasArg(options::OPT_pg);
const bool Pie = Args.hasArg(options::OPT_pie);
ArgStringList CmdArgs;
bool Static = Args.hasArg(options::OPT_static);
bool Shared = Args.hasArg(options::OPT_shared);
bool Profiling = Args.hasArg(options::OPT_pg);
bool Pie = Args.hasArg(options::OPT_pie);

if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
Expand Down
55 changes: 22 additions & 33 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,18 +292,6 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
}
}

static bool getPIE(const ArgList &Args, const ToolChain &TC) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) ||
Args.hasArg(options::OPT_r) || Args.hasArg(options::OPT_static_pie))
return false;

Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
options::OPT_nopie);
if (!A)
return TC.isPIEDefault(Args);
return A->getOption().matches(options::OPT_pie);
}

static bool getStaticPIE(const ArgList &Args, const ToolChain &TC) {
bool HasStaticPIE = Args.hasArg(options::OPT_static_pie);
// -no-pie is an alias for -nopie. So, handling -nopie takes care of
Expand Down Expand Up @@ -386,7 +374,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const bool isAndroid = ToolChain.getTriple().isAndroid();
const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
const bool IsVE = ToolChain.getTriple().isVE();
const bool IsPIE = getPIE(Args, ToolChain);
const bool IsStaticPIE = getStaticPIE(Args, ToolChain);
const bool IsStatic = getStatic(Args);
const bool HasCRTBeginEndFiles =
Expand All @@ -406,17 +393,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

if (IsPIE)
CmdArgs.push_back("-pie");

if (IsStaticPIE) {
CmdArgs.push_back("-static");
CmdArgs.push_back("-pie");
CmdArgs.push_back("--no-dynamic-linker");
CmdArgs.push_back("-z");
CmdArgs.push_back("text");
}

if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");

Expand Down Expand Up @@ -451,19 +427,32 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Triple.isRISCV())
CmdArgs.push_back("-X");

if (Args.hasArg(options::OPT_shared))
const bool IsShared = Args.hasArg(options::OPT_shared);
if (IsShared)
CmdArgs.push_back("-shared");

if (IsStatic) {
bool IsPIE = false;
if (IsStaticPIE) {
CmdArgs.push_back("-static");
CmdArgs.push_back("-pie");
CmdArgs.push_back("--no-dynamic-linker");
CmdArgs.push_back("-z");
CmdArgs.push_back("text");
} else if (IsStatic) {
CmdArgs.push_back("-static");
} else if (!Args.hasArg(options::OPT_r) &&
!Args.hasArg(options::OPT_shared) && !IsStaticPIE) {
} else if (!Args.hasArg(options::OPT_r)) {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");

CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
ToolChain.getDynamicLinker(Args)));
if (!IsShared) {
Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
options::OPT_nopie);
IsPIE = A ? A->getOption().matches(options::OPT_pie)
: ToolChain.isPIEDefault(Args);
if (IsPIE)
CmdArgs.push_back("-pie");
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
ToolChain.getDynamicLinker(Args)));
}
}

CmdArgs.push_back("-o");
Expand Down
14 changes: 7 additions & 7 deletions clang/lib/Driver/ToolChains/OpenBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const auto &ToolChain = static_cast<const OpenBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
const llvm::Triple &Triple = ToolChain.getTriple();
ArgStringList CmdArgs;

claimNoWarnArgs(Args);
ArgStringList CmdArgs;

switch (ToolChain.getArch()) {
case llvm::Triple::x86:
Expand Down Expand Up @@ -112,13 +112,13 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const auto &ToolChain = static_cast<const OpenBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
const llvm::Triple::ArchType Arch = ToolChain.getArch();
ArgStringList CmdArgs;
bool Static = Args.hasArg(options::OPT_static);
bool Shared = Args.hasArg(options::OPT_shared);
bool Profiling = Args.hasArg(options::OPT_pg);
bool Pie = Args.hasArg(options::OPT_pie);
bool Nopie = Args.hasArg(options::OPT_nopie);
const bool Static = Args.hasArg(options::OPT_static);
const bool Shared = Args.hasArg(options::OPT_shared);
const bool Profiling = Args.hasArg(options::OPT_pg);
const bool Pie = Args.hasArg(options::OPT_pie);
const bool Nopie = Args.hasArg(options::OPT_nopie);
const bool Relocatable = Args.hasArg(options::OPT_r);
ArgStringList CmdArgs;

// Silence warning for "clang -g foo.o -o foo"
Args.ClaimAllArgs(options::OPT_g_Group);
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/Format/QualifierAlignmentFixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,14 +535,21 @@ LeftRightQualifierAlignmentFixer::analyze(
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens) {
tooling::Replacements Fixes;
const AdditionalKeywords &Keywords = Tokens.getKeywords();
const SourceManager &SourceMgr = Env.getSourceManager();
AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
fixQualifierAlignment(AnnotatedLines, Tokens, Fixes);
return {Fixes, 0};
}

void LeftRightQualifierAlignmentFixer::fixQualifierAlignment(
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, FormatTokenLexer &Tokens,
tooling::Replacements &Fixes) {
const AdditionalKeywords &Keywords = Tokens.getKeywords();
const SourceManager &SourceMgr = Env.getSourceManager();
tok::TokenKind QualifierToken = getTokenFromQualifier(Qualifier);
assert(QualifierToken != tok::identifier && "Unrecognised Qualifier");

for (AnnotatedLine *Line : AnnotatedLines) {
fixQualifierAlignment(Line->Children, Tokens, Fixes);
if (!Line->Affected || Line->InPPDirective)
continue;
FormatToken *First = Line->First;
Expand All @@ -565,7 +572,6 @@ LeftRightQualifierAlignmentFixer::analyze(
}
}
}
return {Fixes, 0};
}

void prepareLeftRightOrderingForQualifierAlignmentFixer(
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Format/QualifierAlignmentFixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class LeftRightQualifierAlignmentFixer : public TokenAnalyzer {

static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier);

void fixQualifierAlignment(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
FormatTokenLexer &Tokens,
tooling::Replacements &Fixes);

const FormatToken *analyzeRight(const SourceManager &SourceMgr,
const AdditionalKeywords &Keywords,
tooling::Replacements &Fixes,
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw___ibm128:
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw__Accum:
case tok::kw__Fract:
case tok::kw__Sat:
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
#include "clang/Basic/TransformTypeTraits.def"
case tok::kw___auto_type:
Expand Down
30 changes: 30 additions & 0 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4506,6 +4506,36 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
.get();
break;

case ICK_Fixed_Point_Conversion:
assert((FromType->isFixedPointType() || ToType->isFixedPointType()) &&
"Attempting implicit fixed point conversion without a fixed "
"point operand");
if (FromType->isFloatingType())
From = ImpCastExprToType(From, ToType, CK_FloatingToFixedPoint,
VK_PRValue,
/*BasePath=*/nullptr, CCK).get();
else if (ToType->isFloatingType())
From = ImpCastExprToType(From, ToType, CK_FixedPointToFloating,
VK_PRValue,
/*BasePath=*/nullptr, CCK).get();
else if (FromType->isIntegralType(Context))
From = ImpCastExprToType(From, ToType, CK_IntegralToFixedPoint,
VK_PRValue,
/*BasePath=*/nullptr, CCK).get();
else if (ToType->isIntegralType(Context))
From = ImpCastExprToType(From, ToType, CK_FixedPointToIntegral,
VK_PRValue,
/*BasePath=*/nullptr, CCK).get();
else if (ToType->isBooleanType())
From = ImpCastExprToType(From, ToType, CK_FixedPointToBoolean,
VK_PRValue,
/*BasePath=*/nullptr, CCK).get();
else
From = ImpCastExprToType(From, ToType, CK_FixedPointCast,
VK_PRValue,
/*BasePath=*/nullptr, CCK).get();
break;

case ICK_Compatible_Conversion:
From = ImpCastExprToType(From, ToType, CK_NoOp, From->getValueKind(),
/*BasePath=*/nullptr, CCK).get();
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
// it was omitted by the patch that added
// ICK_Zero_Queue_Conversion
ICR_C_Conversion,
ICR_C_Conversion_Extension
ICR_C_Conversion_Extension,
ICR_Conversion,
};
static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds);
return Rank[(int)Kind];
Expand Down Expand Up @@ -197,7 +198,8 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"OpenCL Zero Event Conversion",
"OpenCL Zero Queue Conversion",
"C specific type conversion",
"Incompatible pointer conversion"
"Incompatible pointer conversion",
"Fixed point conversion",
};
static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds);
return Name[Kind];
Expand Down Expand Up @@ -2189,6 +2191,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
From->isIntegerConstantExpr(S.getASTContext())) {
SCS.Second = ICK_Compatible_Conversion;
FromType = ToType;
} else if (ToType->isFixedPointType() || FromType->isFixedPointType()) {
SCS.Second = ICK_Fixed_Point_Conversion;
FromType = ToType;
} else {
// No second conversion required.
SCS.Second = ICK_Identity;
Expand Down Expand Up @@ -5947,6 +5952,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Zero_Event_Conversion:
case ICK_C_Only_Conversion:
case ICK_Incompatible_Pointer_Conversion:
case ICK_Fixed_Point_Conversion:
return false;

case ICK_Lvalue_To_Rvalue:
Expand Down
7 changes: 7 additions & 0 deletions clang/test/AST/Interp/builtin-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,10 @@ namespace clrsb {
char clrsb11[__builtin_clrsb(0xf) == BITSIZE(int) - 5 ? 1 : -1];
char clrsb12[__builtin_clrsb(~0x1f) == BITSIZE(int) - 6 ? 1 : -1];
}

namespace bitreverse {
char bitreverse1[__builtin_bitreverse8(0x01) == 0x80 ? 1 : -1];
char bitreverse2[__builtin_bitreverse16(0x3C48) == 0x123C ? 1 : -1];
char bitreverse3[__builtin_bitreverse32(0x12345678) == 0x1E6A2C48 ? 1 : -1];
char bitreverse4[__builtin_bitreverse64(0x0123456789ABCDEFULL) == 0xF7B3D591E6A2C480 ? 1 : -1];
}
6 changes: 6 additions & 0 deletions clang/test/Driver/aarch64-mcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@
// CORTEXX1C: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-x1c"
// RUN: %clang --target=aarch64 -mcpu=cortex-x3 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEXX3 %s
// CORTEXX3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-x3"
// RUN: %clang --target=aarch64 -mcpu=cortex-x4 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-X4 %s
// CORTEX-X4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-x4"
// RUN: %clang --target=aarch64 -mcpu=cortex-a78 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEXA78 %s
// CORTEXA78: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a78"
// RUN: %clang --target=aarch64 -mcpu=cortex-a78c -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A78C %s
// CORTEX-A78C: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a78c"
// RUN: %clang --target=aarch64 -mcpu=cortex-a715 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A715 %s
// CORTEX-A715: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a715"
// RUN: %clang --target=aarch64 -mcpu=cortex-a720 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A720 %s
// CORTEX-A720: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a720"
// RUN: %clang --target=aarch64 -mcpu=neoverse-e1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-E1 %s
// NEOVERSE-E1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-e1"
// RUN: %clang --target=aarch64 -mcpu=neoverse-v1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-V1 %s
Expand All @@ -62,6 +66,8 @@
// NEOVERSE-N2: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-n2"
// RUN: %clang --target=aarch64 -mcpu=neoverse-512tvb -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-512TVB %s
// NEOVERSE-512TVB: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-512tvb"
// RUN: %clang --target=aarch64 -mcpu=cortex-a520 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A520 %s
// CORTEX-A520: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a520"

// RUN: %clang --target=aarch64 -mcpu=cortex-r82 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEXR82 %s
// CORTEXR82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-r82"
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Driver/dynamic-linker.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// RUN: %clang -target x86_64-unknown-linux-gnu -### -shared /dev/null -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-SHARED %s


// RUN: %clang -target armv7-unknown-linux-gnueabi -### -shared -rdynamic /dev/null -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-SHARED %s
// RUN: %clang --target=armv7-unknown-linux-gnueabi -### -Werror -shared -rdynamic /dev/null -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-SHARED %s
// RUN: %clang -target i386-unknown-linux-gnu -### -shared -rdynamic /dev/null -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-SHARED %s
// RUN: %clang -target mips64-unknown-linux-gnu -### -shared -rdynamic /dev/null -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-SHARED %s
// RUN: %clang -target powerpc64-unknown-linux-gnu -### -shared -rdynamic /dev/null -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-SHARED %s
Expand Down
18 changes: 3 additions & 15 deletions clang/test/Driver/linux-ld.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,8 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE %s
// CHECK-CLANG-LD-STATIC-PIE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-CLANG-LD-STATIC-PIE: "-static"
// CHECK-CLANG-LD-STATIC-PIE: "-pie"
// CHECK-CLANG-LD-STATIC-PIE: "--no-dynamic-linker"
// CHECK-CLANG-LD-STATIC-PIE: "-z"
// CHECK-CLANG-LD-STATIC-PIE: "text"
// CHECK-CLANG-LD-STATIC-PIE: "-m" "elf_x86_64"
// CHECK-CLANG-LD-STATIC-PIE-SAME: "-static" "-pie" "--no-dynamic-linker" "-z" "text"
// CHECK-CLANG-LD-STATIC-PIE: "{{.*}}rcrt1.o"
// CHECK-CLANG-LD-STATIC-PIE: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
//
Expand All @@ -197,12 +193,8 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-PIE %s
// CHECK-CLANG-LD-STATIC-PIE-PIE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "-static"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "-pie"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "--no-dynamic-linker"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "-z"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "text"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "-m" "elf_x86_64"
// CHECK-CLANG-LD-STATIC-PIE-PIE-SAME: "-static" "-pie" "--no-dynamic-linker" "-z" "text"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "{{.*}}rcrt1.o"
// CHECK-CLANG-LD-STATIC-PIE-PIE: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
//
Expand All @@ -212,12 +204,8 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-STATIC %s
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "-static"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "-pie"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "--no-dynamic-linker"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "-z"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "text"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "-m" "elf_x86_64"
// CHECK-CLANG-LD-STATIC-PIE-STATIC-SAME: "-static" "-pie" "--no-dynamic-linker" "-z" "text"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "{{.*}}rcrt1.o"
// CHECK-CLANG-LD-STATIC-PIE-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
//
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Driver/ohos.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
// CHECK-NOT: "-fno-common"
// CHECK: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]"
// CHECK-NOT: "--sysroot=[[SYSROOT]]"
// CHECK: "-pie"
// CHECK-NOT: "--build-id"
// CHECK: "--hash-style=both"
// CHECK: "-pie"
// CHECK: "-dynamic-linker" "/lib/ld-musl-arm.so.1"
// CHECK: Scrt1.o
// CHECK: crti.o
Expand Down
14 changes: 12 additions & 2 deletions clang/test/Frontend/fixed_point_conversions.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s --check-prefixes=CHECK,UNSIGNED
// RUN: %clang_cc1 -x c -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -x c -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s --check-prefixes=CHECK,UNSIGNED
// RUN: %clang_cc1 -x c++ -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -x c++ -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s --check-prefixes=CHECK,UNSIGNED

#ifdef __cplusplus
extern "C" {
#endif

short _Accum sa;
_Accum a, a2;
Expand Down Expand Up @@ -994,3 +1000,7 @@ void float_sat5(void) {
void float_sat6(void) {
sat_uf = fl;
}

#ifdef __cplusplus
}
#endif
2 changes: 1 addition & 1 deletion clang/test/Misc/cc1as-compress.s
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
// ZSTD: 0000 02000000 00000000

.section .debug_str,"MS",@progbits,1
.asciz "perfectly compressable data sample *****************************************"
.asciz "perfectly compressable data sample ******************************************"
4 changes: 2 additions & 2 deletions clang/test/Misc/target-invalid-cpu-note.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

// RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64
// AARCH64: error: unknown target CPU 'not-a-cpu'
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-m1, apple-m2, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, grace{{$}}
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-m1, apple-m2, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, grace{{$}}

// RUN: not %clang_cc1 -triple arm64--- -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE_AARCH64
// TUNE_AARCH64: error: unknown target CPU 'not-a-cpu'
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-m1, apple-m2, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, grace{{$}}
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-m1, apple-m2, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, grace{{$}}

// RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86
// X86: error: unknown target CPU 'not-a-cpu'
Expand Down
5 changes: 4 additions & 1 deletion clang/test/Sema/builtin-classify-type.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ enum gcc_type_class {
function_type_class, method_type_class,
record_type_class, union_type_class,
array_type_class, string_type_class,
lang_type_class
lang_type_class, opaque_type_class,
bitint_type_class
};

void foo(void) {
Expand Down Expand Up @@ -45,6 +46,7 @@ void foo(void) {
vint32_t3 vt5;
typedef _BitInt(64) vint64_t3 __attribute__((vector_size(16)));
vint64_t3 vt6;
_BitInt(16) bitint;

_Atomic int atomic_i;
_Atomic double atomic_d;
Expand All @@ -70,6 +72,7 @@ void foo(void) {
int a17[__builtin_classify_type(atomic_d) == real_type_class ? 1 : -1];
int a18[__builtin_classify_type(complex_i) == complex_type_class ? 1 : -1];
int a19[__builtin_classify_type(complex_d) == complex_type_class ? 1 : -1];
int a20[__builtin_classify_type(bitint) == bitint_type_class ? 1 : -1];
}

extern int (^p)(void);
Expand Down
5 changes: 4 additions & 1 deletion clang/test/SemaCXX/builtin-classify-type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ enum gcc_type_class {
function_type_class, method_type_class,
record_type_class, union_type_class,
array_type_class, string_type_class,
lang_type_class
lang_type_class, opaque_type_class,
bitint_type_class
};

class cl {
Expand Down Expand Up @@ -42,6 +43,7 @@ void foo() {
_Atomic double atomic_d;
_Complex int complex_i;
_Complex double complex_d;
_BitInt(32) bitint;

int a1[__builtin_classify_type(f()) == void_type_class ? 1 : -1];
int a2[__builtin_classify_type(i) == integer_type_class ? 1 : -1];
Expand All @@ -65,5 +67,6 @@ void foo() {
int a20[__builtin_classify_type(atomic_d) == real_type_class ? 1 : -1];
int a21[__builtin_classify_type(complex_i) == complex_type_class ? 1 : -1];
int a22[__builtin_classify_type(complex_d) == complex_type_class ? 1 : -1];
int a23[__builtin_classify_type(bitint) == bitint_type_class ? 1 : -1];
}

6 changes: 6 additions & 0 deletions clang/unittests/Format/QualifierFixerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,9 @@ TEST_F(QualifierFixerTest, RightQualifier) {
verifyFormat("void f(std::integral auto const &x);",
"void f(const std::integral auto &x);", Style);

verifyFormat("auto lambda = [] { int const i = 0; };",
"auto lambda = [] { const int i = 0; };", Style);

verifyFormat("Foo<Foo<int> const> P;\n#if 0\n#else\n#endif",
"Foo<const Foo<int>> P;\n#if 0\n#else\n#endif", Style);

Expand Down Expand Up @@ -663,6 +666,9 @@ TEST_F(QualifierFixerTest, LeftQualifier) {
verifyFormat("void f(const std::integral auto &x);",
"void f(std::integral auto const &x);", Style);

verifyFormat("auto lambda = [] { const int i = 0; };",
"auto lambda = [] { int const i = 0; };", Style);

verifyFormat("Foo<const Foo<int>> P;\n#if 0\n#else\n#endif",
"Foo<Foo<int> const> P;\n#if 0\n#else\n#endif", Style);

Expand Down
151 changes: 151 additions & 0 deletions compiler-rt/lib/orc/bitmask_enum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
//===---- bitmask_enum.h - Enable bitmask operations on enums ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of the ORC runtime support library.
//
//===----------------------------------------------------------------------===//

#ifndef ORC_RT_BITMASK_ENUM_H
#define ORC_RT_BITMASK_ENUM_H

#include "stl_extras.h"

#include <cassert>
#include <type_traits>

namespace __orc_rt {

/// ORC_RT_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you
/// can perform bitwise operations on it without putting static_cast everywhere.
///
/// \code
/// enum MyEnum {
/// E1 = 1, E2 = 2, E3 = 4, E4 = 8,
/// ORC_RT_MARK_AS_BITMASK_ENUM(/* LargestValue = */ E4)
/// };
///
/// void Foo() {
/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // Look, ma: No static_cast!
/// }
/// \endcode
///
/// Normally when you do a bitwise operation on an enum value, you get back an
/// instance of the underlying type (e.g. int). But using this macro, bitwise
/// ops on your enum will return you back instances of the enum. This is
/// particularly useful for enums which represent a combination of flags.
///
/// The parameter to ORC_RT_MARK_AS_BITMASK_ENUM should be the largest
/// individual value in your enum.
///
/// All of the enum's values must be non-negative.
#define ORC_RT_MARK_AS_BITMASK_ENUM(LargestValue) \
ORC_RT_BITMASK_LARGEST_ENUMERATOR = LargestValue

/// ORC_RT_DECLARE_ENUM_AS_BITMASK can be used to declare an enum type as a bit
/// set, so that bitwise operation on such enum does not require static_cast.
///
/// \code
/// enum MyEnum { E1 = 1, E2 = 2, E3 = 4, E4 = 8 };
/// ORC_RT_DECLARE_ENUM_AS_BITMASK(MyEnum, E4);
///
/// void Foo() {
/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // No static_cast
/// }
/// \endcode
///
/// The second parameter to ORC_RT_DECLARE_ENUM_AS_BITMASK specifies the largest
/// bit value of the enum type.
///
/// ORC_RT_DECLARE_ENUM_AS_BITMASK should be used in __orc_rt namespace.
///
/// This a non-intrusive alternative for ORC_RT_MARK_AS_BITMASK_ENUM. It allows
/// declaring more than one non-scoped enumerations as bitmask types in the same
/// scope. Otherwise it provides the same functionality as
/// ORC_RT_MARK_AS_BITMASK_ENUM.
#define ORC_RT_DECLARE_ENUM_AS_BITMASK(Enum, LargestValue) \
template <> struct is_bitmask_enum<Enum> : std::true_type {}; \
template <> struct largest_bitmask_enum_bit<Enum> { \
static constexpr std::underlying_type_t<Enum> value = LargestValue; \
}

/// Traits class to determine whether an enum has been declared as a bitwise
/// enum via ORC_RT_DECLARE_ENUM_AS_BITMASK.
template <typename E, typename Enable = void>
struct is_bitmask_enum : std::false_type {};

template <typename E>
struct is_bitmask_enum<
E, std::enable_if_t<sizeof(E::ORC_RT_BITMASK_LARGEST_ENUMERATOR) >= 0>>
: std::true_type {};

template <typename E>
inline constexpr bool is_bitmask_enum_v = is_bitmask_enum<E>::value;

/// Traits class to deermine bitmask enum largest bit.
template <typename E, typename Enable = void> struct largest_bitmask_enum_bit;

template <typename E>
struct largest_bitmask_enum_bit<
E, std::enable_if_t<sizeof(E::ORC_RT_BITMASK_LARGEST_ENUMERATOR) >= 0>> {
using UnderlyingTy = std::underlying_type_t<E>;
static constexpr UnderlyingTy value =
static_cast<UnderlyingTy>(E::ORC_RT_BITMASK_LARGEST_ENUMERATOR);
};

template <typename E> constexpr std::underlying_type_t<E> Mask() {
return bit_ceil(largest_bitmask_enum_bit<E>::value) - 1;
}

template <typename E> constexpr std::underlying_type_t<E> Underlying(E Val) {
auto U = static_cast<std::underlying_type_t<E>>(Val);
assert(U >= 0 && "Negative enum values are not allowed");
assert(U <= Mask<E>() && "Enum value too large (or langest val too small");
return U;
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum_v<E>>>
constexpr E operator~(E Val) {
return static_cast<E>(~Underlying(Val) & Mask<E>());
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum_v<E>>>
constexpr E operator|(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) | Underlying(RHS));
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum_v<E>>>
constexpr E operator&(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) & Underlying(RHS));
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum_v<E>>>
constexpr E operator^(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) ^ Underlying(RHS));
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum_v<E>>>
E &operator|=(E &LHS, E RHS) {
LHS = LHS | RHS;
return LHS;
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum_v<E>>>
E &operator&=(E &LHS, E RHS) {
LHS = LHS & RHS;
return LHS;
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum_v<E>>>
E &operator^=(E &LHS, E RHS) {
LHS = LHS ^ RHS;
return LHS;
}

} // end namespace __orc_rt

#endif // ORC_RT_BITMASK_ENUM_H
12 changes: 12 additions & 0 deletions compiler-rt/lib/orc/stl_extras.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef ORC_RT_STL_EXTRAS_H
#define ORC_RT_STL_EXTRAS_H

#include <cstdint>
#include <utility>
#include <tuple>

Expand All @@ -28,6 +29,17 @@ template <class Ty> struct identity {
const Ty &operator()(const Ty &self) const { return self; }
};

/// Substitute for std::bit_ceil.
constexpr uint64_t bit_ceil(uint64_t Val) noexcept {
Val |= (Val >> 1);
Val |= (Val >> 2);
Val |= (Val >> 4);
Val |= (Val >> 8);
Val |= (Val >> 16);
Val |= (Val >> 32);
return Val + 1;
}

} // namespace __orc_rt

#endif // ORC_RT_STL_EXTRAS
1 change: 1 addition & 0 deletions compiler-rt/lib/orc/tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set(UNITTEST_SOURCES
adt_test.cpp
bitmask_enum_test.cpp
c_api_test.cpp
endian_test.cpp
error_test.cpp
Expand Down
143 changes: 143 additions & 0 deletions compiler-rt/lib/orc/tests/unit/bitmask_enum_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//===-- adt_test.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of the ORC runtime.
//
//===----------------------------------------------------------------------===//

#include "bitmask_enum.h"
#include "gtest/gtest.h"

#include <sstream>
#include <string>

using namespace __orc_rt;

namespace {

enum Flags { F0 = 0, F1 = 1, F2 = 2, F3 = 4, F4 = 8 };

} // namespace

namespace __orc_rt {
ORC_RT_DECLARE_ENUM_AS_BITMASK(Flags, F4);
} // namespace __orc_rt

static_assert(is_bitmask_enum<Flags>::value != 0);
static_assert(largest_bitmask_enum_bit<Flags>::value == Flags::F4);

namespace {

static_assert(is_bitmask_enum<Flags>::value != 0);
static_assert(largest_bitmask_enum_bit<Flags>::value == Flags::F4);

TEST(BitmaskEnumTest, BitwiseOr) {
Flags f = F1 | F2;
EXPECT_EQ(3, f);

f = f | F3;
EXPECT_EQ(7, f);
}

TEST(BitmaskEnumTest, BitwiseOrEquals) {
Flags f = F1;
f |= F3;
EXPECT_EQ(5, f);

// |= should return a reference to the LHS.
f = F2;
(f |= F3) = F1;
EXPECT_EQ(F1, f);
}

TEST(BitmaskEnumTest, BitwiseAnd) {
Flags f = static_cast<Flags>(3) & F2;
EXPECT_EQ(F2, f);

f = (f | F3) & (F1 | F2 | F3);
EXPECT_EQ(6, f);
}

TEST(BitmaskEnumTest, BitwiseAndEquals) {
Flags f = F1 | F2 | F3;
f &= F1 | F2;
EXPECT_EQ(3, f);

// &= should return a reference to the LHS.
(f &= F1) = F3;
EXPECT_EQ(F3, f);
}

TEST(BitmaskEnumTest, BitwiseXor) {
Flags f = (F1 | F2) ^ (F2 | F3);
EXPECT_EQ(5, f);

f = f ^ F1;
EXPECT_EQ(4, f);
}

TEST(BitmaskEnumTest, BitwiseXorEquals) {
Flags f = (F1 | F2);
f ^= (F2 | F4);
EXPECT_EQ(9, f);

// ^= should return a reference to the LHS.
(f ^= F4) = F3;
EXPECT_EQ(F3, f);
}

TEST(BitmaskEnumTest, ConstantExpression) {
constexpr Flags f1 = ~F1;
constexpr Flags f2 = F1 | F2;
constexpr Flags f3 = F1 & F2;
constexpr Flags f4 = F1 ^ F2;
EXPECT_EQ(f1, ~F1);
EXPECT_EQ(f2, F1 | F2);
EXPECT_EQ(f3, F1 & F2);
EXPECT_EQ(f4, F1 ^ F2);
}

TEST(BitmaskEnumTest, BitwiseNot) {
Flags f = ~F1;
EXPECT_EQ(14, f); // Largest value for f is 15.
EXPECT_EQ(15, ~F0);
}

enum class FlagsClass {
F0 = 0,
F1 = 1,
F2 = 2,
F3 = 4,
ORC_RT_MARK_AS_BITMASK_ENUM(F3)
};

TEST(BitmaskEnumTest, ScopedEnum) {
FlagsClass f = (FlagsClass::F1 & ~FlagsClass::F0) | FlagsClass::F2;
f |= FlagsClass::F3;
EXPECT_EQ(7, static_cast<int>(f));
}

struct Container {
enum Flags {
F0 = 0,
F1 = 1,
F2 = 2,
F3 = 4,
ORC_RT_MARK_AS_BITMASK_ENUM(F3)
};

static Flags getFlags() {
Flags f = F0 | F1;
f |= F2;
return f;
}
};

TEST(BitmaskEnumTest, EnumInStruct) { EXPECT_EQ(3, Container::getFlags()); }

} // namespace
688 changes: 688 additions & 0 deletions flang/docs/AssumedRank.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions flang/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ on how to get in touch with us and to learn more about the current status.
Aliasing
AliasingAnalysisFIR
ArrayComposition
AssumedRank
BijectiveInternalNameUniquing
Calls
Character
Expand Down
45 changes: 28 additions & 17 deletions flang/lib/Lower/OpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ static void createDeclareAllocFuncWithArg(mlir::OpBuilder &modBuilder,
builder, loc, boxAddrOp.getResult(), asFortran, bounds,
/*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType());
builder.create<mlir::acc::DeclareEnterOp>(
loc, mlir::ValueRange(entryOp.getAccPtr()));
loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()),
mlir::ValueRange(entryOp.getAccPtr()));

modBuilder.setInsertionPointAfter(registerFuncOp);
builder.restoreInsertionPoint(crtInsPt);
Expand Down Expand Up @@ -195,7 +196,7 @@ static void createDeclareDeallocFuncWithArg(
/*structured=*/false, /*implicit=*/false, clause,
boxAddrOp.getType());
builder.create<mlir::acc::DeclareExitOp>(
loc, mlir::ValueRange(entryOp.getAccPtr()));
loc, mlir::Value{}, mlir::ValueRange(entryOp.getAccPtr()));

mlir::Value varPtr;
if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
Expand Down Expand Up @@ -2762,7 +2763,13 @@ static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
EntryOp entryOp = createDataEntryOp<EntryOp>(
builder, loc, addrOp.getResTy(), asFortran, bounds,
/*structured=*/false, implicit, clause, addrOp.getResTy().getType());
builder.create<DeclareOp>(loc, mlir::ValueRange(entryOp.getAccPtr()));
if constexpr (std::is_same_v<DeclareOp, mlir::acc::DeclareEnterOp>)
builder.create<DeclareOp>(
loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()),
mlir::ValueRange(entryOp.getAccPtr()));
else
builder.create<DeclareOp>(loc, mlir::Value{},
mlir::ValueRange(entryOp.getAccPtr()));
mlir::Value varPtr;
if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(), varPtr,
Expand Down Expand Up @@ -2812,7 +2819,8 @@ static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
builder, loc, boxAddrOp.getResult(), asFortran, bounds,
/*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType());
builder.create<mlir::acc::DeclareEnterOp>(
loc, mlir::ValueRange(entryOp.getAccPtr()));
loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()),
mlir::ValueRange(entryOp.getAccPtr()));

modBuilder.setInsertionPointAfter(registerFuncOp);
}
Expand Down Expand Up @@ -2850,7 +2858,7 @@ static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder,
boxAddrOp.getType());

builder.create<mlir::acc::DeclareExitOp>(
loc, mlir::ValueRange(entryOp.getAccPtr()));
loc, mlir::Value{}, mlir::ValueRange(entryOp.getAccPtr()));

mlir::Value varPtr;
if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
Expand Down Expand Up @@ -3092,34 +3100,37 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,

mlir::func::FuncOp funcOp = builder.getFunction();
auto ops = funcOp.getOps<mlir::acc::DeclareEnterOp>();
mlir::Value declareToken;
if (ops.empty()) {
builder.create<mlir::acc::DeclareEnterOp>(loc, dataClauseOperands);
declareToken = builder.create<mlir::acc::DeclareEnterOp>(
loc, mlir::acc::DeclareTokenType::get(builder.getContext()),
dataClauseOperands);
} else {
auto declareOp = *ops.begin();
auto newDeclareOp = builder.create<mlir::acc::DeclareEnterOp>(
loc, declareOp.getDataClauseOperands());
loc, mlir::acc::DeclareTokenType::get(builder.getContext()),
declareOp.getDataClauseOperands());
newDeclareOp.getDataClauseOperandsMutable().append(dataClauseOperands);
declareToken = newDeclareOp.getToken();
declareOp.erase();
}

openAccCtx.attachCleanup([&builder, loc, createEntryOperands,
copyEntryOperands, copyoutEntryOperands,
deviceResidentEntryOperands]() {
deviceResidentEntryOperands, declareToken]() {
llvm::SmallVector<mlir::Value> operands;
operands.append(createEntryOperands);
operands.append(deviceResidentEntryOperands);
operands.append(copyEntryOperands);
operands.append(copyoutEntryOperands);

if (!operands.empty()) {
mlir::func::FuncOp funcOp = builder.getFunction();
auto ops = funcOp.getOps<mlir::acc::DeclareExitOp>();
if (ops.empty()) {
builder.create<mlir::acc::DeclareExitOp>(loc, operands);
} else {
auto declareOp = *ops.begin();
declareOp.getDataClauseOperandsMutable().append(operands);
}
mlir::func::FuncOp funcOp = builder.getFunction();
auto ops = funcOp.getOps<mlir::acc::DeclareExitOp>();
if (ops.empty()) {
builder.create<mlir::acc::DeclareExitOp>(loc, declareToken, operands);
} else {
auto declareOp = *ops.begin();
declareOp.getDataClauseOperandsMutable().append(operands);
}

genDataExitOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
Expand Down
28 changes: 14 additions & 14 deletions flang/test/Lower/OpenACC/HLFIR/acc-declare.f90
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ subroutine acc_declare_copy()
! ALL: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index)
! FIR: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL]] : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copy>, name = "a"}
! HLFIR: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL]]#1 : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copy>, name = "a"}
! ALL: acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>)
! ALL: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>)

! ALL: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (index, i32) {
! ALL: }
! ALL: acc.declare_exit dataOperands(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>)
! ALL: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>)
! FIR: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) to varPtr(%[[DECL]] : !fir.ref<!fir.array<100xi32>>) {dataClause = #acc<data_clause acc_copy>, name = "a"}
! HLFIR: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) to varPtr(%[[DECL]]#1 : !fir.ref<!fir.array<100xi32>>) {dataClause = #acc<data_clause acc_copy>, name = "a"}

Expand All @@ -51,11 +51,11 @@ subroutine acc_declare_create()
! ALL: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index)
! FIR: %[[CREATE:.*]] = acc.create varPtr(%[[DECL]] : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
! HLFIR: %[[CREATE:.*]] = acc.create varPtr(%[[DECL]]#1 : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
! ALL: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
! ALL: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)

! ALL: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (index, i32) {
! ALL: }
! ALL: acc.declare_exit dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
! ALL: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
! ALL: acc.delete accPtr(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>) bounds(%[[BOUND]]) {dataClause = #acc<data_clause acc_create>, name = "a"}
! ALL: return

Expand Down Expand Up @@ -119,10 +119,10 @@ subroutine acc_declare_copyout()
! HLFIR: %[[ADECL:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) {acc.declare = #acc.declare<dataClause = acc_copyout>, uniq_name = "_QMacc_declareFacc_declare_copyoutEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
! FIR: %[[CREATE:.*]] = acc.create varPtr(%[[ADECL]] : !fir.ref<!fir.array<100xi32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"}
! HLFIR: %[[CREATE:.*]] = acc.create varPtr(%[[ADECL]]#1 : !fir.ref<!fir.array<100xi32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"}
! ALL: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
! ALL: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
! ALL: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32)

! ALL: acc.declare_exit dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
! ALL: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
! FIR: acc.copyout accPtr(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>) bounds(%{{.*}}) to varPtr(%[[ADECL]] : !fir.ref<!fir.array<100xi32>>) {name = "a"}
! HLFIR: acc.copyout accPtr(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>) bounds(%{{.*}}) to varPtr(%[[ADECL]]#1 : !fir.ref<!fir.array<100xi32>>) {name = "a"}
! ALL: return
Expand Down Expand Up @@ -178,9 +178,9 @@ subroutine acc_declare_device_resident(a)
! HLFIR: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) {acc.declare = #acc.declare<dataClause = acc_declare_device_resident>, uniq_name = "_QMacc_declareFacc_declare_device_residentEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
! FIR: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]] : !fir.ref<!fir.array<100xi32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
! HLFIR: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]]#1 : !fir.ref<!fir.array<100xi32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
! ALL: acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>)
! ALL: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>)
! ALL: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32)
! ALL: acc.declare_exit dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>)
! ALL: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>)
! ALL: acc.delete accPtr(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>) bounds(%{{.*}}) {dataClause = #acc<data_clause acc_declare_device_resident>, name = "a"}

subroutine acc_declare_device_resident2()
Expand All @@ -195,8 +195,8 @@ subroutine acc_declare_device_resident2()
! HLFIR: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare<dataClause = acc_declare_device_resident>, uniq_name = "_QMacc_declareFacc_declare_device_resident2Edataparam"} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
! FIR: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]] : !fir.ref<!fir.array<100xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<100xf32>> {name = "dataparam"}
! HLFIR: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]]#1 : !fir.ref<!fir.array<100xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<100xf32>> {name = "dataparam"}
! ALL: acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xf32>>)
! ALL: acc.declare_exit dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xf32>>)
! ALL: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xf32>>)
! ALL: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xf32>>)
! ALL: acc.delete accPtr(%[[DEVICERES]] : !fir.ref<!fir.array<100xf32>>) bounds(%{{.*}}) {dataClause = #acc<data_clause acc_declare_device_resident>, name = "dataparam"}

subroutine acc_declare_link2()
Expand Down Expand Up @@ -234,10 +234,10 @@ function acc_declare_in_func()

! ALL-LABEL: func.func @_QMacc_declarePacc_declare_in_func() -> f32 {
! HLFIR: %[[DEVICE_RESIDENT:.*]] = acc.declare_device_resident varPtr(%{{.*}}#1 : !fir.ref<!fir.array<1024xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<1024xf32>> {name = "a"}
! HLFIR: acc.declare_enter dataOperands(%[[DEVICE_RESIDENT]] : !fir.ref<!fir.array<1024xf32>>)
! HLFIR: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICE_RESIDENT]] : !fir.ref<!fir.array<1024xf32>>)

! HLFIR: %[[LOAD:.*]] = fir.load %{{.*}}#1 : !fir.ref<f32>
! HLFIR: acc.declare_exit dataOperands(%[[DEVICE_RESIDENT]] : !fir.ref<!fir.array<1024xf32>>)
! HLFIR: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVICE_RESIDENT]] : !fir.ref<!fir.array<1024xf32>>)
! HLFIR: acc.delete accPtr(%[[DEVICE_RESIDENT]] : !fir.ref<!fir.array<1024xf32>>) bounds(%6) {dataClause = #acc<data_clause acc_declare_device_resident>, name = "a"}
! HLFIR: return %[[LOAD]] : f32
! ALL: }
Expand All @@ -254,10 +254,10 @@ function acc_declare_in_func2(i)
! HLFIR: %[[ALLOCA_A:.*]] = fir.alloca !fir.array<1024xf32> {bindc_name = "a", uniq_name = "_QMacc_declareFacc_declare_in_func2Ea"}
! HLFIR: %[[DECL_A:.*]]:2 = hlfir.declare %[[ALLOCA_A]](%{{.*}}) {acc.declare = #acc.declare<dataClause = acc_create>, uniq_name = "_QMacc_declareFacc_declare_in_func2Ea"} : (!fir.ref<!fir.array<1024xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xf32>>, !fir.ref<!fir.array<1024xf32>>)
! HLFIR: %[[CREATE:.*]] = acc.create varPtr(%[[DECL_A]]#1 : !fir.ref<!fir.array<1024xf32>>) bounds(%7) -> !fir.ref<!fir.array<1024xf32>> {name = "a"}
! HLFIR: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<1024xf32>>)
! HLFIR: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<1024xf32>>)
! HLFIR: cf.br ^bb1
! HLFIR: ^bb1:
! HLFIR: acc.declare_exit dataOperands(%[[CREATE]] : !fir.ref<!fir.array<1024xf32>>)
! HLFIR: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref<!fir.array<1024xf32>>)
! HLFIR: acc.delete accPtr(%[[CREATE]] : !fir.ref<!fir.array<1024xf32>>) bounds(%7) {dataClause = #acc<data_clause acc_create>, name = "a"}
! ALL: return %{{.*}} : f32
! ALL: }
Expand Down
1 change: 0 additions & 1 deletion libcxx/include/deque
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,6 @@ public:
// For more details, see the "Using libc++" documentation page or
// the documentation for __sanitizer_annotate_contiguous_container.
#if !defined(_LIBCPP_HAS_NO_ASAN)
// TODO LLVM18: Remove the special-casing
_LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container(
const void* __beg,
const void* __end,
Expand Down
6 changes: 3 additions & 3 deletions libcxx/test/std/experimental/simd/test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef TEST_UTIL_H
#define TEST_UTIL_H
#ifndef LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
#define LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H

#include <algorithm>
#include <array>
Expand Down Expand Up @@ -78,4 +78,4 @@ void assert_simd_mask_values_equal(const ex::simd_mask<T, SimdAbi>& origin_mask,
assert(origin_mask[i] == expected_value[i]);
}

#endif // TEST_UTIL_H
#endif // LIBCXX_TEST_STD_EXPERIMENTAL_SIMD_TEST_UTILS_H
4 changes: 2 additions & 2 deletions libcxx/utils/libcxx/test/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def getStdFlag(cfg, std):
),
actions=lambda std: [
AddFeature(std),
AddSubstitution("%{cxx_std}", re.sub("\+", "x", std)),
AddSubstitution("%{cxx_std}", re.sub(r"\+", "x", std)),
AddCompileFlag(lambda cfg: getStdFlag(cfg, std)),
],
),
Expand Down Expand Up @@ -187,7 +187,7 @@ def getStdFlag(cfg, std):
AddFeature("stdlib={}".format(stdlib)),
# Also add an umbrella feature 'stdlib=libc++' for all flavors of libc++, to simplify
# the test suite.
AddFeature("stdlib=libc++") if re.match(".+-libc\+\+", stdlib) else None,
AddFeature("stdlib=libc++") if re.match(r".+-libc\+\+", stdlib) else None,
],
),
),
Expand Down
5 changes: 0 additions & 5 deletions libcxxabi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ else()
set(LIBCXXABI_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/c++/v1")
endif()

# TODO: Remove this after branching for LLVM 15
if(LIBCXXABI_SYSROOT OR LIBCXXABI_TARGET_TRIPLE OR LIBCXXABI_GCC_TOOLCHAIN)
message(WARNING "LIBCXXABI_SYSROOT, LIBCXXABI_TARGET_TRIPLE and LIBCXXABI_GCC_TOOLCHAIN are not supported anymore, please use the native CMake equivalents instead")
endif()

set(LIBCXXABI_LIBCXX_LIBRARY_PATH "" CACHE PATH "The path to libc++ library.")
set(LIBCXXABI_LIBRARY_VERSION "1.0" CACHE STRING
"Version of libc++abi. This will be reflected in the name of the shared \
Expand Down
5 changes: 0 additions & 5 deletions libunwind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,6 @@ cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY
"Install the shared libunwind library." ON
"LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF)

# TODO: Remove this after branching for LLVM 15
if(LIBUNWIND_SYSROOT OR LIBUNWIND_TARGET_TRIPLE OR LIBUNWIND_GCC_TOOLCHAIN)
message(WARNING "LIBUNWIND_SYSROOT, LIBUNWIND_TARGET_TRIPLE and LIBUNWIND_GCC_TOOLCHAIN are not supported anymore, please use the native CMake equivalents instead")
endif()

if(MINGW)
set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-mingw.cfg.in")
elseif (LIBUNWIND_ENABLE_SHARED)
Expand Down
70 changes: 41 additions & 29 deletions lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ class Writer {
void writeBuildId();
void writePEChecksum();
void sortSections();
void sortExceptionTable();
template <typename T> void sortExceptionTable(Chunk *first, Chunk *last);
void sortExceptionTables();
void sortCRTSectionChunks(std::vector<Chunk *> &chunks);
void addSyntheticIdata();
void sortBySectionOrder(std::vector<Chunk *> &chunks);
Expand Down Expand Up @@ -751,7 +752,7 @@ void Writer::run() {
}
writeSections();
prepareLoadConfig();
sortExceptionTable();
sortExceptionTables();

// Fix up the alignment in the TLS Directory's characteristic field,
// if a specific alignment value is needed
Expand Down Expand Up @@ -2164,41 +2165,52 @@ void Writer::writeBuildId() {
}

// Sort .pdata section contents according to PE/COFF spec 5.5.
void Writer::sortExceptionTable() {
if (!firstPdata)
return;
llvm::TimeTraceScope timeScope("Sort exception table");
template <typename T>
void Writer::sortExceptionTable(Chunk *first, Chunk *last) {
// We assume .pdata contains function table entries only.
auto bufAddr = [&](Chunk *c) {
OutputSection *os = ctx.getOutputSection(c);
return buffer->getBufferStart() + os->getFileOff() + c->getRVA() -
os->getRVA();
};
uint8_t *begin = bufAddr(firstPdata);
uint8_t *end = bufAddr(lastPdata) + lastPdata->getSize();
if (ctx.config.machine == AMD64) {
struct Entry { ulittle32_t begin, end, unwind; };
if ((end - begin) % sizeof(Entry) != 0) {
fatal("unexpected .pdata size: " + Twine(end - begin) +
" is not a multiple of " + Twine(sizeof(Entry)));
}
parallelSort(
MutableArrayRef<Entry>((Entry *)begin, (Entry *)end),
[](const Entry &a, const Entry &b) { return a.begin < b.begin; });
return;
uint8_t *begin = bufAddr(first);
uint8_t *end = bufAddr(last) + last->getSize();
if ((end - begin) % sizeof(T) != 0) {
fatal("unexpected .pdata size: " + Twine(end - begin) +
" is not a multiple of " + Twine(sizeof(T)));
}
if (ctx.config.machine == ARMNT || ctx.config.machine == ARM64) {
struct Entry { ulittle32_t begin, unwind; };
if ((end - begin) % sizeof(Entry) != 0) {
fatal("unexpected .pdata size: " + Twine(end - begin) +
" is not a multiple of " + Twine(sizeof(Entry)));
}
parallelSort(
MutableArrayRef<Entry>((Entry *)begin, (Entry *)end),
[](const Entry &a, const Entry &b) { return a.begin < b.begin; });
return;

parallelSort(MutableArrayRef<T>(reinterpret_cast<T *>(begin),
reinterpret_cast<T *>(end)),
[](const T &a, const T &b) { return a.begin < b.begin; });
}

// Sort .pdata section contents according to PE/COFF spec 5.5.
void Writer::sortExceptionTables() {
llvm::TimeTraceScope timeScope("Sort exception table");

struct EntryX64 {
ulittle32_t begin, end, unwind;
};
struct EntryArm {
ulittle32_t begin, unwind;
};

switch (ctx.config.machine) {
case AMD64:
if (firstPdata)
sortExceptionTable<EntryX64>(firstPdata, lastPdata);
break;
case ARMNT:
case ARM64:
if (firstPdata)
sortExceptionTable<EntryArm>(firstPdata, lastPdata);
break;
default:
if (firstPdata)
lld::errs() << "warning: don't know how to handle .pdata.\n";
break;
}
lld::errs() << "warning: don't know how to handle .pdata.\n";
}

// The CRT section contains, among other things, the array of function
Expand Down
10 changes: 5 additions & 5 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ static std::string createFileLineMsg(StringRef path, unsigned line) {

template <class ELFT>
static std::string getSrcMsgAux(ObjFile<ELFT> &file, const Symbol &sym,
InputSectionBase &sec, uint64_t offset) {
const InputSectionBase &sec, uint64_t offset) {
// In DWARF, functions and variables are stored to different places.
// First, look up a function for a given offset.
if (std::optional<DILineInfo> info = file.getDILineInfo(&sec, offset))
Expand All @@ -363,7 +363,7 @@ static std::string getSrcMsgAux(ObjFile<ELFT> &file, const Symbol &sym,
return std::string(file.sourceFile);
}

std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec,
std::string InputFile::getSrcMsg(const Symbol &sym, const InputSectionBase &sec,
uint64_t offset) {
if (kind() != ObjKind)
return "";
Expand Down Expand Up @@ -474,8 +474,8 @@ ObjFile<ELFT>::getVariableLoc(StringRef name) {
// Returns source line information for a given offset
// using DWARF debug info.
template <class ELFT>
std::optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
uint64_t offset) {
std::optional<DILineInfo>
ObjFile<ELFT>::getDILineInfo(const InputSectionBase *s, uint64_t offset) {
// Detect SectionIndex for specified section.
uint64_t sectionIndex = object::SectionedAddress::UndefSection;
ArrayRef<InputSectionBase *> sections = s->file->getSections();
Expand Down Expand Up @@ -1822,7 +1822,7 @@ template <class ELFT> void ObjFile<ELFT>::parseLazy() {
}
}

bool InputFile::shouldExtractForCommon(StringRef name) {
bool InputFile::shouldExtractForCommon(StringRef name) const {
if (isa<BitcodeFile>(this))
return isBitcodeNonCommonDef(mb, name, archiveName);

Expand Down
7 changes: 4 additions & 3 deletions lld/ELF/InputFiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class InputFile {

// Check if a non-common symbol should be extracted to override a common
// definition.
bool shouldExtractForCommon(StringRef name);
bool shouldExtractForCommon(StringRef name) const;

// .got2 in the current file. This is used by PPC32 -fPIC/-fPIE to compute
// offsets in PLT call stubs.
Expand Down Expand Up @@ -133,7 +133,7 @@ class InputFile {
// True if this is an argument for --just-symbols. Usually false.
bool justSymbols = false;

std::string getSrcMsg(const Symbol &sym, InputSectionBase &sec,
std::string getSrcMsg(const Symbol &sym, const InputSectionBase &sec,
uint64_t offset);

// On PPC64 we need to keep track of which files contain small code model
Expand Down Expand Up @@ -255,7 +255,8 @@ template <class ELFT> class ObjFile : public ELFFileBase {
return getSymbol(symIndex);
}

std::optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t);
std::optional<llvm::DILineInfo> getDILineInfo(const InputSectionBase *,
uint64_t);
std::optional<std::pair<std::string, unsigned>>
getVariableLoc(StringRef name);

Expand Down
10 changes: 6 additions & 4 deletions lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ InputSection *InputSectionBase::getLinkOrderDep() const {
}

// Find a symbol that encloses a given location.
Defined *InputSectionBase::getEnclosingSymbol(uint64_t offset, uint8_t type) {
Defined *InputSectionBase::getEnclosingSymbol(uint64_t offset,
uint8_t type) const {
for (Symbol *b : file->getSymbols())
if (Defined *d = dyn_cast<Defined>(b))
if (d->section == this && d->value <= offset &&
Expand All @@ -252,7 +253,7 @@ Defined *InputSectionBase::getEnclosingSymbol(uint64_t offset, uint8_t type) {
}

// Returns an object file location string. Used to construct an error message.
std::string InputSectionBase::getLocation(uint64_t offset) {
std::string InputSectionBase::getLocation(uint64_t offset) const {
std::string secAndOffset =
(name + "+0x" + Twine::utohexstr(offset) + ")").str();

Expand All @@ -273,7 +274,8 @@ std::string InputSectionBase::getLocation(uint64_t offset) {
// foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42)
//
// Returns an empty string if there's no way to get line info.
std::string InputSectionBase::getSrcMsg(const Symbol &sym, uint64_t offset) {
std::string InputSectionBase::getSrcMsg(const Symbol &sym,
uint64_t offset) const {
return file->getSrcMsg(sym, *this, offset);
}

Expand All @@ -286,7 +288,7 @@ std::string InputSectionBase::getSrcMsg(const Symbol &sym, uint64_t offset) {
// or
//
// path/to/foo.o:(function bar) in archive path/to/bar.a
std::string InputSectionBase::getObjMsg(uint64_t off) {
std::string InputSectionBase::getObjMsg(uint64_t off) const {
std::string filename = std::string(file->getName());

std::string archive;
Expand Down
10 changes: 5 additions & 5 deletions lld/ELF/InputSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,15 @@ class InputSectionBase : public SectionBase {

// Get a symbol that encloses this offset from within the section. If type is
// not zero, return a symbol with the specified type.
Defined *getEnclosingSymbol(uint64_t offset, uint8_t type = 0);
Defined *getEnclosingFunction(uint64_t offset) {
Defined *getEnclosingSymbol(uint64_t offset, uint8_t type = 0) const;
Defined *getEnclosingFunction(uint64_t offset) const {
return getEnclosingSymbol(offset, llvm::ELF::STT_FUNC);
}

// Returns a source location string. Used to construct an error message.
std::string getLocation(uint64_t offset);
std::string getSrcMsg(const Symbol &sym, uint64_t offset);
std::string getObjMsg(uint64_t offset);
std::string getLocation(uint64_t offset) const;
std::string getSrcMsg(const Symbol &sym, uint64_t offset) const;
std::string getObjMsg(uint64_t offset) const;

// Each section knows how to relocate itself. These functions apply
// relocations, assuming that Buf points to this section's copy in
Expand Down
59 changes: 59 additions & 0 deletions lld/test/ELF/lto/arm.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
; REQUIRES: arm
;; Test we can infer the e_machine value EM_ARM from a bitcode file.

; RUN: split-file %s %t

; RUN: llvm-as %t/arm.ll -o %t/arm.o
; RUN: ld.lld %t/arm.o -o %t/arm
; RUN: llvm-readobj -h %t/arm | FileCheck %s --check-prefix=ARM
; RUN: llvm-as %t/armeb.ll -o %t/armeb.o
; RUN: not ld.lld %t/armeb.o -o %t/armeb

; RUN: llvm-as %t/thumb.ll -o %t/thumb.o
; RUN: ld.lld %t/thumb.o -o %t/thumb
; RUN: llvm-readobj -h %t/thumb | FileCheck %s --check-prefix=THUMB
; RUN: llvm-as %t/thumbeb.ll -o %t/thumbeb.o
; RUN: not ld.lld %t/thumbeb.o -o %t/thumbeb

; ARM: Class: 32-bit
; ARM: DataEncoding: LittleEndian
; ARM: Machine: EM_ARM (
; ARMEB: Class: 32-bit
; ARMEB: DataEncoding: BigEndian
; ARMEB: Machine: EM_ARM (

; THUMB: Class: 32-bit
; THUMB: DataEncoding: LittleEndian
; THUMB: Machine: EM_ARM (

;--- arm.ll
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv7-linux-musleabi"

define void @_start() {
ret void
}

;--- thumb.ll
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbv8m.base-none-unknown-gnueabi"

define void @_start() {
ret void
}

;--- armeb.ll
target datalayout = "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armebv7-unknown-linux-musleabi"

define void @_start() {
ret void
}

;--- thumbeb.ll
target datalayout = "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "thumbebv8m.base-none-unknown-gnueabi"

define void @_start() {
ret void
}
8 changes: 8 additions & 0 deletions lldb/include/lldb/Expression/UserExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,14 @@ class UserExpression : public Expression {
/// expression. Text() should contain the definition of this function.
const char *FunctionName() override { return "$__lldb_expr"; }

/// Returns whether the call to Parse on this user expression is cacheable.
/// This function exists to provide an escape hatch for supporting languages
/// where parsing an expression in the exact same context is unsafe. For
/// example, languages where generic functions aren't monomorphized, but
/// implement some other mechanism to represent generic values, may be unsafe
/// to cache, as the concrete type substitution may be different in every
/// expression evaluation.
virtual bool IsParseCacheable() { return true; }
/// Return the language that should be used when parsing. To use the
/// default, return eLanguageTypeUnknown.
lldb::LanguageType Language() const override { return m_language; }
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Breakpoint/BreakpointLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
DiagnosticManager diagnostics;

if (condition_hash != m_condition_hash || !m_user_expression_sp ||
!m_user_expression_sp->IsParseCacheable() ||
!m_user_expression_sp->MatchesContext(exe_ctx)) {
LanguageType language = eLanguageTypeUnknown;
// See if we can figure out the language from the frame, otherwise use the
Expand Down
8 changes: 3 additions & 5 deletions lldb/source/Commands/CommandObjectTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,7 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
error = process_sp->LoadCore();

if (error.Fail()) {
result.AppendError(
error.AsCString("can't find plug-in for core file"));
result.AppendError(error.AsCString("unknown core file format"));
return;
} else {
result.AppendMessageWithFormatv(
Expand All @@ -447,9 +446,8 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
on_error.release();
}
} else {
result.AppendErrorWithFormatv(
"Unable to find process plug-in for core file '{0}'\n",
core_file.GetPath());
result.AppendErrorWithFormatv("Unknown core file format '{0}'\n",
core_file.GetPath());
}
} else {
result.AppendMessageWithFormat(
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Core/IOHandlerCursesGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3178,13 +3178,13 @@ class TargetCreateFormDelegate : public FormDelegate {
m_debugger.GetListener(), llvm::StringRef(), &core_file_spec, false));

if (!process_sp) {
SetError("Unable to find process plug-in for core file!");
SetError("Unknown core file format!");
return;
}

Status status = process_sp->LoadCore();
if (status.Fail()) {
SetError("Can't find plug-in for core file!");
SetError("Unknown core file format!");
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/commands/target/basic/TestTargetCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ def test_target_create_invalid_core_file(self):
self.expect(
"target create -c '" + invalid_core_path + "'",
error=True,
substrs=["Unable to find process plug-in for core file '"],
substrs=["Unknown core file format '"],
)

# Write only files don't seem to be supported on Windows.
Expand Down
1 change: 1 addition & 0 deletions llvm/cmake/modules/AddLLVM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,7 @@ if(NOT LLVM_TOOLCHAIN_TOOLS)
llvm-ar
llvm-cov
llvm-cxxfilt
llvm-dlltool
llvm-dwp
llvm-ranlib
llvm-lib
Expand Down
13 changes: 7 additions & 6 deletions llvm/docs/CommandGuide/llvm-exegesis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ SUPPORTED PLATFORMS
only), MIPS, and PowerPC (PowerPC64LE only) on Linux for benchmarking. Not all
benchmarking functionality is guaranteed to work on every platform.
:program:`llvm-exegesis` also has a separate analysis mode that is supported
on every platform on which LLVM is.
on every platform that LLVM is.

SNIPPET ANNOTATIONS
-------------------

:program:`llvm-exegesis` supports benchmarking arbitrary snippets of assembly.
However, benchmarking these snippets often requires some setup so that they
can execute properly. :program:`llvm-exegesis` has two annotations and some
can execute properly. :program:`llvm-exegesis` has four annotations and some
additional utilities to help with setup so that snippets can be benchmarked
properly.

Expand All @@ -69,10 +69,11 @@ properly.
specifying memory definitions that can later be mapped into the execution
process of a snippet with the `LLVM-EXEGESIS-MEM-MAP` annotation. Each
value is named using the `<value name>` argument so that it can be referenced
later within a map annotation. The size is specified in bytes the the value
is taken in hexadecimal. If the size of the value is less than the specified
size, the value will be repeated until it fills the entire section of memory.
Using this annotation requires using the subprocess execution mode.
later within a map annotation. The size is specified in a decimal number of
bytes and the value is given in hexadecimal. If the size of the value is less
than the specified size, the value will be repeated until it fills the entire
section of memory. Using this annotation requires using the subprocess execution
mode.
* `LLVM-EXEGESIS-MEM-MAP <value name> <address>` - This annotation allows for
mapping previously defined memory definitions into the execution context of a
process. The value name refers to a previously defined memory definition and
Expand Down
2 changes: 2 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ Changes to the AMDGPU Backend

* Implemented :ref:`llvm.get.rounding <int_get_rounding>`

* Added support for Cortex-A520, Cortex-A720 and Cortex-X4 CPUs.

Changes to the ARM Backend
--------------------------

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm-c/Orc.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP);
* Intern a string in the ExecutionSession's SymbolStringPool and return a
* reference to it. This increments the ref-count of the pool entry, and the
* returned value should be released once the client is done with it by
* calling LLVMOrReleaseSymbolStringPoolEntry.
* calling LLVMOrcReleaseSymbolStringPoolEntry.
*
* Since strings are uniqued within the SymbolStringPool
* LLVMOrcSymbolStringPoolEntryRefs can be compared by value to test string
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/Analysis/ScalarEvolution.h
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,10 @@ class ScalarEvolution {
/// def-use chain linking it to a loop.
void forgetValue(Value *V);

/// Forget LCSSA phi node V of loop L to which a new predecessor was added,
/// such that it may no longer be trivial.
void forgetLcssaPhiWithNewPredecessor(Loop *L, PHINode *V);

/// Called when the client has changed the disposition of values in
/// this loop.
///
Expand Down
115 changes: 70 additions & 45 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ class DITypeRefArray {
/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*,
/// defined in llvm/BinaryFormat/Dwarf.h). Called \a DINode because it's
/// potentially used for non-DWARF output.
///
/// Uses the SubclassData16 Metadata slot.
class DINode : public MDNode {
friend class LLVMContextImpl;
friend class MDNode;
Expand Down Expand Up @@ -227,6 +229,8 @@ class DINode : public MDNode {
/// (possibly empty) null-separated \a MDString header that contains arbitrary
/// fields. The remaining operands are \a dwarf_operands(), and are pointers
/// to other metadata.
///
/// Uses the SubclassData32 Metadata slot.
class GenericDINode : public DINode {
friend class LLVMContextImpl;
friend class MDNode;
Expand Down Expand Up @@ -695,12 +699,13 @@ std::optional<StringRef> DIScope::getSource() const {
/// TODO: Remove the hardcoded name and context, since many types don't use
/// them.
/// TODO: Split up flags.
///
/// Uses the SubclassData32 Metadata slot.
class DIType : public DIScope {
unsigned Line;
DIFlags Flags;
uint64_t SizeInBits;
uint64_t OffsetInBits;
uint32_t AlignInBits;

protected:
DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
Expand All @@ -716,7 +721,7 @@ class DIType : public DIScope {
this->Line = Line;
this->Flags = Flags;
this->SizeInBits = SizeInBits;
this->AlignInBits = AlignInBits;
this->SubclassData32 = AlignInBits;
this->OffsetInBits = OffsetInBits;
}

Expand All @@ -735,7 +740,7 @@ class DIType : public DIScope {

unsigned getLine() const { return Line; }
uint64_t getSizeInBits() const { return SizeInBits; }
uint32_t getAlignInBits() const { return AlignInBits; }
uint32_t getAlignInBits() const { return SubclassData32; }
uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }
uint64_t getOffsetInBits() const { return OffsetInBits; }
DIFlags getFlags() const { return Flags; }
Expand Down Expand Up @@ -1389,13 +1394,13 @@ class DICompileUnit : public DIScope {

private:
unsigned SourceLanguage;
bool IsOptimized;
unsigned RuntimeVersion;
unsigned EmissionKind;
uint64_t DWOId;
unsigned EmissionKind;
unsigned NameTableKind;
bool IsOptimized;
bool SplitDebugInlining;
bool DebugInfoForProfiling;
unsigned NameTableKind;
bool RangesBaseAddress;

DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage,
Expand Down Expand Up @@ -1876,6 +1881,10 @@ class DISubprogram : public DILocalScope {
/// Debug location.
///
/// A debug location in source code, used for debug info and otherwise.
///
/// Uses the SubclassData1, SubclassData16 and SubclassData32
/// Metadata slots.

class DILocation : public MDNode {
friend class LLVMContextImpl;
friend class MDNode;
Expand Down Expand Up @@ -2161,17 +2170,20 @@ class DILexicalBlockBase : public DILocalScope {
}
};

/// Debug lexical block.
///
/// Uses the SubclassData32 Metadata slot.
class DILexicalBlock : public DILexicalBlockBase {
friend class LLVMContextImpl;
friend class MDNode;

unsigned Line;
uint16_t Column;

DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line,
unsigned Column, ArrayRef<Metadata *> Ops)
: DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line),
: DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops),
Column(Column) {
SubclassData32 = Line;
assert(Column < (1u << 16) && "Expected 16-bit column");
}
~DILexicalBlock() = default;
Expand Down Expand Up @@ -2206,7 +2218,7 @@ class DILexicalBlock : public DILexicalBlockBase {

TempDILexicalBlock clone() const { return cloneImpl(); }

unsigned getLine() const { return Line; }
unsigned getLine() const { return SubclassData32; }
unsigned getColumn() const { return Column; }

static bool classof(const Metadata *MD) {
Expand All @@ -2218,12 +2230,11 @@ class DILexicalBlockFile : public DILexicalBlockBase {
friend class LLVMContextImpl;
friend class MDNode;

unsigned Discriminator;

DILexicalBlockFile(LLVMContext &C, StorageType Storage,
unsigned Discriminator, ArrayRef<Metadata *> Ops)
: DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops),
Discriminator(Discriminator) {}
: DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops) {
SubclassData32 = Discriminator;
}
~DILexicalBlockFile() = default;

static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope,
Expand Down Expand Up @@ -2255,7 +2266,7 @@ class DILexicalBlockFile : public DILexicalBlockBase {
(Scope, File, Discriminator))

TempDILexicalBlockFile clone() const { return cloneImpl(); }
unsigned getDiscriminator() const { return Discriminator; }
unsigned getDiscriminator() const { return SubclassData32; }

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DILexicalBlockFileKind;
Expand Down Expand Up @@ -2338,12 +2349,13 @@ DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const {
return std::nullopt;
}

/// Debug lexical block.
///
/// Uses the SubclassData1 Metadata slot.
class DINamespace : public DIScope {
friend class LLVMContextImpl;
friend class MDNode;

unsigned ExportSymbols : 1;

DINamespace(LLVMContext &Context, StorageType Storage, bool ExportSymbols,
ArrayRef<Metadata *> Ops);
~DINamespace() = default;
Expand Down Expand Up @@ -2373,7 +2385,7 @@ class DINamespace : public DIScope {

TempDINamespace clone() const { return cloneImpl(); }

bool getExportSymbols() const { return ExportSymbols; }
bool getExportSymbols() const { return SubclassData1; }
DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
StringRef getName() const { return getStringOperand(2); }

Expand All @@ -2387,11 +2399,11 @@ class DINamespace : public DIScope {

/// Represents a module in the programming language, for example, a Clang
/// module, or a Fortran module.
///
/// Uses the SubclassData1 and SubclassData32 Metadata slots.
class DIModule : public DIScope {
friend class LLVMContextImpl;
friend class MDNode;
unsigned LineNo;
bool IsDecl;

DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo,
bool IsDecl, ArrayRef<Metadata *> Ops);
Expand Down Expand Up @@ -2443,8 +2455,8 @@ class DIModule : public DIScope {
StringRef getConfigurationMacros() const { return getStringOperand(3); }
StringRef getIncludePath() const { return getStringOperand(4); }
StringRef getAPINotesFile() const { return getStringOperand(5); }
unsigned getLineNo() const { return LineNo; }
bool getIsDecl() const { return IsDecl; }
unsigned getLineNo() const { return SubclassData32; }
bool getIsDecl() const { return SubclassData1; }

Metadata *getRawScope() const { return getOperand(1); }
MDString *getRawName() const { return getOperandAs<MDString>(2); }
Expand All @@ -2460,13 +2472,15 @@ class DIModule : public DIScope {
};

/// Base class for template parameters.
///
/// Uses the SubclassData1 Metadata slot.
class DITemplateParameter : public DINode {
protected:
bool IsDefault;

DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage,
unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops)
: DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {}
: DINode(Context, ID, Storage, Tag, Ops) {
SubclassData1 = IsDefault;
}
~DITemplateParameter() = default;

public:
Expand All @@ -2475,7 +2489,7 @@ class DITemplateParameter : public DINode {

MDString *getRawName() const { return getOperandAs<MDString>(0); }
Metadata *getRawType() const { return getOperand(1); }
bool isDefault() const { return IsDefault; }
bool isDefault() const { return SubclassData1; }

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DITemplateTypeParameterKind ||
Expand Down Expand Up @@ -2572,9 +2586,10 @@ class DITemplateValueParameter : public DITemplateParameter {
};

/// Base class for variables.
///
/// Uses the SubclassData32 Metadata slot.
class DIVariable : public DINode {
unsigned Line;
uint32_t AlignInBits;

protected:
DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, signed Line,
Expand All @@ -2587,7 +2602,7 @@ class DIVariable : public DINode {
StringRef getName() const { return getStringOperand(1); }
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
DIType *getType() const { return cast_or_null<DIType>(getRawType()); }
uint32_t getAlignInBits() const { return AlignInBits; }
uint32_t getAlignInBits() const { return SubclassData32; }
uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }
/// Determines the size of the variable's type.
std::optional<uint64_t> getSizeInBits() const;
Expand Down Expand Up @@ -3161,9 +3176,10 @@ class DIGlobalVariable : public DIVariable {
}
};

/// Debug common block.
///
/// Uses the SubclassData32 Metadata slot.
class DICommonBlock : public DIScope {
unsigned LineNo;

friend class LLVMContextImpl;
friend class MDNode;

Expand Down Expand Up @@ -3205,7 +3221,7 @@ class DICommonBlock : public DIScope {
}
StringRef getName() const { return getStringOperand(2); }
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
unsigned getLineNo() const { return LineNo; }
unsigned getLineNo() const { return SubclassData32; }

Metadata *getRawScope() const { return getOperand(0); }
Metadata *getRawDecl() const { return getOperand(1); }
Expand Down Expand Up @@ -3310,12 +3326,11 @@ class DILocalVariable : public DIVariable {

/// Label.
///
/// Uses the SubclassData32 Metadata slot.
class DILabel : public DINode {
friend class LLVMContextImpl;
friend class MDNode;

unsigned Line;

DILabel(LLVMContext &C, StorageType Storage, unsigned Line,
ArrayRef<Metadata *> Ops);
~DILabel() = default;
Expand Down Expand Up @@ -3353,7 +3368,7 @@ class DILabel : public DINode {
DILocalScope *getScope() const {
return cast_or_null<DILocalScope>(getRawScope());
}
unsigned getLine() const { return Line; }
unsigned getLine() const { return SubclassData32; }
StringRef getName() const { return getStringOperand(1); }
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }

Expand Down Expand Up @@ -3455,15 +3470,17 @@ class DIObjCProperty : public DINode {
};

/// An imported module (C++ using directive or similar).
///
/// Uses the SubclassData32 Metadata slot.
class DIImportedEntity : public DINode {
friend class LLVMContextImpl;
friend class MDNode;

unsigned Line;

DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag,
unsigned Line, ArrayRef<Metadata *> Ops)
: DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {}
: DINode(C, DIImportedEntityKind, Storage, Tag, Ops) {
SubclassData32 = Line;
}
~DIImportedEntity() = default;

static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
Expand Down Expand Up @@ -3499,7 +3516,7 @@ class DIImportedEntity : public DINode {

TempDIImportedEntity clone() const { return cloneImpl(); }

unsigned getLine() const { return Line; }
unsigned getLine() const { return SubclassData32; }
DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
DINode *getEntity() const { return cast_or_null<DINode>(getRawEntity()); }
StringRef getName() const { return getStringOperand(2); }
Expand Down Expand Up @@ -3567,6 +3584,8 @@ class DIGlobalVariableExpression : public MDNode {
/// \c DW_MACINFO_*, defined in llvm/BinaryFormat/Dwarf.h). Called \a
/// DIMacroNode
/// because it's potentially used for non-DWARF output.
///
/// Uses the SubclassData16 Metadata slot.
class DIMacroNode : public MDNode {
friend class LLVMContextImpl;
friend class MDNode;
Expand Down Expand Up @@ -3611,15 +3630,18 @@ class DIMacroNode : public MDNode {
}
};

/// Macro
///
/// Uses the SubclassData32 Metadata slot.
class DIMacro : public DIMacroNode {
friend class LLVMContextImpl;
friend class MDNode;

unsigned Line;

DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line,
ArrayRef<Metadata *> Ops)
: DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {}
: DIMacroNode(C, DIMacroKind, Storage, MIType, Ops) {
SubclassData32 = Line;
}
~DIMacro() = default;

static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line,
Expand Down Expand Up @@ -3649,7 +3671,7 @@ class DIMacro : public DIMacroNode {

TempDIMacro clone() const { return cloneImpl(); }

unsigned getLine() const { return Line; }
unsigned getLine() const { return SubclassData32; }

StringRef getName() const { return getStringOperand(0); }
StringRef getValue() const { return getStringOperand(1); }
Expand All @@ -3662,15 +3684,18 @@ class DIMacro : public DIMacroNode {
}
};

/// Macro file
///
/// Uses the SubclassData32 Metadata slot.
class DIMacroFile : public DIMacroNode {
friend class LLVMContextImpl;
friend class MDNode;

unsigned Line;

DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType,
unsigned Line, ArrayRef<Metadata *> Ops)
: DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {}
: DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops) {
SubclassData32 = Line;
}
~DIMacroFile() = default;

static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType,
Expand Down Expand Up @@ -3711,7 +3736,7 @@ class DIMacroFile : public DIMacroNode {
replaceOperandWith(1, Elements.get());
}

unsigned getLine() const { return Line; }
unsigned getLine() const { return SubclassData32; }
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }

DIMacroNodeArray getElements() const {
Expand Down
17 changes: 17 additions & 0 deletions llvm/include/llvm/TargetParser/AArch64TargetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,11 @@ inline constexpr CpuInfo CpuInfos[] = {
AArch64::AEK_PAUTH, AArch64::AEK_MTE, AArch64::AEK_SSBS,
AArch64::AEK_SVE, AArch64::AEK_SVE2, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FP16FML}))},
{"cortex-a520", ARMV9_2A,
(AArch64::ExtensionBitset(
{AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES}))},
{"cortex-a57", ARMV8A,
(AArch64::ExtensionBitset(
{AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC}))},
Expand Down Expand Up @@ -483,6 +488,12 @@ inline constexpr CpuInfo CpuInfos[] = {
AArch64::AEK_I8MM, AArch64::AEK_PREDRES, AArch64::AEK_PERFMON,
AArch64::AEK_PROFILE, AArch64::AEK_SVE, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_BF16, AArch64::AEK_FLAGM}))},
{"cortex-a720", ARMV9_2A,
(AArch64::ExtensionBitset(
{AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES,
AArch64::AEK_PROFILE}))},
{"cortex-r82", ARMV8R,
(AArch64::ExtensionBitset({AArch64::AEK_LSE}))},
{"cortex-x1", ARMV8_2A,
Expand All @@ -508,6 +519,12 @@ inline constexpr CpuInfo CpuInfos[] = {
AArch64::AEK_SVE2BITPERM, AArch64::AEK_SB, AArch64::AEK_PAUTH,
AArch64::AEK_FP16, AArch64::AEK_FP16FML, AArch64::AEK_PREDRES,
AArch64::AEK_FLAGM, AArch64::AEK_SSBS}))},
{"cortex-x4", ARMV9_2A,
(AArch64::ExtensionBitset(
{AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE,
AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM,
AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES,
AArch64::AEK_PROFILE}))},
{"neoverse-e1", ARMV8_2A,
(AArch64::ExtensionBitset(
{AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_DOTPROD,
Expand Down
8 changes: 1 addition & 7 deletions llvm/lib/Analysis/AssumptionCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,7 @@ findAffectedValues(CallBase *CI, TargetTransformInfo *TTI,
if (Pred == ICmpInst::ICMP_EQ) {
// For equality comparisons, we handle the case of bit inversion.
auto AddAffectedFromEq = [&AddAffected](Value *V) {
Value *A;
if (match(V, m_Not(m_Value(A)))) {
AddAffected(A);
V = A;
}

Value *B;
Value *A, *B;
// (A & B) or (A | B) or (A ^ B).
if (match(V, m_BitwiseLogic(m_Value(A), m_Value(B)))) {
AddAffected(A);
Expand Down
38 changes: 38 additions & 0 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8410,6 +8410,44 @@ void ScalarEvolution::forgetValue(Value *V) {
forgetMemoizedResults(ToForget);
}

void ScalarEvolution::forgetLcssaPhiWithNewPredecessor(Loop *L, PHINode *V) {
if (!isSCEVable(V->getType()))
return;

// If SCEV looked through a trivial LCSSA phi node, we might have SCEV's
// directly using a SCEVUnknown/SCEVAddRec defined in the loop. After an
// extra predecessor is added, this is no longer valid. Find all Unknowns and
// AddRecs defined in the loop and invalidate any SCEV's making use of them.
if (const SCEV *S = getExistingSCEV(V)) {
struct InvalidationRootCollector {
Loop *L;
SmallVector<const SCEV *, 8> Roots;

InvalidationRootCollector(Loop *L) : L(L) {}

bool follow(const SCEV *S) {
if (auto *SU = dyn_cast<SCEVUnknown>(S)) {
if (auto *I = dyn_cast<Instruction>(SU->getValue()))
if (L->contains(I))
Roots.push_back(S);
} else if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
if (L->contains(AddRec->getLoop()))
Roots.push_back(S);
}
return true;
}
bool isDone() const { return false; }
};

InvalidationRootCollector C(L);
visitAll(S, C);
forgetMemoizedResults(C.Roots);
}

// Also perform the normal invalidation.
forgetValue(V);
}

void ScalarEvolution::forgetLoopDispositions() { LoopDispositions.clear(); }

void ScalarEvolution::forgetBlockAndLoopDispositions(Value *V) {
Expand Down
5 changes: 0 additions & 5 deletions llvm/lib/Analysis/TrainingLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@

using namespace llvm;

// FIXME(mtrofin): remove the flag altogether
static cl::opt<bool>
UseSimpleLogger("tfutils-use-simplelogger", cl::init(true), cl::Hidden,
cl::desc("Output simple (non-protobuf) log."));

void Logger::writeHeader(std::optional<TensorSpec> AdviceSpec) {
json::OStream JOS(*OS);
JOS.object([&]() {
Expand Down
Loading